WinDebugger.cpp 362 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979109801098110982109831098410985109861098710988109891099010991109921099310994109951099610997109981099911000110011100211003110041100511006110071100811009110101101111012110131101411015110161101711018110191102011021110221102311024110251102611027110281102911030110311103211033110341103511036110371103811039110401104111042110431104411045110461104711048110491105011051110521105311054110551105611057110581105911060110611106211063110641106511066110671106811069110701107111072110731107411075110761107711078110791108011081110821108311084110851108611087110881108911090110911109211093110941109511096110971109811099111001110111102111031110411105111061110711108111091111011111111121111311114111151111611117111181111911120111211112211123111241112511126111271112811129111301113111132111331113411135111361113711138111391114011141111421114311144111451114611147111481114911150111511115211153111541115511156111571115811159111601116111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011201112021120311204112051120611207112081120911210112111121211213112141121511216112171121811219112201122111222112231122411225112261122711228112291123011231112321123311234112351123611237112381123911240112411124211243112441124511246112471124811249112501125111252112531125411255112561125711258112591126011261112621126311264112651126611267112681126911270112711127211273112741127511276112771127811279112801128111282112831128411285112861128711288112891129011291112921129311294112951129611297112981129911300113011130211303113041130511306113071130811309113101131111312113131131411315113161131711318113191132011321113221132311324113251132611327113281132911330113311133211333113341133511336113371133811339113401134111342113431134411345113461134711348113491135011351113521135311354113551135611357113581135911360113611136211363113641136511366113671136811369113701137111372113731137411375113761137711378113791138011381113821138311384113851138611387113881138911390113911139211393113941139511396113971139811399114001140111402114031140411405114061140711408114091141011411114121141311414114151141611417114181141911420114211142211423114241142511426114271142811429114301143111432114331143411435114361143711438114391144011441114421144311444114451144611447114481144911450114511145211453114541145511456114571145811459114601146111462114631146411465114661146711468114691147011471114721147311474114751147611477114781147911480114811148211483114841148511486114871148811489114901149111492114931149411495114961149711498114991150011501115021150311504115051150611507115081150911510115111151211513115141151511516115171151811519115201152111522115231152411525115261152711528115291153011531115321153311534115351153611537115381153911540115411154211543115441154511546115471154811549115501155111552115531155411555115561155711558115591156011561115621156311564115651156611567115681156911570115711157211573115741157511576115771157811579115801158111582115831158411585115861158711588115891159011591115921159311594115951159611597115981159911600116011160211603116041160511606116071160811609116101161111612116131161411615116161161711618116191162011621116221162311624116251162611627116281162911630116311163211633116341163511636116371163811639116401164111642116431164411645116461164711648116491165011651116521165311654116551165611657116581165911660116611166211663116641166511666116671166811669116701167111672116731167411675116761167711678116791168011681116821168311684116851168611687116881168911690116911169211693116941169511696116971169811699117001170111702117031170411705117061170711708117091171011711117121171311714117151171611717117181171911720117211172211723117241172511726117271172811729117301173111732117331173411735117361173711738117391174011741117421174311744117451174611747117481174911750117511175211753117541175511756117571175811759117601176111762117631176411765117661176711768117691177011771117721177311774117751177611777117781177911780117811178211783117841178511786117871178811789117901179111792117931179411795117961179711798117991180011801118021180311804118051180611807118081180911810118111181211813118141181511816118171181811819118201182111822118231182411825118261182711828118291183011831118321183311834118351183611837118381183911840118411184211843118441184511846118471184811849118501185111852118531185411855118561185711858118591186011861118621186311864118651186611867118681186911870118711187211873118741187511876118771187811879118801188111882118831188411885118861188711888118891189011891118921189311894118951189611897118981189911900119011190211903119041190511906119071190811909119101191111912119131191411915119161191711918119191192011921119221192311924119251192611927119281192911930119311193211933119341193511936119371193811939119401194111942119431194411945119461194711948119491195011951119521195311954119551195611957119581195911960119611196211963119641196511966119671196811969119701197111972119731197411975119761197711978119791198011981119821198311984119851198611987119881198911990119911199211993119941199511996119971199811999120001200112002120031200412005120061200712008120091201012011120121201312014120151201612017120181201912020120211202212023120241202512026120271202812029120301203112032120331203412035120361203712038120391204012041120421204312044120451204612047120481204912050120511205212053120541205512056120571205812059120601206112062120631206412065120661206712068120691207012071120721207312074120751207612077120781207912080120811208212083120841208512086120871208812089120901209112092120931209412095120961209712098120991210012101121021210312104121051210612107121081210912110121111211212113121141211512116121171211812119121201212112122121231212412125121261212712128121291213012131121321213312134121351213612137121381213912140121411214212143121441214512146121471214812149121501215112152121531215412155121561215712158121591216012161121621216312164121651216612167121681216912170121711217212173121741217512176121771217812179121801218112182121831218412185121861218712188121891219012191121921219312194121951219612197121981219912200122011220212203122041220512206122071220812209122101221112212122131221412215122161221712218122191222012221122221222312224122251222612227122281222912230122311223212233122341223512236122371223812239122401224112242122431224412245122461224712248122491225012251122521225312254122551225612257122581225912260122611226212263122641226512266122671226812269122701227112272122731227412275122761227712278122791228012281122821228312284122851228612287122881228912290122911229212293122941229512296122971229812299123001230112302123031230412305123061230712308123091231012311123121231312314123151231612317123181231912320123211232212323123241232512326123271232812329123301233112332123331233412335123361233712338123391234012341123421234312344123451234612347123481234912350123511235212353123541235512356123571235812359123601236112362123631236412365123661236712368123691237012371123721237312374123751237612377123781237912380123811238212383123841238512386123871238812389123901239112392123931239412395123961239712398123991240012401124021240312404124051240612407124081240912410124111241212413124141241512416124171241812419124201242112422124231242412425124261242712428124291243012431124321243312434124351243612437124381243912440124411244212443124441244512446124471244812449124501245112452124531245412455124561245712458124591246012461124621246312464124651246612467124681246912470124711247212473124741247512476124771247812479124801248112482124831248412485124861248712488124891249012491124921249312494
  1. #pragma warning(disable:4996)
  2. // TODO: Remove for 64-bit
  3. #pragma warning(disable:4244)
  4. #pragma warning(disable:4267)
  5. #define NTDDI_VERSION 0x06020000
  6. #include "WinDebugger.h"
  7. #include "CPU.h"
  8. #include "DbgModule.h"
  9. #include "DebugVisualizers.h"
  10. #include "MiniDumpDebugger.h"
  11. #include "X86.h"
  12. #include "BeefySysLib/Common.h"
  13. #include "BeefySysLib/util/PerfTimer.h"
  14. #include "BeefySysLib/util/BeefPerf.h"
  15. #include "BeefySysLib/util/CritSect.h"
  16. #include "BeefySysLib/util/UTF8.h"
  17. #include "BeefySysLib/FileStream.h"
  18. #include "BeefySysLib/FileHandleStream.h"
  19. #include <inttypes.h>
  20. #include <windows.h>
  21. #include "DbgExprEvaluator.h"
  22. #include "Compiler/BfSystem.h"
  23. #include "Compiler/BfParser.h"
  24. #include "Compiler/BfReducer.h"
  25. #include "Compiler/BfDemangler.h"
  26. #include "Compiler/BfPrinter.h"
  27. #include <Shlobj.h>
  28. #include "NetManager.h"
  29. #include "DebugManager.h"
  30. #include "X86Target.h"
  31. #include "HotHeap.h"
  32. #include "HotScanner.h"
  33. #include "Profiler.h"
  34. #include <float.h>
  35. #include <psapi.h>
  36. #if !defined BF32 || !defined BF_DBG_64
  37. #define STATUS_WX86_CONTINUE 0x4000001DL
  38. #define STATUS_WX86_SINGLE_STEP 0x4000001EL
  39. #define STATUS_WX86_BREAKPOINT 0x4000001FL
  40. #define STATUS_WX86_EXCEPTION_CONTINUE 0x40000020L
  41. #pragma pack(push, 1)
  42. struct HotJumpOp
  43. {
  44. uint8 mOpCode;
  45. int32 mRelTarget;
  46. };
  47. #pragma pack(pop)
  48. #include "BeefySysLib/util/AllocDebug.h"
  49. #include <limits>
  50. USING_NS_BF_DBG;
  51. static void FilterThreadName(String& name)
  52. {
  53. for (int i = 0; i < (int)name.length(); i++)
  54. {
  55. uint8 c = name[i];
  56. if (c == 0)
  57. {
  58. name.RemoveToEnd(i);
  59. return;
  60. }
  61. if (c < 32)
  62. {
  63. name.Remove(i);
  64. i--;
  65. continue;
  66. }
  67. }
  68. }
  69. //////////////////////////////////////////////////////////////////////////
  70. WdBreakpointCondition::~WdBreakpointCondition()
  71. {
  72. delete mDbgEvaluationContext;
  73. }
  74. //////////////////////////////////////////////////////////////////////////
  75. DbgEvaluationContext::DbgEvaluationContext(WinDebugger* winDebugger, DbgModule* dbgModule, const StringImpl& expr, DwFormatInfo* formatInfo, DbgTypedValue contextValue)
  76. {
  77. Init(winDebugger, dbgModule, expr, formatInfo, contextValue);
  78. }
  79. DbgEvaluationContext::DbgEvaluationContext(WinDebugger* winDebugger, DbgCompileUnit* dbgCompileUnit, const StringImpl& expr, DwFormatInfo* formatInfo, DbgTypedValue contextValue)
  80. {
  81. DbgModule* dbgModule = NULL;
  82. if (dbgCompileUnit != NULL)
  83. dbgModule = dbgCompileUnit->mDbgModule;
  84. Init(winDebugger, dbgModule, expr, formatInfo, contextValue);
  85. }
  86. void DbgEvaluationContext::Init(WinDebugger* winDebugger, DbgModule* dbgModule, const StringImpl& expr, DwFormatInfo* formatInfo, DbgTypedValue contextValue)
  87. {
  88. if (expr.empty())
  89. {
  90. mParser = NULL;
  91. mReducer = NULL;
  92. mPassInstance = NULL;
  93. mDbgExprEvaluator = NULL;
  94. mExprNode = NULL;
  95. return;
  96. }
  97. mParser = new BfParser(winDebugger->mBfSystem);
  98. mParser->mCompatMode = true;
  99. mPassInstance = new BfPassInstance(winDebugger->mBfSystem);
  100. auto terminatedExpr = expr + ";";
  101. mParser->SetSource(terminatedExpr.c_str(), terminatedExpr.length());
  102. mParser->Parse(mPassInstance);
  103. mReducer = new BfReducer();
  104. mReducer->mAlloc = mParser->mAlloc;
  105. mReducer->mSystem = winDebugger->mBfSystem;
  106. mReducer->mPassInstance = mPassInstance;
  107. mReducer->mVisitorPos = BfReducer::BfVisitorPos(mParser->mRootNode);
  108. mReducer->mVisitorPos.MoveNext();
  109. mReducer->mCompatMode = mParser->mCompatMode;
  110. mReducer->mSource = mParser;
  111. mExprNode = mReducer->CreateExpression(mParser->mRootNode->GetFirst());
  112. mParser->Close();
  113. mDbgExprEvaluator = new DbgExprEvaluator(winDebugger, dbgModule, mPassInstance, -1, -1);
  114. if ((formatInfo != NULL) && (mExprNode != NULL) && (mExprNode->GetSrcEnd() < (int) expr.length()))
  115. {
  116. String formatFlags = expr.Substring(mExprNode->GetSrcEnd());
  117. String errorString = "Invalid expression";
  118. if (!winDebugger->ParseFormatInfo(dbgModule, formatFlags, formatInfo, mPassInstance, NULL, NULL, &errorString, contextValue))
  119. {
  120. mPassInstance->FailAt(errorString, mParser->mSourceData, mExprNode->GetSrcEnd(), (int)expr.length() - mExprNode->GetSrcEnd());
  121. formatFlags = "";
  122. }
  123. }
  124. if (formatInfo != NULL)
  125. {
  126. mDbgExprEvaluator->mExplicitThis = formatInfo->mExplicitThis;
  127. mDbgExprEvaluator->mCallStackIdx = formatInfo->mCallStackIdx;
  128. }
  129. }
  130. bool DbgEvaluationContext::HasExpression()
  131. {
  132. return mExprNode != NULL;
  133. }
  134. DbgEvaluationContext::~DbgEvaluationContext()
  135. {
  136. delete mParser;
  137. delete mReducer;
  138. delete mDbgExprEvaluator;
  139. delete mPassInstance;
  140. }
  141. DbgTypedValue DbgEvaluationContext::EvaluateInContext(DbgTypedValue contextTypedValue)
  142. {
  143. if (mExprNode == NULL)
  144. return DbgTypedValue();
  145. mPassInstance->ClearErrors();
  146. if (contextTypedValue)
  147. {
  148. mDbgExprEvaluator->mExplicitThis = contextTypedValue;
  149. if ((mDbgExprEvaluator->mExplicitThis.mType->IsPointer()) && (mDbgExprEvaluator->mExplicitThis.mType->mTypeParam->WantsRefThis()))
  150. {
  151. mDbgExprEvaluator->mExplicitThis.mType = mDbgExprEvaluator->mExplicitThis.mType->mTypeParam;
  152. mDbgExprEvaluator->mExplicitThis.mSrcAddress = mDbgExprEvaluator->mExplicitThis.mPtr;
  153. mDbgExprEvaluator->mExplicitThis.mPtr = 0;
  154. }
  155. if ((mDbgExprEvaluator->mExplicitThis.mType->IsCompositeType()) && (!mDbgExprEvaluator->mExplicitThis.mType->WantsRefThis()))
  156. {
  157. if (mDbgExprEvaluator->mExplicitThis.mSrcAddress != 0)
  158. {
  159. mDbgExprEvaluator->mExplicitThis.mType = mDbgExprEvaluator->mDbgModule->GetPointerType(mDbgExprEvaluator->mExplicitThis.mType);
  160. mDbgExprEvaluator->mExplicitThis.mPtr = mDbgExprEvaluator->mExplicitThis.mSrcAddress;
  161. mDbgExprEvaluator->mExplicitThis.mSrcAddress = 0;
  162. }
  163. }
  164. }
  165. if (contextTypedValue.mType != NULL)
  166. mDbgExprEvaluator->mDbgCompileUnit = contextTypedValue.mType->mCompileUnit;
  167. DbgTypedValue exprResult;
  168. auto result = mDbgExprEvaluator->Resolve(mExprNode);
  169. return result;
  170. }
  171. bool DbgEvaluationContext::HadError()
  172. {
  173. return mPassInstance->mFailedIdx != 0;
  174. }
  175. String DbgEvaluationContext::GetErrorStr()
  176. {
  177. String errorStr = mPassInstance->mErrors[0]->mError;
  178. if (mExprNode != NULL)
  179. {
  180. errorStr += ": ";
  181. errorStr += mExprNode->ToString();
  182. }
  183. return errorStr;
  184. }
  185. //////////////////////////////////////////////////////////////////////////
  186. typedef HRESULT(WINAPI* SetThreadDescription_t)(HANDLE hThread, PCWSTR lpThreadDescription);
  187. typedef HRESULT(WINAPI* GetThreadDescription_t)(HANDLE hThread, PWSTR* lpThreadDescription);
  188. static SetThreadDescription_t gSetThreadDescription = NULL;
  189. static GetThreadDescription_t gGetThreadDescription = NULL;
  190. static HMODULE gKernelDll = NULL;
  191. static void ImportKernel()
  192. {
  193. if (gKernelDll != NULL)
  194. return;
  195. WCHAR path[MAX_PATH];
  196. GetSystemDirectory(path, MAX_PATH);
  197. wcscat(path, L"\\kernel32.dll");
  198. gKernelDll = GetModuleHandle(path);
  199. if (gKernelDll == NULL)
  200. {
  201. return;
  202. }
  203. gSetThreadDescription = (SetThreadDescription_t)GetProcAddress(gKernelDll, "SetThreadDescription");
  204. gGetThreadDescription = (GetThreadDescription_t)GetProcAddress(gKernelDll, "GetThreadDescription");
  205. }
  206. void WinDebugger::TryGetThreadName(WdThreadInfo* threadInfo)
  207. {
  208. if (threadInfo->mHThread == NULL)
  209. return;
  210. ImportKernel();
  211. PWSTR wStr = NULL;
  212. if (gGetThreadDescription != NULL)
  213. {
  214. gGetThreadDescription(threadInfo->mHThread, &wStr);
  215. if (wStr == NULL)
  216. return;
  217. threadInfo->mName = UTF8Encode(wStr);
  218. FilterThreadName(threadInfo->mName);
  219. LocalFree(wStr);
  220. }
  221. }
  222. static void CreateFilterName(String& name, DbgType* type)
  223. {
  224. CreateFilterName(name, type->mParent);
  225. switch (type->mTypeCode)
  226. {
  227. case DbgType_Namespace:
  228. case DbgType_Struct:
  229. case DbgType_Class:
  230. name += type->mName;
  231. break;
  232. }
  233. }
  234. static void CreateFilterName(String& name, const char* srcStr, DbgLanguage language)
  235. {
  236. int chevronDepth = 0;
  237. const char* cPtr = srcStr;
  238. for (; true; cPtr++)
  239. {
  240. char c = *cPtr;
  241. if (c == 0)
  242. break;
  243. if (c == '>')
  244. chevronDepth--;
  245. bool inGeneric = chevronDepth > 0;
  246. if (c == '<')
  247. chevronDepth++;
  248. if (inGeneric) // Bundle all generic instances together
  249. continue;
  250. if (c == '[') // Bundle all arrays together
  251. name.clear();
  252. if (c == '(')
  253. return; // Start of params
  254. if ((c == ':') && (cPtr[1] == ':') && (language == DbgLanguage_Beef))
  255. {
  256. name.Append('.');
  257. cPtr++;
  258. }
  259. else
  260. name.Append(c);
  261. }
  262. }
  263. static void CreateFilterName(String& name, DbgSubprogram* subprogram)
  264. {
  265. auto language = subprogram->GetLanguage();
  266. if (subprogram->mName == NULL)
  267. {
  268. if (subprogram->mLinkName[0] == '<')
  269. {
  270. name += subprogram->mLinkName;
  271. return;
  272. }
  273. name = BfDemangler::Demangle(subprogram->mLinkName, language);
  274. // Strip off the params since we need to generate those ourselves
  275. int parenPos = (int)name.IndexOf('(');
  276. if (parenPos != -1)
  277. name.RemoveToEnd(parenPos);
  278. return;
  279. }
  280. else if (subprogram->mHasQualifiedName)
  281. {
  282. const char* cPtr = subprogram->mName;
  283. if (strncmp(cPtr, "_bf::", 5) == 0)
  284. {
  285. CreateFilterName(name, cPtr + 5, DbgLanguage_Beef);
  286. name.Replace(".__BfStaticCtor", ".this$static");
  287. name.Replace(".__BfCtorClear", ".this$clear");
  288. name.Replace(".__BfCtor", ".this");
  289. }
  290. else
  291. CreateFilterName(name, subprogram->mName, language);
  292. return;
  293. }
  294. else
  295. {
  296. if (subprogram->mParentType != NULL)
  297. {
  298. String parentName = subprogram->mParentType->ToString();
  299. CreateFilterName(name, parentName.c_str(), language);
  300. if (!name.empty())
  301. {
  302. if (language == DbgLanguage_Beef)
  303. name += ".";
  304. else
  305. name += "::";
  306. }
  307. }
  308. if ((language == DbgLanguage_Beef) && (subprogram->mParentType != NULL) && (subprogram->mParentType->mTypeName != NULL) &&
  309. (strcmp(subprogram->mName, subprogram->mParentType->mTypeName) == 0))
  310. name += "this";
  311. else if ((language == DbgLanguage_Beef) && (subprogram->mName[0] == '~'))
  312. name += "~this";
  313. else if (strncmp(subprogram->mName, "_bf::", 5) == 0)
  314. {
  315. CreateFilterName(name, subprogram->mName + 5, DbgLanguage_Beef);
  316. }
  317. else
  318. {
  319. CreateFilterName(name, subprogram->mName, language);
  320. }
  321. }
  322. if (name.empty())
  323. name += "`anon";
  324. if ((name[name.length() - 1] == '!') || (name[0] == '<'))
  325. {
  326. if (language == DbgLanguage_Beef)
  327. {
  328. // It's a mixin - assert that there's no params
  329. //BF_ASSERT(subprogram->mParams.Size() == 0);
  330. }
  331. return;
  332. }
  333. }
  334. //////////////////////////////////////////////////////////////////////////
  335. DbgPendingExpr::DbgPendingExpr()
  336. {
  337. mThreadId = -1;
  338. mCallStackIdx = -1;
  339. mParser = NULL;
  340. mCursorPos = -1;
  341. mExprNode = NULL;
  342. mIdleTicks = 0;
  343. mExplitType = NULL;
  344. mExpressionFlags = DwEvalExpressionFlag_None;
  345. }
  346. DbgPendingExpr::~DbgPendingExpr()
  347. {
  348. delete mParser;
  349. }
  350. // conversion logic based on table at http://en.wikipedia.org/wiki/Extended_precision
  351. //CDH TODO put this somewhere more general
  352. static double ConvertFloat80ToDouble(const byte fp80[10])
  353. {
  354. uint16 e = *((uint16*)&fp80[8]);
  355. uint64 m = *((uint64*)&fp80[0]);
  356. uint64 bit63 = (uint64)1 << 63;
  357. uint64 bit62 = (uint64)1 << 62;
  358. bool isNegative = (e & 0x8000) != 0;
  359. double s = isNegative ? -1.0 : 1.0;
  360. e &= 0x7fff;
  361. if (!e)
  362. {
  363. // the high bit and mantissa content will determine whether it's an actual zero, or a denormal or
  364. // pseudo-denormal number with an effective exponent of -16382. But since that exponent is so far
  365. // below anything we can handle in double-precision (even accounting for denormal bit shifts), we're
  366. // effectively still dealing with zero.
  367. return s * 0.0;
  368. }
  369. else if (e == 0x7fff)
  370. {
  371. if (m & bit63)
  372. {
  373. if (m & bit62)
  374. {
  375. return std::numeric_limits<double>::quiet_NaN();
  376. }
  377. else
  378. {
  379. if (m == bit63)
  380. return s * std::numeric_limits<double>::infinity();
  381. else
  382. return std::numeric_limits<double>::signaling_NaN();
  383. }
  384. }
  385. else
  386. {
  387. return std::numeric_limits<double>::quiet_NaN();
  388. }
  389. }
  390. else
  391. {
  392. if (!(m & bit63))
  393. return std::numeric_limits<double>::quiet_NaN(); // unnormal (we don't handle these since 80387 and later treat them as invalid operands anyway)
  394. // else is a normalized value
  395. }
  396. int useExponent = (int)e - 16383;
  397. if (useExponent < -1022)
  398. return s * 0.0; // we could technically support e from -1023 to -1074 as denormals, but don't bother with that for now.
  399. else if (useExponent > 1023)
  400. return s * HUGE_VAL;
  401. useExponent += 1023;
  402. BF_ASSERT((useExponent > 0) && (useExponent < 0x7ff)); // assume we've filtered for valid exponent range
  403. BF_ASSERT(m & bit63); // assume we've filtered out values that aren't normalized by now
  404. uint64 result = 0;
  405. if (isNegative)
  406. result |= bit63;
  407. result |= (uint64)useExponent << 52;
  408. result |= (m & ~bit63) >> 11;
  409. return *reinterpret_cast<double*>(&result);
  410. }
  411. addr_target NS_BF_DBG::DecodeTargetDataPtr(const char*& strRef)
  412. {
  413. addr_target val = (addr_target)stouln(strRef, sizeof(intptr) * 2);
  414. strRef += sizeof(intptr) * 2;
  415. return val;
  416. }
  417. WinDebugger::WinDebugger(DebugManager* debugManager) : mDbgSymSrv(this)
  418. {
  419. ZeroMemory(&mProcessInfo, sizeof(mProcessInfo));
  420. mActiveHotIdx = -1;
  421. mGotStartupEvent = false;
  422. mIsContinuingFromException = false;
  423. mDestroying = false;
  424. mDebugManager = debugManager;
  425. mNeedsRehupBreakpoints = false;
  426. mStepInAssembly = false;
  427. mStepSP = 0;
  428. mStepIsRecursing = false;
  429. mStepStopOnNextInstruction = false;
  430. mDebugTarget = NULL;
  431. mShuttingDown = false;
  432. mBfSystem = new BfSystem();
  433. mAtBreakThread = NULL;
  434. mActiveThread = NULL;
  435. mActiveBreakpoint = NULL;
  436. mSteppingThread = NULL;
  437. mExplicitStopThread = NULL;
  438. mStepSwitchedThreads = false;
  439. mIsDebuggerWaiting = false;
  440. mWantsDebugContinue = false;
  441. mContinueFromBreakpointFailed = false;
  442. mIsStepIntoSpecific = false;
  443. mDbgBreak = false;
  444. mDebuggerWaitingThread = NULL;
  445. mStepType = StepType_None;
  446. mOrigStepType = StepType_None;
  447. mLastValidStepIntoPC = 0;
  448. mActiveSymSrvRequest = NULL;
  449. mStoredReturnValueAddr = 0;
  450. #ifdef BF_DBG_32
  451. mCPU = gX86Target->mX86CPU;
  452. #else
  453. mCPU = gX86Target->mX64CPU;
  454. #endif
  455. mRunState = RunState_NotStarted;
  456. mIsRunning = false;
  457. mSavedAtBreakpointAddress = 0;
  458. mSavedBreakpointAddressContinuing = 0;
  459. mRequestedStackFrameIdx = 0;
  460. mShowPCOverride = 0;
  461. mCurNoInfoStepTries = 0;
  462. mDbgAttachFlags = BfDbgAttachFlag_None;
  463. mDbgProcessHandle = 0;
  464. mDbgThreadHandle = 0;
  465. mDbgProcessId = 0;
  466. mIsPartialCallStack = true;
  467. for (int i = 0; i < 4; i++)
  468. {
  469. mFreeMemoryBreakIndices.push_back(i);
  470. }
  471. SYSTEM_INFO systemInfo;
  472. GetSystemInfo(&systemInfo);
  473. mPageSize = systemInfo.dwPageSize;
  474. mEmptyDebugTarget = new DebugTarget(this);
  475. mEmptyDebugTarget->CreateEmptyTarget();
  476. mEmptyDebugTarget->mIsEmpty = true;
  477. mDebugTarget = mEmptyDebugTarget;
  478. mDebugPendingExpr = NULL;
  479. mDebugEvalThreadInfo = WdThreadInfo();
  480. mMemCacheAddr = 0;
  481. mDebuggerThreadId = 0;
  482. }
  483. WinDebugger::~WinDebugger()
  484. {
  485. mDestroying = true;
  486. delete gDbgPerfManager;
  487. gDbgPerfManager = NULL;
  488. if ((mDebugTarget != NULL) && (mDebugTarget != mEmptyDebugTarget))
  489. Detach();
  490. for (auto breakpoint : mBreakpoints)
  491. {
  492. auto checkBreakpoint = breakpoint->mLinkedSibling;
  493. while (checkBreakpoint != NULL)
  494. {
  495. auto nextBreakpoint = checkBreakpoint->mLinkedSibling;
  496. delete checkBreakpoint;
  497. checkBreakpoint = nextBreakpoint;
  498. }
  499. delete breakpoint;
  500. }
  501. delete mEmptyDebugTarget;
  502. delete mBfSystem;
  503. for (auto kv : mPendingProfilerMap)
  504. delete kv.mValue;
  505. for (auto profiler : mNewProfilerList)
  506. delete profiler;
  507. delete mDebugPendingExpr;
  508. }
  509. void WinDebugger::Fail(const StringImpl& error)
  510. {
  511. if (mIsRunning)
  512. mDebugManager->mOutMessages.push_back(StrFormat("error %s", error.c_str()));
  513. }
  514. // Leave active thread unpaused
  515. void WinDebugger::ThreadRestorePause(WdThreadInfo* onlyPauseThread, WdThreadInfo* dontPauseThread)
  516. {
  517. BfLogDbg("ThreadRestorePause %d %d\n", (onlyPauseThread != NULL) ? onlyPauseThread->mThreadId : 0, (dontPauseThread != NULL) ? dontPauseThread->mThreadId : 0);
  518. for (auto threadInfo : mThreadList)
  519. {
  520. if (((threadInfo != dontPauseThread) && (!threadInfo->mIsBreakRestorePaused)) &&
  521. ((onlyPauseThread == NULL) || (threadInfo == onlyPauseThread)))
  522. {
  523. BF_ASSERT(!threadInfo->mIsBreakRestorePaused);
  524. BfLogDbg("SuspendThread %d\n", threadInfo->mThreadId);
  525. ::SuspendThread(threadInfo->mHThread);
  526. threadInfo->mIsBreakRestorePaused = true;
  527. }
  528. }
  529. }
  530. void WinDebugger::ThreadRestoreUnpause()
  531. {
  532. BfLogDbg("ThreadRestoreUnpause\n");
  533. for (auto threadInfo : mThreadList)
  534. {
  535. if (threadInfo->mIsBreakRestorePaused)
  536. {
  537. BfLogDbg("ResumeThread %d\n", threadInfo->mThreadId);
  538. ::ResumeThread(threadInfo->mHThread);
  539. threadInfo->mIsBreakRestorePaused = false;
  540. }
  541. }
  542. }
  543. void WinDebugger::UpdateThreadDebugRegisters(WdThreadInfo* threadInfo)
  544. {
  545. auto threadId = threadInfo->mHThread;
  546. BF_CONTEXT lcContext;
  547. lcContext.ContextFlags = BF_CONTEXT_DEBUG_REGISTERS;
  548. BF_GetThreadContext(threadId, &lcContext);
  549. for (int memoryBreakIdx = 0; memoryBreakIdx < 4; memoryBreakIdx++)
  550. {
  551. WdMemoryBreakpointBind memoryBreakpointBind = mMemoryBreakpoints[memoryBreakIdx];
  552. WdBreakpoint* wdBreakpoint = memoryBreakpointBind.mBreakpoint;
  553. if (wdBreakpoint == NULL)
  554. {
  555. *(&lcContext.Dr0 + memoryBreakIdx) = 0;
  556. lcContext.Dr7 &= ~((1 << (memoryBreakIdx * 2)) | (1 << (16 + memoryBreakIdx * 4)) | (3 << (18 + memoryBreakIdx * 4)));
  557. }
  558. else
  559. {
  560. int sizeCode = 0;
  561. if (memoryBreakpointBind.mByteCount == 2)
  562. sizeCode = 1;
  563. else if (memoryBreakpointBind.mByteCount == 4)
  564. sizeCode = 3;
  565. else if (memoryBreakpointBind.mByteCount == 8)
  566. sizeCode = 2;
  567. addr_target calcAddr = wdBreakpoint->mMemoryBreakpointInfo->mMemoryAddress + memoryBreakpointBind.mOfs;
  568. BF_ASSERT(calcAddr == memoryBreakpointBind.mAddress);
  569. *(&lcContext.Dr0 + memoryBreakIdx) = calcAddr;
  570. lcContext.Dr7 |= (1 << (memoryBreakIdx * 2)) | (1 << (16 + memoryBreakIdx * 4)) | (sizeCode << (18 + memoryBreakIdx * 4));
  571. }
  572. }
  573. bool worked = BF_SetThreadContext(threadId, &lcContext) != 0;
  574. BF_ASSERT(worked || (mRunState == RunState_Terminating) || (mRunState == RunState_Terminated));
  575. }
  576. void WinDebugger::UpdateThreadDebugRegisters()
  577. {
  578. for (auto threadInfo : mThreadList)
  579. {
  580. ::SuspendThread(threadInfo->mHThread);
  581. UpdateThreadDebugRegisters(threadInfo);
  582. ::ResumeThread(threadInfo->mHThread);
  583. }
  584. }
  585. void WinDebugger::PhysSetBreakpoint(addr_target address)
  586. {
  587. BfLogDbg("PhysSetBreakpoint %p\n", address);
  588. uint8 newData = 0xCC;
  589. // This ensure that we have the orig image data cached
  590. DbgMemoryFlags flags = mDebugTarget->ReadOrigImageData(address, NULL, 1);
  591. if ((flags & DbgMemoryFlags_Execute) == 0)
  592. {
  593. BfLogDbg("Breakpoint ignored - execute flag NOT set in breakpoint address\n", address);
  594. BfLogDbg("Memory Flags = %d\n", gDebugger->GetMemoryFlags(address));
  595. return;
  596. }
  597. // Replace it with Breakpoint
  598. SIZE_T dwReadBytes;
  599. BOOL worked = ::WriteProcessMemory(mProcessInfo.hProcess, (void*)(intptr)address, &newData, 1, &dwReadBytes);
  600. if (!worked)
  601. {
  602. int err = GetLastError();
  603. BfLogDbg("SetBreakpoint FAILED %p\n", address);
  604. }
  605. FlushInstructionCache(mProcessInfo.hProcess, (void*)(intptr)address, 1);
  606. {
  607. uint8 mem = ReadMemory<uint8>(address);
  608. BfLogDbg("Breakpoint byte %X\n", mem);
  609. }
  610. }
  611. void WinDebugger::SetBreakpoint(addr_target address, bool fromRehup)
  612. {
  613. int* countPtr = NULL;
  614. if (mBreakpointAddrMap.TryAdd(address, NULL, &countPtr))
  615. {
  616. BfLogDbg("SetBreakpoint %p\n", address);
  617. *countPtr = 1;
  618. }
  619. else
  620. {
  621. if (fromRehup)
  622. {
  623. BfLogDbg("SetBreakpoint %p Count: %d. Rehup (ignored).\n", address, *countPtr);
  624. return;
  625. }
  626. (*countPtr)++;
  627. BfLogDbg("SetBreakpoint %p Count: %d\n", address, *countPtr);
  628. return;
  629. }
  630. PhysSetBreakpoint(address);
  631. }
  632. void WinDebugger::SetTempBreakpoint(addr_target address)
  633. {
  634. BfLogDbg("SetTempBreakpoint %p\n", address);
  635. mTempBreakpoint.push_back(address);
  636. SetBreakpoint(address);
  637. }
  638. void WinDebugger::PhysRemoveBreakpoint(addr_target address)
  639. {
  640. BfLogDbg("PhysRemoveBreakpoint %p\n", address);
  641. uint8 origData;
  642. DbgMemoryFlags flags = mDebugTarget->ReadOrigImageData(address, &origData, 1);
  643. if ((flags & DbgMemoryFlags_Execute) == 0)
  644. {
  645. //BF_ASSERT("Failed" == 0);
  646. return;
  647. }
  648. SIZE_T dwReadBytes;
  649. if (!WriteProcessMemory(mProcessInfo.hProcess, (void*)(intptr)address, &origData, 1, &dwReadBytes))
  650. {
  651. int err = GetLastError();
  652. BfLogDbg("RemoveBreakpoint FAILED %p\n", address);
  653. }
  654. FlushInstructionCache(mProcessInfo.hProcess, (void*)(intptr)address, 1);
  655. }
  656. void WinDebugger::RemoveBreakpoint(addr_target address)
  657. {
  658. int* countPtr = NULL;
  659. mBreakpointAddrMap.TryGetValue(address, &countPtr);
  660. // This can happen when we shutdown and we're continuing from a breakpoint
  661. //BF_ASSERT(*countPtr != NULL);
  662. if (countPtr == NULL)
  663. {
  664. BfLogDbg("RemoveBreakpoint %p FAILED\n", address);
  665. return;
  666. }
  667. BfLogDbg("RemoveBreakpoint %p count: %d\n", address, *countPtr);
  668. if (*countPtr > 1)
  669. {
  670. (*countPtr)--;
  671. return;
  672. }
  673. mBreakpointAddrMap.Remove(address);
  674. PhysRemoveBreakpoint(address);
  675. }
  676. void WinDebugger::SingleStepX86()
  677. {
  678. // In what cases did this catch bugs?
  679. // This caused other failures (caught in tests)
  680. // if (mActiveThread->mIsAtBreakpointAddress != 0)
  681. // {
  682. // ContinueFromBreakpoint();
  683. // return;
  684. // }
  685. BfLogDbg("Setup SingleStepX86 ActiveThread: %d\n", (mActiveThread != NULL) ? mActiveThread->mThreadId : -1);
  686. BF_CONTEXT lcContext;
  687. lcContext.ContextFlags = BF_CONTEXT_ALL;
  688. BF_GetThreadContext(mActiveThread->mHThread, &lcContext);
  689. lcContext.EFlags |= 0x100; // Set trap flag, which raises "single-step" exception
  690. BF_SetThreadContext(mActiveThread->mHThread, &lcContext);
  691. }
  692. bool WinDebugger::IsInRunState()
  693. {
  694. return (mRunState == RunState_Running) || (mRunState == RunState_Running_ToTempBreakpoint);
  695. }
  696. bool WinDebugger::ContinueFromBreakpoint()
  697. {
  698. if (mDebuggerWaitingThread->mFrozen)
  699. {
  700. BfLogDbg("ContinueFromBreakpoint bailout on frozen thread\n");
  701. mDebuggerWaitingThread->mStoppedAtAddress = 0;
  702. mDebuggerWaitingThread->mIsAtBreakpointAddress = 0;
  703. return true;
  704. }
  705. mActiveThread = mDebuggerWaitingThread;
  706. mActiveBreakpoint = NULL;
  707. BfLogDbg("ContinueFromBreakpoint. ActiveThread: %d\n", (mActiveThread != NULL) ? mActiveThread->mThreadId : -1);
  708. BfLogDbg("ResumeThread %d\n", mActiveThread->mThreadId);
  709. BOOL success = ::ResumeThread(mActiveThread->mHThread);
  710. if (success)
  711. {
  712. // It's possible the active thread is suspended - possibly by the GC, so we would deadlock if we
  713. // attempted to pause the other threads
  714. BfLogDbg("SuspendThread %d\n", mActiveThread->mThreadId);
  715. BfLogDbg("Thread already paused!\n");
  716. ::SuspendThread(mActiveThread->mHThread);
  717. return false;
  718. }
  719. ThreadRestorePause(NULL, mActiveThread);
  720. PhysRemoveBreakpoint(mActiveThread->mIsAtBreakpointAddress);
  721. BF_CONTEXT lcContext;
  722. lcContext.ContextFlags = BF_CONTEXT_ALL;
  723. BF_GetThreadContext(mActiveThread->mHThread, &lcContext);
  724. lcContext.EFlags |= 0x100; // Set trap flag, which raises "single-step" exception
  725. BF_SetThreadContext(mActiveThread->mHThread, &lcContext);
  726. mActiveThread->mStoppedAtAddress = 0;
  727. mActiveThread->mBreakpointAddressContinuing = mActiveThread->mIsAtBreakpointAddress;
  728. mActiveThread->mIsAtBreakpointAddress = 0;
  729. BfLogDbg("ContinueFromBreakpoint set mIsAtBreakpointAddress = 0\n");
  730. return true;
  731. }
  732. Breakpoint* WinDebugger::FindBreakpointAt(intptr addressIn)
  733. {
  734. addr_target address = addressIn;
  735. WdBreakpoint* found = NULL;
  736. for (auto breakpoint : mBreakpoints)
  737. {
  738. if (breakpoint->mAddr == address)
  739. found = breakpoint;
  740. auto checkSibling = (WdBreakpoint*)breakpoint->mLinkedSibling;
  741. while (checkSibling != NULL)
  742. {
  743. if (checkSibling->mAddr == address)
  744. found = checkSibling;
  745. checkSibling = (WdBreakpoint*)checkSibling->mLinkedSibling;
  746. }
  747. }
  748. return found;
  749. }
  750. Breakpoint* WinDebugger::GetActiveBreakpoint()
  751. {
  752. if ((mActiveBreakpoint != NULL) && (mActiveBreakpoint->mHead != NULL))
  753. return mActiveBreakpoint->mHead;
  754. return mActiveBreakpoint;
  755. }
  756. void WinDebugger::DebugThreadProc()
  757. {
  758. BpSetThreadName("DebugThread");
  759. BfpThread_SetName(NULL, "DebugThread", NULL);
  760. mDebuggerThreadId = GetCurrentThreadId();
  761. if (!IsMiniDumpDebugger())
  762. {
  763. if (!DoOpenFile(mFileName, mArgs, mWorkingDir, mEnvBlock))
  764. {
  765. if (mDbgProcessId != 0)
  766. OutputRawMessage("error Unable to attach to process");
  767. else
  768. OutputRawMessage(StrFormat("error Failed to launch: %s", mFileName.c_str()));
  769. mShuttingDown = true;
  770. mRunState = RunState_Terminated;
  771. }
  772. }
  773. while (!mShuttingDown)
  774. {
  775. DoUpdate();
  776. }
  777. mIsRunning = false;
  778. for (int i = 0; i < (int) mBreakpoints.size(); i++)
  779. {
  780. WdBreakpoint* wdBreakpoint = mBreakpoints[i];
  781. wdBreakpoint->mAddr = 0;
  782. wdBreakpoint->mLineData = DbgLineDataEx();
  783. wdBreakpoint->mSrcFile = NULL;
  784. if (wdBreakpoint->mLinkedSibling != NULL)
  785. {
  786. DeleteBreakpoint(wdBreakpoint->mLinkedSibling);
  787. wdBreakpoint->mLinkedSibling = NULL;
  788. }
  789. }
  790. if (!IsMiniDumpDebugger())
  791. {
  792. while (true)
  793. {
  794. if (!mIsDebuggerWaiting)
  795. {
  796. if (!WaitForDebugEvent(&mDebugEvent, 0))
  797. break;
  798. }
  799. if (mDebuggerWaitingThread != NULL)
  800. {
  801. BF_ASSERT_REL((mDebuggerWaitingThread->mIsAtBreakpointAddress == 0) || (mShuttingDown));
  802. ::ContinueDebugEvent(mDebuggerWaitingThread->mProcessId, mDebuggerWaitingThread->mThreadId, DBG_CONTINUE);
  803. BfLogDbg("::ContinueDebugEvent startup ThreadId:%d\n", mDebuggerWaitingThread->mThreadId);
  804. }
  805. mIsDebuggerWaiting = false;
  806. mDebuggerWaitingThread = NULL;
  807. }
  808. }
  809. mDebuggerThreadId = 0;
  810. }
  811. static void DebugThreadProcThunk(void* winDebugger)
  812. {
  813. ((WinDebugger*) winDebugger)->DebugThreadProc();
  814. }
  815. int WinDebugger::GetAddrSize()
  816. {
  817. return sizeof(addr_target);
  818. }
  819. bool WinDebugger::CanOpen(const StringImpl& fileName, DebuggerResult* outResult)
  820. {
  821. FILE* fp = fopen(fileName.c_str(), "rb");
  822. if (fp == NULL)
  823. {
  824. *outResult = DebuggerResult_CannotOpen;
  825. return false;
  826. }
  827. FileStream fs;
  828. fs.mFP = fp;
  829. *outResult = DebuggerResult_Ok;
  830. bool canRead = DbgModule::CanRead(&fs, outResult);
  831. fclose(fp);
  832. return canRead;
  833. }
  834. void WinDebugger::OpenFile(const StringImpl& fileName, const StringImpl& args, const StringImpl& workingDir, const Array<uint8>& envBlock)
  835. {
  836. BF_ASSERT(!mIsRunning);
  837. mFileName = fileName;
  838. mArgs = args;
  839. mWorkingDir = workingDir;
  840. mEnvBlock = envBlock;
  841. mDebugTarget = new DebugTarget(this);
  842. }
  843. bool WinDebugger::Attach(int processId, BfDbgAttachFlags attachFlags)
  844. {
  845. BF_ASSERT(!mIsRunning);
  846. mDbgAttachFlags = attachFlags;
  847. mDbgProcessHandle = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)processId);
  848. if (mDbgProcessHandle == 0)
  849. return false;
  850. BOOL is32Bit = false;
  851. if (!IsWow64Process(mDbgProcessHandle, &is32Bit))
  852. {
  853. mDbgProcessHandle = 0;
  854. ::CloseHandle(mDbgProcessHandle);
  855. return false;
  856. }
  857. bool want32Bit = sizeof(intptr_target) == 4;
  858. if (want32Bit != (is32Bit != 0))
  859. {
  860. mDbgProcessHandle = 0;
  861. ::CloseHandle(mDbgProcessHandle);
  862. return false;
  863. }
  864. HMODULE mainModule = 0;
  865. DWORD memNeeded = 0;
  866. ::EnumProcessModules(mDbgProcessHandle, &mainModule, sizeof(HMODULE), &memNeeded);
  867. WCHAR fileName[MAX_PATH] = {0};
  868. GetModuleFileNameExW(mDbgProcessHandle, mainModule, fileName, MAX_PATH);
  869. mFileName = UTF8Encode(fileName);
  870. mDbgProcessId = processId;
  871. mDbgProcessHandle = 0;
  872. ::CloseHandle(mDbgProcessHandle);
  873. mDebugTarget = new DebugTarget(this);
  874. return true;
  875. }
  876. void WinDebugger::Run()
  877. {
  878. mIsRunning = true;
  879. DWORD localThreadId;
  880. HANDLE hThread = ::CreateThread(NULL, 64 * 1024, (LPTHREAD_START_ROUTINE) &DebugThreadProcThunk, (void*)this, 0, &localThreadId);
  881. CloseHandle(hThread);
  882. }
  883. void WinDebugger::HotLoad(const Array<String>& objectFiles, int hotIdx)
  884. {
  885. AutoCrit autoCrit(mDebugManager->mCritSect);
  886. SetAndRestoreValue<int> prevHotIdx(mActiveHotIdx, hotIdx);
  887. BF_ASSERT(mHotThreadStates.empty());
  888. mHotThreadStates.Resize(mThreadList.size());
  889. for (int threadIdx = 0; threadIdx < (int)mThreadList.size(); threadIdx++)
  890. {
  891. WdThreadInfo* threadInfo = mThreadList[threadIdx];
  892. SetAndRestoreValue<WdThreadInfo*> prevActiveThread(mActiveThread, threadInfo);
  893. BfLogDbg("SuspendThread %d\n", threadInfo->mThreadId);
  894. ::SuspendThread(threadInfo->mHThread);
  895. PopulateRegisters(&mHotThreadStates[threadIdx]);
  896. }
  897. for (auto address : mTempBreakpoint)
  898. RemoveBreakpoint(address);
  899. mTempBreakpoint.Clear();
  900. mStepBreakpointAddrs.Clear();
  901. for (auto breakpoint : mBreakpoints)
  902. {
  903. DetachBreakpoint(breakpoint);
  904. }
  905. int startingModuleIdx = (int)mDebugTarget->mDbgModules.size();
  906. BfLogDbg("WinDebugger::HotLoad\n");
  907. bool failed = false;
  908. for (auto fileName : objectFiles)
  909. {
  910. BfLogDbg("WinDebugger::HotLoad: %s\n", fileName.c_str());
  911. DbgModule* newBinary = mDebugTarget->HotLoad(fileName, hotIdx);
  912. if ((newBinary != NULL) && (newBinary->mFailed))
  913. failed = true;
  914. }
  915. for (int moduleIdx = startingModuleIdx; moduleIdx < (int)mDebugTarget->mDbgModules.size(); moduleIdx++)
  916. {
  917. auto dbgModule = mDebugTarget->mDbgModules[moduleIdx];
  918. BF_ASSERT(dbgModule->mIsHotObjectFile);
  919. BF_ASSERT(dbgModule->mHotIdx == hotIdx);
  920. dbgModule->FinishHotSwap();
  921. }
  922. for (auto dwarf : mDebugTarget->mDbgModules)
  923. dwarf->RevertWritingEnable();
  924. mHotThreadStates.Clear();
  925. int blockAllocSinceClean = mDebugTarget->mHotHeap->mBlockAllocIdx - mDebugTarget->mLastHotHeapCleanIdx;
  926. // Clean up the hot heap every 64MB
  927. int blocksBetweenCleans = (64 * 1024 * 1024) / HotHeap::BLOCK_SIZE;
  928. #ifdef _DEBUG
  929. //TODO: This is just for testing
  930. blocksBetweenCleans = 1;
  931. #endif
  932. //TODO: Put this back after we fix the cleanup
  933. if (blockAllocSinceClean >= blocksBetweenCleans)
  934. CleanupHotHeap();
  935. mDebugTarget->RehupSrcFiles();
  936. for (int breakIdx = 0; breakIdx < (int)mBreakpoints.size(); breakIdx++)
  937. {
  938. auto breakpoint = mBreakpoints[breakIdx];
  939. CheckBreakpoint(breakpoint);
  940. }
  941. for (int threadIdx = 0; threadIdx < (int)mThreadList.size(); threadIdx++)
  942. {
  943. WdThreadInfo* threadInfo = mThreadList[threadIdx];
  944. BfLogDbg("ResumeThread %d\n", threadInfo->mThreadId);
  945. ::ResumeThread(threadInfo->mHThread);
  946. }
  947. if (IsPaused())
  948. {
  949. ClearCallStack();
  950. UpdateCallStack();
  951. }
  952. }
  953. void WinDebugger::InitiateHotResolve(DbgHotResolveFlags flags)
  954. {
  955. AutoCrit autoCrit(mDebugManager->mCritSect);
  956. delete mHotResolveData;
  957. mHotResolveData = NULL;
  958. mHotResolveData = new DbgHotResolveData();
  959. DbgHotScanner* hotScanner = new DbgHotScanner(this);
  960. hotScanner->Scan(flags);
  961. delete hotScanner;
  962. }
  963. bool WinDebugger::DoOpenFile(const StringImpl& fileName, const StringImpl& args, const StringImpl& workingDir, const Array<uint8>& envBlock)
  964. {
  965. BP_ZONE("WinDebugger::DoOpenFile");
  966. AutoCrit autoCrit(mDebugManager->mCritSect);
  967. //gDbgPerfManager->StartRecording();
  968. STARTUPINFOW si;
  969. ZeroMemory(&si, sizeof(si));
  970. si.cb = sizeof(si);
  971. ZeroMemory(&mProcessInfo, sizeof(mProcessInfo));
  972. if (mDbgProcessId != 0)
  973. {
  974. BOOL success = ::DebugActiveProcess(mDbgProcessId);
  975. if (!success)
  976. return false;
  977. mProcessInfo.dwProcessId = mDbgProcessId;
  978. }
  979. else
  980. {
  981. BP_ZONE("DoOpenFile_CreateProcessW");
  982. UTF16String envW;
  983. DWORD flags = DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS | CREATE_DEFAULT_ERROR_MODE;
  984. void* envPtr = NULL;
  985. if (!envBlock.IsEmpty())
  986. {
  987. //UTF16?
  988. if (envBlock[1] == 0)
  989. {
  990. envPtr = (void*)&envBlock[0];
  991. flags |= CREATE_UNICODE_ENVIRONMENT;
  992. }
  993. else
  994. {
  995. String str8((char*)&envBlock[0], (int)envBlock.size());
  996. envW = UTF8Decode(str8);
  997. envPtr = (void*)envW.c_str();
  998. flags |= CREATE_UNICODE_ENVIRONMENT;
  999. }
  1000. }
  1001. String cmdLine = "\"";
  1002. cmdLine += fileName;
  1003. cmdLine += "\"";
  1004. if (!args.IsEmpty())
  1005. {
  1006. cmdLine += " ";
  1007. cmdLine += args;
  1008. }
  1009. BOOL worked = CreateProcessW(NULL, (WCHAR*)UTF8Decode(cmdLine).c_str(), NULL, NULL, FALSE,
  1010. flags, envPtr, (WCHAR*)UTF8Decode(workingDir).c_str(), &si, &mProcessInfo);
  1011. if (!worked)
  1012. {
  1013. auto lastError = ::GetLastError();
  1014. if (lastError == ERROR_DIRECTORY)
  1015. {
  1016. mDebugManager->mOutMessages.push_back(StrFormat("error Unable to locate specified working directory '%s'", SlashString(workingDir, false, false).c_str()));
  1017. }
  1018. return false;
  1019. }
  1020. WdThreadInfo* threadInfo = new WdThreadInfo();
  1021. threadInfo->mProcessId = mProcessInfo.dwProcessId;
  1022. threadInfo->mThreadId = mProcessInfo.dwThreadId;
  1023. threadInfo->mHThread = mProcessInfo.hThread;
  1024. threadInfo->mThreadLocalBase = NULL;
  1025. threadInfo->mStartAddress = NULL;
  1026. mThreadMap[mProcessInfo.dwThreadId] = threadInfo;
  1027. mThreadList.push_back(threadInfo);
  1028. }
  1029. mRunState = RunState_Running;
  1030. while (true)
  1031. {
  1032. BP_ZONE("DoOpenFile_WaitForImageBase");
  1033. autoCrit.mCritSect->Unlock();
  1034. DoUpdate();
  1035. autoCrit.mCritSect->Lock();
  1036. ContinueDebugEvent();
  1037. if ((mDebugTarget->mTargetBinary != NULL) && (mDebugTarget->mTargetBinary->mOrigImageData != NULL))
  1038. break;
  1039. }
  1040. RehupBreakpoints(true);
  1041. //gDbgPerfManager->StopRecording();
  1042. //gDbgPerfManager->DbgPrint();
  1043. return true;
  1044. }
  1045. void WinDebugger::StopDebugging()
  1046. {
  1047. AutoCrit autoCrit(mDebugManager->mCritSect);
  1048. BfLogDbg("WinDebugger::Terminate\n");
  1049. if (mActiveSymSrvRequest != NULL)
  1050. mActiveSymSrvRequest->Cancel();
  1051. if ((mRunState == RunState_NotStarted) || (mRunState == RunState_Terminated) || (mRunState == RunState_Terminating))
  1052. return;
  1053. if ((mDbgProcessId != 0) && ((mDbgAttachFlags & BfDbgAttachFlag_ShutdownOnExit) == 0))
  1054. {
  1055. BfLogDbg("StopDebugging\n");
  1056. ::DebugActiveProcessStop(mDbgProcessId);
  1057. mRunState = RunState_Terminated;
  1058. BfLogDbg("mRunState = RunState_Terminated\n");
  1059. }
  1060. else
  1061. {
  1062. TerminateProcess(mProcessInfo.hProcess, 0);
  1063. mRunState = RunState_Terminating;
  1064. BfLogDbg("mRunState = RunState_Terminating\n");
  1065. }
  1066. }
  1067. void WinDebugger::Terminate()
  1068. {
  1069. AutoCrit autoCrit(mDebugManager->mCritSect);
  1070. BfLogDbg("WinDebugger::Terminate\n");
  1071. if (mActiveSymSrvRequest != NULL)
  1072. mActiveSymSrvRequest->Cancel();
  1073. if ((mRunState == RunState_NotStarted) || (mRunState == RunState_Terminated) || (mRunState == RunState_Terminating))
  1074. return;
  1075. TerminateProcess(mProcessInfo.hProcess, 0);
  1076. mRunState = RunState_Terminating;
  1077. BfLogDbg("mRunState = RunState_Terminating\n");
  1078. }
  1079. static int gDebugUpdateCnt = 0;
  1080. void WinDebugger::Detach()
  1081. {
  1082. BfLogDbg("Debugger Detach\n");
  1083. mDebugManager->mNetManager->CancelAll();
  1084. while ((mIsRunning) || (mDebuggerThreadId != 0))
  1085. {
  1086. mShuttingDown = true;
  1087. Sleep(1);
  1088. }
  1089. mPendingProfilerMap.Clear();
  1090. for (auto profiler : mNewProfilerList)
  1091. delete profiler;
  1092. mNewProfilerList.Clear();
  1093. mPendingImageLoad.Clear();
  1094. mPendingDebugInfoLoad.Clear();
  1095. RemoveTempBreakpoints();
  1096. mContinueEvent.Reset();
  1097. if (mDebugTarget != mEmptyDebugTarget)
  1098. delete mDebugTarget;
  1099. mDebugTarget = mEmptyDebugTarget;
  1100. mShuttingDown = false;
  1101. mStepSP = 0;
  1102. ClearCallStack();
  1103. mRunState = RunState_NotStarted;
  1104. mStepType = StepType_None;
  1105. mHadImageFindError = false;
  1106. mIsPartialCallStack = true;
  1107. delete mDebugPendingExpr;
  1108. mDebugPendingExpr = NULL;
  1109. for (auto threadPair : mThreadMap)
  1110. {
  1111. auto threadInfo = threadPair.mValue;
  1112. delete threadInfo;
  1113. }
  1114. mThreadMap.Clear();
  1115. mThreadList.Clear();
  1116. mHotTargetMemory.Clear();
  1117. // We don't need to close the hThread when we have attached to a process
  1118. if (mDbgProcessId == 0)
  1119. {
  1120. CloseHandle(mProcessInfo.hThread);
  1121. CloseHandle(mProcessInfo.hProcess);
  1122. }
  1123. for (auto breakpoint : mBreakpoints)
  1124. {
  1125. if (!mDestroying)
  1126. {
  1127. BF_FATAL("Breakpoints should be deleted already");
  1128. }
  1129. if (breakpoint->mMemoryBreakpointInfo != NULL)
  1130. {
  1131. DetachBreakpoint(breakpoint);
  1132. }
  1133. }
  1134. ZeroMemory(&mProcessInfo, sizeof(mProcessInfo));
  1135. mStepBreakpointAddrs.Clear();
  1136. mIsRunning = false;
  1137. mDbgAttachFlags = BfDbgAttachFlag_None;
  1138. mDbgProcessId = 0;
  1139. mDbgProcessHandle = 0;
  1140. ClearCallStack();
  1141. mWantsDebugContinue = false;
  1142. mAtBreakThread = NULL;
  1143. mActiveThread = NULL;
  1144. mActiveBreakpoint = NULL;
  1145. mSteppingThread = NULL;
  1146. mExplicitStopThread = NULL;
  1147. mIsContinuingFromException = false;
  1148. mGotStartupEvent = false;
  1149. mIsDebuggerWaiting = false;
  1150. mBreakpointAddrMap.Clear();
  1151. gDebugUpdateCnt = 0;
  1152. }
  1153. Profiler* WinDebugger::StartProfiling()
  1154. {
  1155. return new DbgProfiler(this);
  1156. }
  1157. Profiler* WinDebugger::PopProfiler()
  1158. {
  1159. AutoCrit autoCrit(mDebugManager->mCritSect);
  1160. if (mNewProfilerList.IsEmpty())
  1161. return NULL;
  1162. auto profiler = (DbgProfiler*)mNewProfilerList[0];
  1163. mNewProfilerList.erase(mNewProfilerList.begin());
  1164. return profiler;
  1165. }
  1166. void WinDebugger::ReportMemory(MemReporter* memReporter)
  1167. {
  1168. mEmptyDebugTarget->ReportMemory(memReporter);
  1169. if (mDebugTarget != mEmptyDebugTarget)
  1170. mDebugTarget->ReportMemory(memReporter);
  1171. }
  1172. void WinDebugger::ModuleChanged(DbgModule* dbgModule)
  1173. {
  1174. mDebugManager->mOutMessages.push_back(String("dbgInfoLoaded ") + dbgModule->mFilePath);
  1175. }
  1176. bool WinDebugger::DoUpdate()
  1177. {
  1178. if ((mDbgProcessId != 0) && ((mDbgAttachFlags & BfDbgAttachFlag_ShutdownOnExit) == 0))
  1179. ::DebugSetProcessKillOnExit(FALSE);
  1180. else
  1181. ::DebugSetProcessKillOnExit(TRUE);
  1182. //
  1183. {
  1184. AutoCrit autoCrit(mDebugManager->mCritSect);
  1185. auto _ModuleChanged = [&](DbgModule* dbgModule)
  1186. {
  1187. ModuleChanged(dbgModule);
  1188. ClearCallStack(); // We may have actual dbgSubprograms and stuff now...
  1189. };
  1190. for (auto dbgModule : mPendingImageLoad)
  1191. {
  1192. dbgModule->PreCacheImage();
  1193. }
  1194. for (auto dbgModule : mPendingDebugInfoLoad)
  1195. {
  1196. dbgModule->PreCacheDebugInfo();
  1197. }
  1198. while (!mPendingImageLoad.IsEmpty())
  1199. {
  1200. auto dbgModule = mPendingImageLoad.back();
  1201. mPendingImageLoad.pop_back();
  1202. dbgModule->RequestImage();
  1203. _ModuleChanged(dbgModule);
  1204. }
  1205. while (!mPendingDebugInfoLoad.IsEmpty())
  1206. {
  1207. auto dbgModule = mPendingDebugInfoLoad.back();
  1208. mPendingDebugInfoLoad.pop_back();
  1209. dbgModule->RequestDebugInfo();
  1210. // We do a "_ModuleChanged" even if the load failed, so we rehup the callstack and stop
  1211. // saying "<Loading...>"
  1212. _ModuleChanged(dbgModule);
  1213. }
  1214. /*while (!mPendingDebugInfoRequests.IsEmpty())
  1215. {
  1216. if ((!mPendingImageLoad.IsEmpty()) || (!mPendingDebugInfoLoad.IsEmpty()))
  1217. break;
  1218. auto dbgModule = mPendingDebugInfoRequests.back();
  1219. mPendingDebugInfoRequests.pop_back();
  1220. if (LoadDebugInfoForModule(dbgModule) == 1)
  1221. _ModuleChanged(dbgModule);
  1222. }*/
  1223. }
  1224. if (IsMiniDumpDebugger())
  1225. {
  1226. Sleep(20);
  1227. return false;
  1228. }
  1229. if (mIsDebuggerWaiting)
  1230. {
  1231. if ((IsInRunState()) || (mRunState == RunState_Terminating) || (mRunState == RunState_DebugEval))
  1232. ContinueDebugEvent();
  1233. if (mContinueEvent.WaitFor(8))
  1234. {
  1235. BF_ASSERT(!mWantsDebugContinue); // mWantsDebugContinue should already been reset
  1236. BfLogDbg("::ContinueDebugEvent 1 ThreadId:%d\n", mDebuggerWaitingThread->mThreadId);
  1237. BF_ASSERT_REL(mDebuggerWaitingThread->mIsAtBreakpointAddress == 0);
  1238. ::ContinueDebugEvent(mDebuggerWaitingThread->mProcessId, mDebuggerWaitingThread->mThreadId, mIsContinuingFromException ? DBG_EXCEPTION_NOT_HANDLED : DBG_CONTINUE);
  1239. mIsContinuingFromException = false;
  1240. mIsDebuggerWaiting = false;
  1241. mDebuggerWaitingThread = NULL;
  1242. }
  1243. else
  1244. return false;
  1245. }
  1246. if (!WaitForDebugEvent(&mDebugEvent, 8))
  1247. return false;
  1248. gDebugUpdateCnt++;
  1249. static const char* eventNames[] = { "DBG_EVENT ?",
  1250. "EXCEPTION_DEBUG_EVENT",
  1251. "CREATE_THREAD_DEBUG_EVENT",
  1252. "CREATE_PROCESS_DEBUG_EVENT",
  1253. "EXIT_THREAD_DEBUG_EVENT",
  1254. "EXIT_PROCESS_DEBUG_EVENT",
  1255. "LOAD_DLL_DEBUG_EVENT",
  1256. "UNLOAD_DLL_DEBUG_EVENT",
  1257. "OUTPUT_DEBUG_STRING_EVENT",
  1258. "RIP_EVENT"};
  1259. BfLogDbg("WaitForDebugEvent %s ThreadId:%d\n", eventNames[mDebugEvent.dwDebugEventCode], mDebugEvent.dwThreadId);
  1260. BP_ZONE(eventNames[mDebugEvent.dwDebugEventCode]);
  1261. AutoCrit autoCrit(mDebugManager->mCritSect);
  1262. mActiveBreakpoint = NULL;
  1263. mIsDebuggerWaiting = true;
  1264. mWantsDebugContinue = true;
  1265. mRequestedStackFrameIdx = 0;
  1266. mBreakStackFrameIdx = 0;
  1267. mShowPCOverride = 0;
  1268. WdThreadInfo* threadInfo = NULL;
  1269. mThreadMap.TryGetValue(mDebugEvent.dwThreadId, &threadInfo);
  1270. mDebuggerWaitingThread = threadInfo;
  1271. mExplicitStopThread = mDebuggerWaitingThread;
  1272. switch (mDebugEvent.dwDebugEventCode)
  1273. {
  1274. case CREATE_PROCESS_DEBUG_EVENT:
  1275. {
  1276. if (threadInfo == NULL)
  1277. {
  1278. BF_ASSERT(mThreadMap.size() == 0);
  1279. WdThreadInfo* newThreadInfo = new WdThreadInfo();
  1280. newThreadInfo->mProcessId = mDebugEvent.dwProcessId;
  1281. newThreadInfo->mThreadId = mDebugEvent.dwThreadId;
  1282. newThreadInfo->mHThread = mDebugEvent.u.CreateProcessInfo.hThread;
  1283. newThreadInfo->mThreadLocalBase = mDebugEvent.u.CreateProcessInfo.lpThreadLocalBase;
  1284. newThreadInfo->mStartAddress = (void*)mDebugEvent.u.CreateProcessInfo.lpStartAddress;
  1285. BF_CONTEXT lcContext;
  1286. lcContext.ContextFlags = BF_CONTEXT_CONTROL;
  1287. BF_GetThreadContext(newThreadInfo->mHThread, &lcContext);
  1288. newThreadInfo->mStartSP = BF_CONTEXT_SP(lcContext);
  1289. mThreadMap[mDebugEvent.dwThreadId] = newThreadInfo;
  1290. mDebuggerWaitingThread = newThreadInfo;
  1291. mThreadList.push_back(mDebuggerWaitingThread);
  1292. UpdateThreadDebugRegisters();
  1293. OutputMessage(StrFormat("Creating thread from CREATE_PROCESS_DEBUG_EVENT %d\n", mDebugEvent.dwThreadId));
  1294. threadInfo = mDebuggerWaitingThread;
  1295. mProcessInfo.dwThreadId = threadInfo->mThreadId;
  1296. mProcessInfo.hThread = threadInfo->mHThread;
  1297. mProcessInfo.hProcess = mDebugEvent.u.CreateProcessInfo.hProcess;
  1298. }
  1299. else
  1300. {
  1301. threadInfo->mThreadLocalBase = mDebugEvent.u.CreateProcessInfo.lpThreadLocalBase;
  1302. threadInfo->mStartAddress = (void*)mDebugEvent.u.CreateProcessInfo.lpStartAddress;
  1303. }
  1304. BF_CONTEXT lcContext;
  1305. lcContext.ContextFlags = BF_CONTEXT_CONTROL;
  1306. BF_GetThreadContext(threadInfo->mHThread, &lcContext);
  1307. threadInfo->mStartSP = BF_CONTEXT_SP(lcContext);
  1308. DbgModule* targetBinary = mDebugTarget->Init(mFileName, (addr_target)(intptr)mDebugEvent.u.CreateProcessInfo.lpBaseOfImage);
  1309. addr_target gotImageBase = (addr_target)(intptr)mDebugEvent.u.CreateProcessInfo.lpBaseOfImage;
  1310. if (targetBinary->mImageBase != gotImageBase)
  1311. {
  1312. BF_FATAL("Image base didn't match");
  1313. }
  1314. targetBinary->mImageBase = gotImageBase;
  1315. targetBinary->mImageSize = (int)targetBinary->GetImageSize();
  1316. targetBinary->mOrigImageData = new DbgModuleMemoryCache(targetBinary->mImageBase, targetBinary->mImageSize);
  1317. bool wantsHotHeap = mDbgProcessId == 0;
  1318. #ifdef BF_DBG_32
  1319. if (wantsHotHeap)
  1320. mDebugTarget->mHotHeap = new HotHeap();
  1321. #else
  1322. if (wantsHotHeap)
  1323. {
  1324. // 64-bit hot loaded code needs to be placed close to the original EXE so 32-bit relative
  1325. // offsets within the hot code can still reach the old code
  1326. addr_target checkHotReserveAddr = (addr_target)targetBinary->mImageBase + targetBinary->mImageSize;
  1327. int mb = 1024 * 1024;
  1328. int reserveSize = 512 * mb;
  1329. // Round up to MB boundary + 64MB, to help keep other DLLs at their preferred base addresses
  1330. checkHotReserveAddr = ((checkHotReserveAddr + 64 * mb) & ~(mb - 1));
  1331. checkHotReserveAddr = (addr_target)targetBinary->mImageBase;
  1332. addr_target reservedPtr = NULL;
  1333. while ((addr_target)checkHotReserveAddr < (addr_target)targetBinary->mImageBase + 0x30000000)
  1334. {
  1335. reservedPtr = (addr_target)VirtualAllocEx(mProcessInfo.hProcess, (void*)(intptr)checkHotReserveAddr, reserveSize, MEM_RESERVE, PAGE_EXECUTE_READWRITE);
  1336. if (reservedPtr != NULL)
  1337. break;
  1338. checkHotReserveAddr += 4 * mb;
  1339. }
  1340. if (reservedPtr != 0)
  1341. {
  1342. BF_ASSERT(mDebugTarget->mHotHeap == NULL);
  1343. mDebugTarget->mHotHeap = new HotHeap(reservedPtr, reserveSize);
  1344. }
  1345. //TODO: Throw actual error if we can't reserve HOT area
  1346. BF_ASSERT(reservedPtr != NULL);
  1347. }
  1348. #endif
  1349. if (mDebugEvent.u.CreateProcessInfo.hFile != NULL)
  1350. CloseHandle(mDebugEvent.u.CreateProcessInfo.hFile);
  1351. mDbgProcessHandle = mDebugEvent.u.CreateProcessInfo.hProcess;
  1352. mDbgThreadHandle = mDebugEvent.u.CreateProcessInfo.hThread;
  1353. mGotStartupEvent = true;
  1354. mDebugManager->mOutMessages.push_back("modulesChanged");
  1355. }
  1356. break;
  1357. case EXIT_PROCESS_DEBUG_EVENT:
  1358. {
  1359. BfLogDbg("EXIT_PROCESS_DEBUG_EVENT\n");
  1360. DWORD exitCode = mDebugEvent.u.ExitProcess.dwExitCode;
  1361. String exitMessage;
  1362. switch (exitCode)
  1363. {
  1364. case STATUS_DLL_NOT_FOUND:
  1365. exitMessage = "STATUS_DLL_NOT_FOUND";
  1366. break;
  1367. case STATUS_DLL_INIT_FAILED:
  1368. exitMessage = "STATUS_DLL_INIT_FAILED";
  1369. break;
  1370. case STATUS_ENTRYPOINT_NOT_FOUND:
  1371. exitMessage = "STATUS_ENTRYPOINT_NOT_FOUND";
  1372. break;
  1373. }
  1374. String exitCodeStr;
  1375. if ((exitCode >= 0x10000000) && (exitCode <= 0xF7000000))
  1376. exitCodeStr = StrFormat("0x%X", exitCode);
  1377. else
  1378. exitCodeStr = StrFormat("%d", exitCode);
  1379. if (!exitMessage.IsEmpty())
  1380. OutputMessage(StrFormat("Process terminated. ExitCode: %s (%s).\n", exitCodeStr.c_str(), exitMessage.c_str()));
  1381. else
  1382. OutputMessage(StrFormat("Process terminated. ExitCode: %s.\n", exitCodeStr.c_str()));
  1383. mRunState = RunState_Terminated;
  1384. mDebugManager->mOutMessages.push_back("modulesChanged");
  1385. }
  1386. break;
  1387. case LOAD_DLL_DEBUG_EVENT:
  1388. {
  1389. WCHAR moduleNameStr[MAX_PATH] = { 0 };
  1390. GetFinalPathNameByHandleW(mDebugEvent.u.LoadDll.hFile, moduleNameStr, MAX_PATH, FILE_NAME_NORMALIZED);
  1391. std::wstring wow64Dir;
  1392. std::wstring systemDir;
  1393. PWSTR wow64DirPtr = NULL;
  1394. SHGetKnownFolderPath(FOLDERID_SystemX86, KF_FLAG_NO_ALIAS, NULL, &wow64DirPtr);
  1395. if (wow64DirPtr != NULL)
  1396. {
  1397. wow64Dir = wow64DirPtr;
  1398. CoTaskMemFree(wow64DirPtr);
  1399. }
  1400. PWSTR systemDirPtr = NULL;
  1401. SHGetKnownFolderPath(FOLDERID_System, KF_FLAG_NO_ALIAS, NULL, &systemDirPtr);
  1402. if (systemDirPtr != NULL)
  1403. {
  1404. systemDir = systemDirPtr;
  1405. CoTaskMemFree(systemDirPtr);
  1406. }
  1407. if ((mDebugEvent.u.LoadDll.lpImageName != 0) && (mDebugEvent.u.LoadDll.fUnicode))
  1408. {
  1409. addr_target strAddr = ReadMemory<addr_target>((addr_target)(intptr)mDebugEvent.u.LoadDll.lpImageName);
  1410. for (int i = 0; i < MAX_PATH - 1; i++)
  1411. {
  1412. WCHAR c = ReadMemory<WCHAR>(strAddr + i*2);
  1413. moduleNameStr[i] = (WCHAR)c;
  1414. if (c == 0)
  1415. break;
  1416. }
  1417. }
  1418. String origModuleName = UTF8Encode(moduleNameStr);
  1419. String moduleName = origModuleName;
  1420. String loadMsg;
  1421. HANDLE altFileHandle = INVALID_HANDLE_VALUE;
  1422. if (moduleName != origModuleName)
  1423. {
  1424. loadMsg = StrFormat("Loading DLL: %s(%s) @ %s", origModuleName.c_str(), moduleName.c_str(), EncodeDataPtr((addr_target)(intptr)mDebugEvent.u.LoadDll.lpBaseOfDll, true).c_str());
  1425. altFileHandle = ::CreateFileW(UTF8Decode(moduleName).c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  1426. }
  1427. else
  1428. {
  1429. loadMsg = StrFormat("Loading DLL: %s @ %s", moduleName.c_str(), EncodeDataPtr((addr_target)(intptr)mDebugEvent.u.LoadDll.lpBaseOfDll, true).c_str());
  1430. }
  1431. BfLogDbg("LOAD_DLL_DEBUG_EVENT %s\n", moduleName.c_str());
  1432. bool skipLoad = false;
  1433. #ifdef BF_DBG_32
  1434. if (((uintptr)mDebugEvent.u.LoadDll.lpBaseOfDll & 0xFFFFFFFF00000000LL) != 0)
  1435. {
  1436. skipLoad = true;
  1437. loadMsg += " - Skipped";
  1438. }
  1439. #endif
  1440. if (!skipLoad)
  1441. {
  1442. FileHandleStream stream;
  1443. stream.mFileHandle = mDebugEvent.u.LoadDll.hFile;
  1444. if (altFileHandle != INVALID_HANDLE_VALUE)
  1445. stream.mFileHandle = altFileHandle;
  1446. if (mDebugTarget->SetupDyn(moduleName, &stream, (intptr)mDebugEvent.u.LoadDll.lpBaseOfDll) == NULL)
  1447. loadMsg += " - Failed to load";
  1448. stream.mFileHandle = 0;
  1449. }
  1450. OutputMessage(loadMsg + "\n");
  1451. if (altFileHandle != INVALID_HANDLE_VALUE)
  1452. ::CloseHandle(altFileHandle);
  1453. ::CloseHandle(mDebugEvent.u.LoadDll.hFile);
  1454. // Try to bind any breakpoints tied to this DLL
  1455. RehupBreakpoints(true);
  1456. mDebugManager->mOutMessages.push_back("modulesChanged");
  1457. }
  1458. break;
  1459. case UNLOAD_DLL_DEBUG_EVENT:
  1460. {
  1461. bool needsBreakpointRehup = false;
  1462. String name = "???";
  1463. DbgModule* dbgModule = mDebugTarget->FindDbgModuleForAddress((addr_target)(intptr)mDebugEvent.u.UnloadDll.lpBaseOfDll);
  1464. if (dbgModule != NULL)
  1465. {
  1466. name = dbgModule->mFilePath;
  1467. for (int i = 0; i < (int)mBreakpoints.size(); i++)
  1468. {
  1469. auto breakpoint = mBreakpoints[i];
  1470. auto checkBreakpoint = breakpoint;
  1471. bool hasAddr = false;
  1472. while (checkBreakpoint != NULL)
  1473. {
  1474. if ((checkBreakpoint->mAddr >= dbgModule->mImageBase) && (checkBreakpoint->mAddr < dbgModule->mImageBase + dbgModule->mImageSize))
  1475. hasAddr = true;
  1476. checkBreakpoint = (WdBreakpoint*)checkBreakpoint->mLinkedSibling;
  1477. }
  1478. if (hasAddr)
  1479. {
  1480. DetachBreakpoint(breakpoint);
  1481. needsBreakpointRehup = true;
  1482. }
  1483. }
  1484. mDebugTarget->UnloadDyn(dbgModule->mImageBase);
  1485. if (needsBreakpointRehup)
  1486. RehupBreakpoints(true);
  1487. mPendingDebugInfoLoad.Remove(dbgModule);
  1488. mPendingDebugInfoRequests.Remove(dbgModule);
  1489. mDebugManager->mOutMessages.push_back("modulesChanged");
  1490. }
  1491. if (!name.empty())
  1492. OutputMessage(StrFormat("Unloading DLL: %s @ %0s\n", name.c_str(), EncodeDataPtr((addr_target)(intptr)mDebugEvent.u.UnloadDll.lpBaseOfDll, true).c_str()));
  1493. BfLogDbg("UNLOAD_DLL_DEBUG_EVENT %s\n", name.c_str());
  1494. }
  1495. break;
  1496. case OUTPUT_DEBUG_STRING_EVENT:
  1497. {
  1498. const int maxChars = 1024 * 1024;
  1499. int len = BF_MIN(maxChars, (int)mDebugEvent.u.DebugString.nDebugStringLength); // 1MB max
  1500. char* message = new char[len + 1];
  1501. message[0] = 0;
  1502. message[len] = 0;
  1503. ReadMemory((addr_target)(intptr)mDebugEvent.u.DebugString.lpDebugStringData, len, message);
  1504. if ((mRunState == RunState_DebugEval) && (mDebuggerWaitingThread->mThreadId == mDebugEvalThreadInfo.mThreadId))
  1505. mDebugManager->mOutMessages.push_back(String("dbgEvalMsg ") + message);
  1506. else
  1507. mDebugManager->mOutMessages.push_back(String("msg ") + message);
  1508. BfLogDbg("OUTPUT_DEBUG_STRING_EVENT (BreakAddr:%@): %s\n", threadInfo->mIsAtBreakpointAddress, message);
  1509. BF_ASSERT_REL(threadInfo->mIsAtBreakpointAddress == 0);
  1510. delete [] message;
  1511. }
  1512. break;
  1513. case CREATE_THREAD_DEBUG_EVENT:
  1514. {
  1515. WdThreadInfo* threadInfo = new WdThreadInfo();
  1516. threadInfo->mProcessId = mDebugEvent.dwProcessId;
  1517. threadInfo->mThreadId = mDebugEvent.dwThreadId;
  1518. threadInfo->mHThread = mDebugEvent.u.CreateThread.hThread;
  1519. threadInfo->mThreadLocalBase = mDebugEvent.u.CreateThread.lpThreadLocalBase;
  1520. threadInfo->mStartAddress = (void*)mDebugEvent.u.CreateThread.lpStartAddress;
  1521. BF_CONTEXT lcContext;
  1522. lcContext.ContextFlags = BF_CONTEXT_CONTROL;
  1523. BF_GetThreadContext(threadInfo->mHThread, &lcContext);
  1524. threadInfo->mStartSP = BF_CONTEXT_SP(lcContext);
  1525. mThreadMap[mDebugEvent.dwThreadId] = threadInfo;
  1526. mDebuggerWaitingThread = threadInfo;
  1527. mThreadList.push_back(mDebuggerWaitingThread);
  1528. UpdateThreadDebugRegisters();
  1529. OutputMessage(StrFormat("Creating thread %d\n", mDebugEvent.dwThreadId));
  1530. }
  1531. break;
  1532. case EXIT_THREAD_DEBUG_EVENT:
  1533. {
  1534. OutputMessage(StrFormat("Exiting thread %d\n", mDebugEvent.dwThreadId));
  1535. if (mSteppingThread == threadInfo)
  1536. {
  1537. // We were attempting stepping on this thread, but not anymore!
  1538. ClearStep();
  1539. }
  1540. ::ContinueDebugEvent(mDebuggerWaitingThread->mProcessId, mDebuggerWaitingThread->mThreadId, DBG_CONTINUE);
  1541. mIsDebuggerWaiting = false;
  1542. mWantsDebugContinue = false;
  1543. if ((mRunState == RunState_DebugEval) && (mDebuggerWaitingThread->mThreadId == mDebugEvalThreadInfo.mThreadId))
  1544. {
  1545. // Thread terminated while evaluating! Is there a more graceful way of handling this?
  1546. CleanupDebugEval(false);
  1547. mRunState = RunState_Running;
  1548. }
  1549. mThreadList.Remove(mDebuggerWaitingThread);
  1550. delete mDebuggerWaitingThread;
  1551. mDebuggerWaitingThread = NULL;
  1552. mThreadMap.Remove(mDebugEvent.dwThreadId);
  1553. return true;
  1554. }
  1555. break;
  1556. case RIP_EVENT:
  1557. OutputMessage("RIP Event\n");
  1558. break;
  1559. case EXCEPTION_DEBUG_EVENT:
  1560. {
  1561. auto exceptionRecord = &mDebugEvent.u.Exception.ExceptionRecord;
  1562. switch (exceptionRecord->ExceptionCode)
  1563. {
  1564. case STATUS_WX86_BREAKPOINT:
  1565. case EXCEPTION_BREAKPOINT:
  1566. {
  1567. if (mRunState == RunState_Terminating)
  1568. {
  1569. BfLogDbg("Ignoring event because of RunState_Terminating\n");
  1570. break;
  1571. }
  1572. mAtBreakThread = threadInfo;
  1573. mActiveThread = mAtBreakThread;
  1574. bool isHighAddr = false;
  1575. #ifdef BF_DBG_32
  1576. if (((uintptr)exceptionRecord->ExceptionAddress & 0xFFFFFFFF00000000) != 0)
  1577. {
  1578. if (mActiveThread == mThreadList.front())
  1579. {
  1580. // Skip the initial Wow64 ntdll.dll!LdrpDoDebuggerBreak
  1581. mRunState = RunState_Running;
  1582. break;
  1583. }
  1584. isHighAddr = true;
  1585. }
  1586. #endif
  1587. addr_target pcAddress = (addr_target)(intptr)exceptionRecord->ExceptionAddress;
  1588. if (isHighAddr)
  1589. pcAddress = (addr_target)-1;
  1590. //mStoppedAtAddress = pcAddress;
  1591. bool isStepOut = false;
  1592. if ((mStepType == StepType_StepOut) || (mStepType == StepType_StepOut_ThenInto))
  1593. {
  1594. isStepOut = mStepBreakpointAddrs.Contains(pcAddress);
  1595. }
  1596. BF_CONTEXT lcContext;
  1597. lcContext.ContextFlags = BF_CONTEXT_ALL;
  1598. BF_GetThreadContext(threadInfo->mHThread, &lcContext);
  1599. BfLogDbg("EXCEPTION_BREAKPOINT Thread:%d %p SP:%p\n", mActiveThread->mThreadId, pcAddress, BF_CONTEXT_SP(lcContext));
  1600. uint8 origImageData = 0xCC;
  1601. mDebugTarget->ReadOrigImageData(pcAddress, &origImageData, 1);
  1602. bool wasDebugBreakpoint = origImageData != 0xCC;
  1603. DbgSubprogram* dwSubprogram = NULL;
  1604. DbgLineData* dwLineData = NULL;
  1605. if (!isStepOut)
  1606. {
  1607. dwLineData = FindLineDataAtAddress(pcAddress, &dwSubprogram, NULL, NULL, DbgOnDemandKind_LocalOnly);
  1608. if (dwSubprogram == NULL)
  1609. dwSubprogram = mDebugTarget->FindSubProgram(pcAddress, DbgOnDemandKind_LocalOnly);
  1610. }
  1611. bool isLineStart = (dwLineData != NULL) && (dwSubprogram->GetLineAddr(*dwLineData) == pcAddress);
  1612. bool isNonDebuggerBreak = false;
  1613. if (wasDebugBreakpoint)
  1614. {
  1615. // Go ahead and set EIP back one instruction
  1616. BF_CONTEXT_IP(lcContext)--;
  1617. BF_SetThreadContext(threadInfo->mHThread, &lcContext);
  1618. }
  1619. else
  1620. {
  1621. // This was an actual "break" instruction
  1622. BfLogDbg("Non-debugger break\n");
  1623. isNonDebuggerBreak = true;
  1624. auto prevState = mRunState;
  1625. // Make it an "auto" stop, so for example when we have an assert/retry we won't stop inside assembly
  1626. mRequestedStackFrameIdx = -2;
  1627. mRunState = RunState_Paused;
  1628. CheckNonDebuggerBreak();
  1629. if (IsInRunState())
  1630. {
  1631. BF_ASSERT((prevState == RunState_Running) || (prevState == RunState_DebugEval));
  1632. mRunState = prevState;
  1633. break; // Continue as if nothing happened
  1634. }
  1635. if (prevState == RunState_DebugEval)
  1636. mRequestedStackFrameIdx = -1; // Don't show a rolled back stack idx if a debug eval fails
  1637. ClearStep();
  1638. }
  1639. if (threadInfo->mIsBreakRestorePaused)
  1640. {
  1641. // The thread is supposed to be paused, but the IP has been reset
  1642. // so just break here so we'll hit that breakpoint again once we're
  1643. // actually unpaused properly
  1644. BfLogDbg("Ignoring EXCEPTION_BREAKPOINT\n", threadInfo->mThreadId);
  1645. break;
  1646. }
  1647. if ((mRunState == RunState_DebugEval) || (mRunState == RunState_HotStep))
  1648. {
  1649. // If we hit a breakpoint while doing a debug eval, we just remove the breakpoint
  1650. // and expect to reinstate it during a rehup after the evaluation has completed
  1651. WdBreakpoint* breakpoint = (WdBreakpoint*)FindBreakpointAt((uintptr_t) exceptionRecord->ExceptionAddress);
  1652. if (breakpoint != NULL)
  1653. {
  1654. mNeedsRehupBreakpoints = true;
  1655. RemoveBreakpoint(breakpoint->mLineData.GetAddress());
  1656. }
  1657. break;
  1658. }
  1659. bool isDeeper = false;
  1660. int stepBreakAddrIdx = (int)mStepBreakpointAddrs.IndexOf(pcAddress);
  1661. WdBreakpoint* breakpoint = NULL;
  1662. bool ignoreBreakpoint = false;
  1663. if ((mStepType != StepType_None) && (mSteppingThread == mAtBreakThread))
  1664. {
  1665. if (mStepType == StepType_ToTempBreakpoint)
  1666. {
  1667. RemoveTempBreakpoints();
  1668. mRunState = RunState_Paused;
  1669. break;
  1670. }
  1671. if (mContinueFromBreakpointFailed)
  1672. {
  1673. BfLogDbg("Continuing from ContinueFromBreakpointFailed\n");
  1674. SetupStep(mStepType);
  1675. mRunState = RunState_Running;
  1676. break;
  1677. }
  1678. if (!isStepOut)
  1679. breakpoint = (WdBreakpoint*)FindBreakpointAt(pcAddress);
  1680. // Ignore breakpoint if it's on the line we're stepping off of
  1681. if ((breakpoint != NULL) && (breakpoint->mAddr == mStepPC) &&
  1682. (mStepSP == BF_CONTEXT_SP(lcContext)))
  1683. {
  1684. ignoreBreakpoint = true;
  1685. }
  1686. else if ((breakpoint != NULL) && (stepBreakAddrIdx == -1) && (!CheckConditionalBreakpoint(breakpoint, dwSubprogram, pcAddress)))
  1687. {
  1688. ignoreBreakpoint = true;
  1689. }
  1690. if ((stepBreakAddrIdx == -1) && (breakpoint == NULL) && (!isNonDebuggerBreak))
  1691. {
  1692. // If a breakpoint is removed in a prior thread
  1693. BfLogDbg("Ignoring step break (old breakpoint)\n");
  1694. if ((mSteppingThread == mAtBreakThread) && (mStepSwitchedThreads))
  1695. {
  1696. SetupStep(mStepType);
  1697. }
  1698. break;
  1699. }
  1700. if ((stepBreakAddrIdx != -1) && (breakpoint == NULL) && (mSteppingThread != mActiveThread))
  1701. {
  1702. BfLogDbg("Ignoring break (wrong thread)\n");
  1703. ThreadRestorePause(mSteppingThread, mActiveThread);
  1704. threadInfo->mIsAtBreakpointAddress = pcAddress;
  1705. break;
  1706. }
  1707. isDeeper = mStepSP > BF_CONTEXT_SP(lcContext);
  1708. if ((mStepType == StepType_StepOut) || (mStepType == StepType_StepOut_ThenInto))
  1709. {
  1710. isDeeper = mStepSP >= BF_CONTEXT_SP(lcContext);
  1711. BfLogDbg("StepOut Iteration SP:%p StartSP:%p IsDeeper:%d\n", BF_CONTEXT_SP(lcContext), mStepSP, isDeeper);
  1712. }
  1713. if (((mStepType == StepType_StepOut) || (mStepType == StepType_StepOut_ThenInto)) && (breakpoint == NULL) && (isDeeper))
  1714. {
  1715. // We're encountered recursion
  1716. // Make sure we don't already have one of these stored
  1717. BF_ASSERT(mStoredReturnValueAddr == 0);
  1718. threadInfo->mIsAtBreakpointAddress = pcAddress;
  1719. break; // Don't fall through, we don't want to set mIsAtBreakpointAddress
  1720. }
  1721. if (isStepOut)
  1722. {
  1723. threadInfo->mIsAtBreakpointAddress = pcAddress;
  1724. if (mStepType == StepType_StepOut_ThenInto)
  1725. {
  1726. dwLineData = FindLineDataAtAddress(pcAddress, &dwSubprogram, NULL, NULL, DbgOnDemandKind_LocalOnly);
  1727. if ((dwLineData != NULL) && (pcAddress == dwSubprogram->GetLineAddr(*dwLineData)))
  1728. {
  1729. // Our step out from a filtered function put us at the start of a new line. Stop here
  1730. // <do nothing>
  1731. }
  1732. else
  1733. {
  1734. // .. otherwise keep going until we get to the start of a new line
  1735. SetupStep(StepType_StepInto);
  1736. mRunState = RunState_Running;
  1737. break;
  1738. }
  1739. }
  1740. if (!mStepInAssembly)
  1741. {
  1742. // Keep stepping out until we find a frame that we have source for
  1743. DbgSubprogram* dwSubprogram = NULL;
  1744. DbgLineData* dwLineData = FindLineDataAtAddress(BF_CONTEXT_IP(lcContext), &dwSubprogram);
  1745. if (dwLineData == NULL)
  1746. {
  1747. SetupStep(StepType_StepOut);
  1748. break;
  1749. }
  1750. if ((dwSubprogram != NULL) && (dwSubprogram->mInlineeInfo != NULL) && (pcAddress == dwSubprogram->mBlock.mLowPC))
  1751. {
  1752. // We've stepped out, but right into the start of an inlined method, so step out of this inlined method now...
  1753. SetupStep(StepType_StepOut);
  1754. break;
  1755. }
  1756. }
  1757. ClearStep();
  1758. mRunState = RunState_Paused;
  1759. threadInfo->mStoppedAtAddress = pcAddress;
  1760. break;
  1761. }
  1762. mRunState = RunState_Paused;
  1763. if (breakpoint != NULL)
  1764. {
  1765. // While stepping we hit a legit breakpoint
  1766. threadInfo->mIsAtBreakpointAddress = breakpoint->mAddr;
  1767. // Ignore breakpoint on return statement if we're return-stepping
  1768. mRunState = RunState_Breakpoint;
  1769. }
  1770. if ((mStepType == StepType_StepInto) && (dwSubprogram != NULL))
  1771. {
  1772. // Don't filter out the current subprogram (would break cases where we explicitly stepped into or hit breakpoint in a filtered subprogram)
  1773. bool isInStartSubprogram = (mStepStartPC >= dwSubprogram->mBlock.mLowPC) && (mStepStartPC < dwSubprogram->mBlock.mHighPC);
  1774. if ((!isInStartSubprogram) && (IsStepFiltered(dwSubprogram, dwLineData)))
  1775. {
  1776. BfLogDbg("Hit step filter\n");
  1777. mRunState = RunState_Running;
  1778. SetupStep(StepType_StepOut_ThenInto);
  1779. break;
  1780. }
  1781. }
  1782. if ((mStepType == StepType_StepOver) && (stepBreakAddrIdx == 0) && (mStepBreakpointAddrs[0] != 0) && (mStepBreakpointAddrs.size() > 1))
  1783. {
  1784. // Break was on the 'call' instruction, not the instruction after it -- means recursion
  1785. BfLogDbg("StepOver detected recursing\n");
  1786. mStepIsRecursing = true;
  1787. if (mTempBreakpoint.Remove(mStepBreakpointAddrs[0]))
  1788. {
  1789. RemoveBreakpoint(mStepBreakpointAddrs[0]);
  1790. }
  1791. mStepBreakpointAddrs[0] = 0;
  1792. mRunState = RunState_Running;
  1793. break;
  1794. }
  1795. if ((mStepType == StepType_StepOver) && (stepBreakAddrIdx > 0) && (mStepBreakpointAddrs[0] != 0) && (isDeeper))
  1796. {
  1797. // This is the first time we've hit the target breakpoint.
  1798. if (HasSteppedIntoCall())
  1799. {
  1800. mStepIsRecursing = true;
  1801. RemoveBreakpoint(mStepBreakpointAddrs[0]);
  1802. mStepBreakpointAddrs[0] = 0;
  1803. //mStepBreakpointAddrs.erase(mStepBreakpointAddrs.begin());
  1804. }
  1805. }
  1806. if ((mStepType == StepType_StepOver) && (mStepIsRecursing) && (stepBreakAddrIdx != -1) && (isDeeper))
  1807. {
  1808. // Decrement so the equality test on "step out" marks us as not being deeper when we
  1809. // hit the expected SP
  1810. BfLogDbg("Converting StepOver to StepOut\n");
  1811. mStepSP--;
  1812. mStepType = StepType_StepOut_ThenInto;
  1813. //SetupStep(StepType_StepOut);
  1814. mRunState = RunState_Running;
  1815. break;
  1816. }
  1817. if ((mStepType == StepType_StepOver) && (!ignoreBreakpoint) && (breakpoint == NULL) && (!mStepInAssembly))
  1818. {
  1819. // Test for stepping over inline method
  1820. DbgSubprogram* dwSubprogram = mDebugTarget->FindSubProgram(pcAddress);
  1821. // mTempBreakpoints will have 2 entries if we are on a 'call' line. If we have an inlined call immediately following a call, then we
  1822. // assume we're hitting a return break
  1823. /*if ((dwSubprogram != NULL) && (dwSubprogram->mInlineParent != NULL) && (pcAddress == dwSubprogram->mBlock.mLowPC) && (mTempBreakpoint.size() < 2))
  1824. {
  1825. BfLogDbg("Attempting StepOver of inlined method\n");
  1826. SetupStep(StepType_StepOut);
  1827. mRunState = RunState_Running;
  1828. break;
  1829. } */
  1830. //TODO: The previous logic with the "(mTempBreakpoint.size() < 2)" was causing Try!(Method()); stepovers to enter into Try!. What did we mean by
  1831. // "assume we're hitting a return break"?
  1832. if ((dwSubprogram != NULL) && (dwSubprogram->mInlineeInfo != NULL) && (pcAddress == dwSubprogram->mBlock.mLowPC))
  1833. {
  1834. RemoveTempBreakpoints();
  1835. BfLogDbg("Attempting StepOver of inlined method\n");
  1836. SetupStep(StepType_StepOut);
  1837. mRunState = RunState_Running;
  1838. break;
  1839. }
  1840. }
  1841. if (mStepType == StepType_StepOut_Inline)
  1842. {
  1843. if (mOrigStepType == StepType_StepOver)
  1844. {
  1845. // For the step over, if we are still inside the source line after an inline then step over again...
  1846. DbgSubprogram* origSubprogram = NULL;
  1847. auto origLineData = FindLineDataAtAddress(mStepStartPC, &origSubprogram);
  1848. DbgSubprogram* curSubprogram = NULL;
  1849. auto curLineData = FindLineDataAtAddress(pcAddress, &curSubprogram);
  1850. if ((origLineData != NULL) &&
  1851. ((origLineData == curLineData) ||
  1852. ((origSubprogram == curSubprogram) && (origLineData->mLine == curLineData->mLine))))
  1853. {
  1854. mRunState = RunState_Running;
  1855. SetupStep(StepType_StepOver);
  1856. break;
  1857. }
  1858. }
  1859. ClearStep();
  1860. break;
  1861. }
  1862. if ((mStepType != StepType_None) && (ignoreBreakpoint) && (!mStepInAssembly) && (stepBreakAddrIdx == -1))
  1863. {
  1864. // Ignore breakpoint by just continuing...
  1865. mRunState = RunState_Running;
  1866. break;
  1867. }
  1868. RemoveTempBreakpoints();
  1869. if ((mStepType != StepType_None) && (!mStepInAssembly) && (!isLineStart) && (stepBreakAddrIdx != -1))
  1870. {
  1871. SetupStep(mStepType);
  1872. mRunState = RunState_Running;
  1873. }
  1874. else
  1875. {
  1876. //if (mStepType != StepType_Return)
  1877. if (stepBreakAddrIdx != -1)
  1878. {
  1879. // Even if we've detected we're at a breakpoint, we mark ourselves as just stepping if we also
  1880. // have a step breakpoint here
  1881. StepLineTryPause(pcAddress, true);
  1882. }
  1883. if (mRunState == RunState_Paused)
  1884. ClearStep();
  1885. }
  1886. if (ignoreBreakpoint)
  1887. {
  1888. SetupStep(mStepType);
  1889. mRunState = RunState_Running;
  1890. }
  1891. if ((mRunState == RunState_Paused) && (breakpoint != NULL))
  1892. {
  1893. // Just do the 'check' here so we can do the logging/condition stuff
  1894. CheckConditionalBreakpoint(breakpoint, dwSubprogram, pcAddress);
  1895. }
  1896. }
  1897. else
  1898. {
  1899. breakpoint = (WdBreakpoint*)FindBreakpointAt((uintptr_t)exceptionRecord->ExceptionAddress);
  1900. if ((breakpoint != NULL) && (!CheckConditionalBreakpoint(breakpoint, dwSubprogram, pcAddress)))
  1901. {
  1902. BfLogDbg("Skipping conditional breakpoint. Setting mIsAtBreakpointAddress = %p\n", breakpoint->mAddr);
  1903. threadInfo->mIsAtBreakpointAddress = breakpoint->mAddr;
  1904. mRunState = RunState_Running;
  1905. break;
  1906. }
  1907. if (breakpoint != NULL)
  1908. {
  1909. BfLogDbg("Breakpoint hit. mIsAtBreakpointAddress = %p\n", breakpoint->mAddr);
  1910. threadInfo->mIsAtBreakpointAddress = breakpoint->mAddr;
  1911. mRunState = RunState_Breakpoint;
  1912. }
  1913. else if ((stepBreakAddrIdx != -1) || (isNonDebuggerBreak))
  1914. {
  1915. if (mRunState != RunState_DebugEval)
  1916. {
  1917. // Was in mStepBreakpointAddrs list
  1918. if ((isNonDebuggerBreak) || (mStepType == StepType_None) || (mSteppingThread == mAtBreakThread))
  1919. {
  1920. BfLogDbg("Hit mStepBreakpointAddrs breakpoint\n");
  1921. mRunState = RunState_Paused;
  1922. }
  1923. else
  1924. {
  1925. BfLogDbg("Ignored mStepBreakpointAddrs breakpoint (wrong thread)\n");
  1926. mRunState = RunState_Running;
  1927. }
  1928. }
  1929. }
  1930. else
  1931. {
  1932. BfLogDbg("Ignoring break (old or ignored breakpoint)\n");
  1933. mRunState = RunState_Running;
  1934. }
  1935. }
  1936. if ((breakpoint != NULL) && (!ignoreBreakpoint))
  1937. {
  1938. mActiveBreakpoint = breakpoint;
  1939. mBreakStackFrameIdx = -1;
  1940. }
  1941. if ((mRunState == RunState_Paused) || (mRunState == RunState_Breakpoint))
  1942. threadInfo->mStoppedAtAddress = pcAddress;
  1943. }
  1944. break;
  1945. case STATUS_WX86_SINGLE_STEP:
  1946. case EXCEPTION_SINGLE_STEP:
  1947. {
  1948. if (mRunState == RunState_Terminating)
  1949. {
  1950. BfLogDbg("Ignoring event because of RunState_Terminating\n");
  1951. break;
  1952. }
  1953. if ((mStepSwitchedThreads) && (mActiveThread == mSteppingThread) && (mActiveThread->mIsAtBreakpointAddress != NULL))
  1954. {
  1955. ContinueFromBreakpoint();
  1956. break;
  1957. }
  1958. if (mRunState == RunState_HotStep)
  1959. {
  1960. BF_ASSERT(mActiveThread == mDebuggerWaitingThread);
  1961. mRunState = RunState_Paused;
  1962. break;
  1963. }
  1964. mActiveThread = mDebuggerWaitingThread;
  1965. BF_CONTEXT lcContext;
  1966. lcContext.ContextFlags = BF_CONTEXT_ALL;
  1967. BF_GetThreadContext(mActiveThread->mHThread, &lcContext);
  1968. addr_target pcAddress = BF_CONTEXT_IP(lcContext);
  1969. bool wasUnfilteredStep = mStepType == StepType_StepInto_Unfiltered;
  1970. if (mStepType == StepType_StepInto_UnfilteredSingle)
  1971. {
  1972. wasUnfilteredStep = true;
  1973. mStepType = StepType_StepInto;
  1974. mStepStartPC = pcAddress;
  1975. }
  1976. BfLogDbg("EXCEPTION_SINGLE_STEP Thread:%d PC:%p\n", mActiveThread->mThreadId, exceptionRecord->ExceptionAddress);
  1977. if (lcContext.Dr6 & 0x0F) // Memory breakpoint hit
  1978. {
  1979. WdBreakpoint* foundBreakpoint = NULL;
  1980. for (int memoryWatchSlot = 0; memoryWatchSlot < 4; memoryWatchSlot++)
  1981. {
  1982. if ((lcContext.Dr6 & ((intptr_target)1 << memoryWatchSlot)) != 0)
  1983. {
  1984. foundBreakpoint = mMemoryBreakpoints[memoryWatchSlot].mBreakpoint;
  1985. break;
  1986. }
  1987. }
  1988. BF_ASSERT(foundBreakpoint != NULL);
  1989. DbgSubprogram* subprogram = mDebugTarget->FindSubProgram(pcAddress);
  1990. if (CheckConditionalBreakpoint(foundBreakpoint, subprogram, pcAddress))
  1991. {
  1992. if (foundBreakpoint != NULL)
  1993. {
  1994. mDebugManager->mOutMessages.push_back(StrFormat("memoryBreak %s", EncodeDataPtr(foundBreakpoint->mMemoryBreakpointInfo->mMemoryAddress, false).c_str()));
  1995. mRunState = RunState_Paused;
  1996. }
  1997. mActiveBreakpoint = foundBreakpoint;
  1998. mBreakStackFrameIdx = -1;
  1999. RemoveTempBreakpoints();
  2000. BfLogDbg("Memory breakpoint hit: %p\n", foundBreakpoint);
  2001. }
  2002. break;
  2003. }
  2004. if ((mRunState == RunState_DebugEval) && (mDebugEvalThreadInfo.mThreadId == mDebuggerWaitingThread->mThreadId))
  2005. {
  2006. if ((addr_target)(intptr)exceptionRecord->ExceptionAddress == mDebugEvalSetRegisters.GetPC())
  2007. {
  2008. // This indicates we are returning from kernel mode and our registers are clobbered
  2009. SetRegisters(&mDebugEvalSetRegisters);
  2010. }
  2011. break;
  2012. }
  2013. bool hadBreakpointContinue = true;
  2014. if (threadInfo->mBreakpointAddressContinuing != 0)
  2015. {
  2016. bool wantsBreakpoint = WantsBreakpointAt(threadInfo->mBreakpointAddressContinuing);
  2017. BfLogDbg("Continuing breakpoint at %p WantsReset:%d\n", threadInfo->mBreakpointAddressContinuing, wantsBreakpoint);
  2018. if (wantsBreakpoint)
  2019. {
  2020. PhysSetBreakpoint(threadInfo->mBreakpointAddressContinuing);
  2021. }
  2022. threadInfo->mBreakpointAddressContinuing = NULL;
  2023. hadBreakpointContinue = true;
  2024. ThreadRestoreUnpause();
  2025. }
  2026. if ((mSteppingThread != NULL) && (mSteppingThread != mActiveThread))
  2027. {
  2028. // This SINGLE_STEP happened in the wrong thread - we need the stepping thread to do the stepping!
  2029. // Try again.
  2030. mActiveThread = mSteppingThread;
  2031. SingleStepX86();
  2032. break;
  2033. }
  2034. bool isDeeper = mStepSP > BF_CONTEXT_SP(lcContext);
  2035. if ((mStepSwitchedThreads) && (mStepType == StepType_StepOver) && (isDeeper))
  2036. {
  2037. if (HasSteppedIntoCall())
  2038. {
  2039. // Since we switched threads, we needed to do a hardware step which has placed us inside a
  2040. // call, so we need to step out of that now...
  2041. SetupStep(StepType_StepOut_NoFrame);
  2042. break;
  2043. }
  2044. }
  2045. // If we don't have a mStepBreakpointAddrs set, that means we're stepping through individual instructions --
  2046. // so process the new location here
  2047. if (((mStepType == StepType_StepInto) || (mStepType == StepType_StepInto_Unfiltered) || (mStepType == StepType_StepOver)) && (mStepBreakpointAddrs.size() == 0))
  2048. {
  2049. DbgSubprogram* dwSubprogram = NULL;
  2050. DbgLineData* dwLineData = FindLineDataAtAddress(pcAddress, &dwSubprogram, NULL, NULL, DbgOnDemandKind_LocalOnly);
  2051. if ((dwSubprogram != NULL) && (pcAddress == dwSubprogram->mBlock.mLowPC) && (dwSubprogram->mWasHotReplaced))
  2052. {
  2053. BfLogDbg("Stepping through hot thunk\n");
  2054. mRunState = RunState_Running;
  2055. SingleStepX86();
  2056. break;
  2057. }
  2058. if ((mStepType == StepType_StepOver) && (!mStepInAssembly))
  2059. {
  2060. if ((dwSubprogram != NULL) && (dwSubprogram->mInlineeInfo != NULL) && (pcAddress == dwSubprogram->mBlock.mLowPC))
  2061. {
  2062. BfLogDbg("Attempting StepOver of inlined method - SingleStep\n");
  2063. SetupStep(StepType_StepOut);
  2064. mRunState = RunState_Running;
  2065. break;
  2066. }
  2067. }
  2068. // Column of -1 means "Illegal", keep stepping!
  2069. if ((mStepInAssembly) ||
  2070. ((dwLineData != NULL) && (dwLineData->IsStackFrameSetup()) && (dwLineData->mColumn >= 0) &&
  2071. ((dwSubprogram->GetLineAddr(*dwLineData) == pcAddress) || (mStepStopOnNextInstruction))))
  2072. {
  2073. // Hit a line while stepping, we're done!
  2074. mRunState = RunState_Paused;
  2075. StepLineTryPause(pcAddress, false);
  2076. if (mRunState == RunState_Paused)
  2077. {
  2078. if ((mStepType == StepType_StepInto) && (!wasUnfilteredStep) && (!mStepInAssembly) && (dwSubprogram != NULL))
  2079. {
  2080. // Don't filter out the current subprogram (would break cases where we explicitly stepped into or hit breakpoint in a filtered subprogram)
  2081. bool isInStartSubprogram = (mStepStartPC >= dwSubprogram->mBlock.mLowPC) && (mStepStartPC < dwSubprogram->mBlock.mHighPC);
  2082. if ((!isInStartSubprogram) && (IsStepFiltered(dwSubprogram, dwLineData)))
  2083. {
  2084. BfLogDbg("Hit step filter (2)\n");
  2085. mRunState = RunState_Running;
  2086. SetupStep(StepType_StepOut_ThenInto);
  2087. break;
  2088. }
  2089. }
  2090. ClearStep();
  2091. mCurNoInfoStepTries = 0; // Reset
  2092. }
  2093. else
  2094. SetupStep(mStepType);
  2095. }
  2096. else if (dwSubprogram != NULL)
  2097. {
  2098. if ((dwSubprogram->mWasHotReplaced) && ((mStepType == StepType_StepInto) || (mStepType == StepType_StepInto_Unfiltered)))
  2099. {
  2100. SingleStepX86();
  2101. }
  2102. else
  2103. {
  2104. // Inside a line's instruction, keep going
  2105. SetupStep(mStepType);
  2106. mCurNoInfoStepTries = 0; // Reset
  2107. }
  2108. }
  2109. else if (mStepType == StepType_StepInto_Unfiltered)
  2110. {
  2111. CPUInst inst;
  2112. if (mDebugTarget->DecodeInstruction(pcAddress, &inst))
  2113. {
  2114. if (inst.IsBranch())
  2115. {
  2116. auto target = inst.GetTarget();
  2117. if (target != 0)
  2118. {
  2119. DbgSubprogram* destSubprogram = mDebugTarget->FindSubProgram(target);
  2120. if ((destSubprogram != NULL) && (target == destSubprogram->mBlock.mLowPC))
  2121. {
  2122. // We're jumping to an actual subprogram, so continue stepping here
  2123. mStepType = StepType_StepInto_UnfilteredSingle;
  2124. SingleStepX86();
  2125. break;
  2126. }
  2127. }
  2128. }
  2129. }
  2130. // We requested to step into this method so stop here even if we don't have source
  2131. mRunState = RunState_Paused;
  2132. }
  2133. else
  2134. {
  2135. // No debug info!
  2136. bool doStepOut = false;
  2137. if (mCurNoInfoStepTries < 16)
  2138. {
  2139. mCurNoInfoStepTries++;
  2140. BfLogDbg("NoInfoStepTries: %d\n", mCurNoInfoStepTries);
  2141. if (!SetupStep(mStepType))
  2142. doStepOut = true;
  2143. }
  2144. else
  2145. doStepOut = true;
  2146. if (doStepOut)
  2147. {
  2148. // Step out of current call.
  2149. mStepSP = 0;
  2150. SetupStep(StepType_StepOut_NoFrame);
  2151. // Aggressive stepout - don't monitor BP
  2152. mStepSP = 0;
  2153. }
  2154. }
  2155. }
  2156. else if (!hadBreakpointContinue)
  2157. {
  2158. BF_DBG_FATAL("EXCEPTION_SINGLE_STEP bad debugger state");
  2159. }
  2160. if (mRunState == RunState_Paused)
  2161. threadInfo->mStoppedAtAddress = pcAddress;
  2162. }
  2163. break;
  2164. default:
  2165. {
  2166. bool isSystemException =
  2167. (exceptionRecord->ExceptionCode >= STATUS_ACCESS_VIOLATION) &&
  2168. (exceptionRecord->ExceptionCode <= STATUS_ASSERTION_FAILURE);
  2169. bool isFirstChance = mDebugEvent.u.Exception.dwFirstChance != 0;
  2170. bool handled = false;
  2171. //TODO: Use a user-defined filter here to determine whether to stop or continue
  2172. if ((!isSystemException) && (isFirstChance))
  2173. {
  2174. if (exceptionRecord->ExceptionCode == 0x406D1388) // Visual C
  2175. {
  2176. if ((int32)exceptionRecord->ExceptionInformation[0] == 0x1000)
  2177. {
  2178. struct THREADNAME_INFO
  2179. {
  2180. DWORD dwType; // Must be 0x1000.
  2181. LPCSTR szName; // Pointer to name (in user addr space).
  2182. DWORD dwThreadID; // Thread ID (-1=caller thread).
  2183. DWORD dwFlags; // Reserved for future use, must be zero.
  2184. };
  2185. THREADNAME_INFO* threadNameInfo = (THREADNAME_INFO*)exceptionRecord->ExceptionInformation;
  2186. DwFormatInfo formatInfo;
  2187. formatInfo.mRawString = true;
  2188. String nameStr = ReadString(DbgType_SChar, (intptr)threadNameInfo->szName, false, 1024, formatInfo);
  2189. WdThreadInfo* namingThreadInfo = threadInfo;
  2190. if (threadNameInfo->dwThreadID != (DWORD)-1)
  2191. {
  2192. namingThreadInfo = NULL;
  2193. mThreadMap.TryGetValue(threadNameInfo->dwThreadID, &namingThreadInfo);
  2194. }
  2195. if (namingThreadInfo != NULL)
  2196. {
  2197. namingThreadInfo->mName = nameStr;
  2198. FilterThreadName(namingThreadInfo->mName);
  2199. }
  2200. }
  2201. else if (((int32)exceptionRecord->ExceptionInformation[0] == 0x1001) && ((int32)exceptionRecord->ExceptionInformation[1] == 0x1002))
  2202. {
  2203. struct FailMessage
  2204. {
  2205. addr_target mPtr0; // Unknown
  2206. addr_target mPtr1; // 0
  2207. addr_target mPtr2; // 0
  2208. addr_target mPtr3; // Unknown
  2209. addr_target mErrorStr;
  2210. };
  2211. FailMessage failMessage = ReadMemory<FailMessage>(exceptionRecord->ExceptionInformation[2]);
  2212. DwFormatInfo formatInfo;
  2213. String failStr = ReadString(DbgType_SChar16, failMessage.mErrorStr, false, 8192, formatInfo);
  2214. mDebugManager->mOutMessages.push_back(StrFormat("error Run-Time Check Failure %d - %s", exceptionRecord->ExceptionInformation[6], failStr.c_str()));
  2215. mRunState = RunState_Paused;
  2216. mRequestedStackFrameIdx = -2; // -2 = "auto"
  2217. handled = true;
  2218. }
  2219. }
  2220. if (!handled)
  2221. {
  2222. OutputMessage(StrFormat("Skipping first chance exception %08Xd at address %@ in thread %d\n", exceptionRecord->ExceptionCode, exceptionRecord->ExceptionAddress, threadInfo->mThreadId));
  2223. ::ContinueDebugEvent(mDebuggerWaitingThread->mProcessId, mDebuggerWaitingThread->mThreadId, DBG_EXCEPTION_NOT_HANDLED);
  2224. mIsDebuggerWaiting = false;
  2225. }
  2226. }
  2227. else
  2228. {
  2229. BfLogDbg("EXCEPTION in thread %d at %p\n", threadInfo->mThreadId, exceptionRecord->ExceptionAddress);
  2230. OutputDebugStrF("EXCEPTION\n");
  2231. mActiveThread = threadInfo;
  2232. memcpy(&mCurException, exceptionRecord, sizeof(EXCEPTION_RECORD));
  2233. if (mRunState == RunState_DebugEval)
  2234. {
  2235. if ((intptr)mCurException.ExceptionAddress == 42)
  2236. {
  2237. BfLogDbg("RunState_DebugEval_Done\n");
  2238. OutputDebugStrF(" RunState_DebugEval_Done\n");
  2239. }
  2240. else
  2241. {
  2242. BfLogDbg("Exception at 0x%@ in thread %d, exception code 0x%08X",
  2243. mCurException.ExceptionAddress, mActiveThread->mThreadId, mCurException.ExceptionCode);
  2244. mDebugPendingExpr->mException = StrFormat("Exception at 0x%@ in thread %d, exception code 0x%08X",
  2245. mCurException.ExceptionAddress, mActiveThread->mThreadId, mCurException.ExceptionCode);
  2246. }
  2247. mRunState = RunState_DebugEval_Done;
  2248. mExplicitStopThread = mActiveThread;
  2249. mRequestedStackFrameIdx = mDebugPendingExpr->mCallStackIdx;
  2250. }
  2251. else
  2252. {
  2253. mRunState = RunState_Exception;
  2254. }
  2255. }
  2256. }
  2257. break;
  2258. }
  2259. }
  2260. break;
  2261. }
  2262. if ((mDebugEvalThreadInfo.mThreadId != 0) && (mRunState != RunState_DebugEval) && (mRunState != RunState_DebugEval_Done))
  2263. {
  2264. CleanupDebugEval();
  2265. }
  2266. // Stepping done?
  2267. if (mStepType == StepType_None)
  2268. {
  2269. mLastValidStepIntoPC = 0;
  2270. }
  2271. BF_ASSERT(mDebuggerWaitingThread != NULL);
  2272. return true;
  2273. }
  2274. void WinDebugger::Update()
  2275. {
  2276. AutoCrit autoCrit(mDebugManager->mCritSect);
  2277. // if (mRunState == RunState_DebugEval)
  2278. // ContinueDebugEvent();
  2279. if (mRunState == RunState_DebugEval_Done)
  2280. {
  2281. if (mDebugPendingExpr != NULL)
  2282. {
  2283. mDebugPendingExpr->mIdleTicks++;
  2284. if (mDebugPendingExpr->mIdleTicks >= 2)
  2285. {
  2286. BfLogDbg("Finishing pending expr in thread %d\n", mDebugEvalThreadInfo.mThreadId);
  2287. mRunState = RunState_Paused;
  2288. CleanupDebugEval();
  2289. }
  2290. }
  2291. }
  2292. else if (mDebugPendingExpr != NULL)
  2293. {
  2294. mDebugPendingExpr->mIdleTicks = 0;
  2295. }
  2296. }
  2297. void WinDebugger::ContinueDebugEvent()
  2298. {
  2299. AutoCrit autoCrit(mDebugManager->mCritSect);
  2300. BF_ASSERT(mRunState != RunState_DebugEval_Done);
  2301. if (!mWantsDebugContinue)
  2302. return;
  2303. if (!TryRunContinue())
  2304. return;
  2305. // if ((mRunState == RunState_DebugEval) && (mDebuggerWaitingThread->mThreadId != mDebugEvalThreadInfo.mThreadId))
  2306. // {
  2307. // // Don't process the 'mIsAtBreakpointAddress' stuff
  2308. // mWantsDebugContinue = false;
  2309. // mContinueEvent.Set();
  2310. // return;
  2311. // }
  2312. if ((mDebuggerWaitingThread->mIsAtBreakpointAddress == 0) && (mDebuggerWaitingThread->mStoppedAtAddress != 0))
  2313. {
  2314. auto breakpoint = FindBreakpointAt(mDebuggerWaitingThread->mStoppedAtAddress);
  2315. if (breakpoint != NULL)
  2316. {
  2317. mDebuggerWaitingThread->mIsAtBreakpointAddress = mDebuggerWaitingThread->mStoppedAtAddress;
  2318. }
  2319. }
  2320. if (mDebuggerWaitingThread->mIsAtBreakpointAddress != 0)
  2321. {
  2322. if (!ContinueFromBreakpoint())
  2323. {
  2324. BfLogDbg("ContinueFromBreakpoint failed\n");
  2325. ClearCallStack();
  2326. mDebuggerWaitingThread->mStoppedAtAddress = 0;
  2327. mDebuggerWaitingThread->mIsAtBreakpointAddress = 0;
  2328. mWantsDebugContinue = false;
  2329. mContinueFromBreakpointFailed = true;
  2330. mContinueEvent.Set();
  2331. return;
  2332. }
  2333. }
  2334. if ((mRunState == RunState_Breakpoint) || (mRunState == RunState_Paused))
  2335. {
  2336. ClearCallStack();
  2337. mRunState = RunState_Running;
  2338. }
  2339. mDebuggerWaitingThread->mStoppedAtAddress = 0;
  2340. mWantsDebugContinue = false;
  2341. BF_ASSERT_REL(mDebuggerWaitingThread->mIsAtBreakpointAddress == 0);
  2342. mContinueEvent.Set();
  2343. }
  2344. static BOOL CALLBACK WdEnumWindowsProc(HWND hwnd, LPARAM lParam)
  2345. {
  2346. HWND owner = GetWindow(hwnd, GW_OWNER);
  2347. if (!IsWindowVisible(hwnd))
  2348. return TRUE;
  2349. DWORD processId = 0;
  2350. DWORD threadId = GetWindowThreadProcessId(hwnd, &processId);
  2351. if (processId != ((WinDebugger*)gDebugger)->mProcessInfo.dwProcessId)
  2352. return TRUE;
  2353. SetForegroundWindow(hwnd);
  2354. return TRUE;
  2355. }
  2356. void WinDebugger::ForegroundTarget()
  2357. {
  2358. EnumWindows(WdEnumWindowsProc, 0);
  2359. }
  2360. static int gFindLineDataAt = 0;
  2361. DbgLineData* WinDebugger::FindLineDataAtAddress(addr_target address, DbgSubprogram** outSubProgram, DbgSrcFile** outSrcFile, int* outLineIdx, DbgOnDemandKind onDemandKind)
  2362. {
  2363. gFindLineDataAt++;
  2364. BP_ZONE("WinDebugger::FindLineDataAtAddress");
  2365. auto dwSubprogram = mDebugTarget->FindSubProgram((addr_target)address, onDemandKind);
  2366. if (dwSubprogram == NULL)
  2367. return NULL;
  2368. FixupLineDataForSubprogram(dwSubprogram);
  2369. auto lineData = dwSubprogram->FindClosestLine(address, outSubProgram, outSrcFile, outLineIdx);
  2370. return lineData;
  2371. }
  2372. DbgLineData* WinDebugger::FindLineDataInSubprogram(addr_target address, DbgSubprogram* dwSubprogram)
  2373. {
  2374. auto dwCompileUnit = dwSubprogram->mCompileUnit;
  2375. FixupLineDataForSubprogram(dwSubprogram);
  2376. auto lineData = dwSubprogram->FindClosestLine(address);
  2377. return lineData;
  2378. }
  2379. bool WinDebugger::IsStepFiltered(DbgSubprogram* dbgSubprogram, DbgLineData* dbgLineData)
  2380. {
  2381. if (mIsStepIntoSpecific)
  2382. return false;
  2383. if (dbgSubprogram->mStepFilterVersion != mDebugManager->mStepFilterVersion)
  2384. {
  2385. String filterName;
  2386. CreateFilterName(filterName, dbgSubprogram);
  2387. dbgSubprogram->PopulateSubprogram();
  2388. bool doDefault = false;
  2389. StepFilter* stepFilterPtr;
  2390. if (mDebugManager->mStepFilters.TryGetValue(filterName, &stepFilterPtr))
  2391. {
  2392. switch (stepFilterPtr->mFilterKind)
  2393. {
  2394. case BfStepFilterKind_Default:
  2395. doDefault = true;
  2396. break;
  2397. case BfStepFilterKind_Filtered:
  2398. dbgSubprogram->mIsStepFiltered = true;
  2399. break;
  2400. case BfStepFilterKind_NotFiltered:
  2401. dbgSubprogram->mIsStepFiltered = false;
  2402. break;
  2403. }
  2404. }
  2405. else
  2406. {
  2407. doDefault = true;
  2408. }
  2409. if (doDefault)
  2410. {
  2411. dbgSubprogram->mIsStepFiltered = dbgSubprogram->mIsStepFilteredDefault;
  2412. }
  2413. dbgSubprogram->mStepFilterVersion = mDebugManager->mStepFilterVersion;
  2414. }
  2415. if (!dbgSubprogram->mIsStepFiltered)
  2416. {
  2417. if (dbgLineData != NULL)
  2418. {
  2419. auto dbgSrcFile = dbgSubprogram->GetLineSrcFile(*dbgLineData);
  2420. if (dbgSrcFile->mStepFilterVersion != mDebugManager->mStepFilterVersion)
  2421. {
  2422. dbgSrcFile->mFileExistKind = dbgSubprogram->mCompileUnit->mDbgModule->CheckSourceFileExist(dbgSrcFile->GetLocalPath());
  2423. dbgSrcFile->mStepFilterVersion = mDebugManager->mStepFilterVersion;
  2424. }
  2425. switch (dbgSrcFile->mFileExistKind)
  2426. {
  2427. case DbgFileExistKind_NotFound:
  2428. return true;
  2429. case DbgFileExistKind_HasOldSourceCommand:
  2430. if (mDebugManager->mStepOverExternalFiles)
  2431. return true;
  2432. }
  2433. }
  2434. }
  2435. return dbgSubprogram->mIsStepFiltered;
  2436. }
  2437. void WinDebugger::RemoveTempBreakpoints()
  2438. {
  2439. BfLogDbg("RemoveTempBreakpoints\n");
  2440. for (auto address : mTempBreakpoint)
  2441. {
  2442. RemoveBreakpoint(address);
  2443. // if (FindBreakpointAt(address) == NULL)
  2444. // {
  2445. // RemoveBreakpoint(address);
  2446. // }
  2447. // else
  2448. // {
  2449. // BfLogDbg("Ignoring remove on temp breakpoint %p\n", address);
  2450. // }
  2451. }
  2452. mTempBreakpoint.Clear();
  2453. mStepBreakpointAddrs.Clear();
  2454. }
  2455. void WinDebugger::RehupBreakpoints(bool doFlush)
  2456. {
  2457. BfLogDbg("RehupBreakpoints\n");
  2458. // First pass- detach breakpoints that need to be rebound
  2459. for (int i = 0; i < (int)mBreakpoints.size(); i++)
  2460. {
  2461. auto breakpoint = mBreakpoints[i];
  2462. while (breakpoint != NULL)
  2463. {
  2464. if (((breakpoint->mSrcFile != NULL) && (breakpoint->mSrcFile->mDeferredRefs.size() > 0)) ||
  2465. (!breakpoint->mSymbolName.IsEmpty()))
  2466. {
  2467. // This breakpoint was already bound, but we loaded a debug module that also had this file so rebind it
  2468. DetachBreakpoint(breakpoint);
  2469. }
  2470. breakpoint = (WdBreakpoint*)breakpoint->mLinkedSibling;
  2471. }
  2472. }
  2473. // Second pass- actually set breakpoints
  2474. for (int i = 0; i < (int)mBreakpoints.size(); i++)
  2475. {
  2476. auto breakpoint = mBreakpoints[i];
  2477. while (breakpoint != NULL)
  2478. {
  2479. CheckBreakpoint(breakpoint);
  2480. if (breakpoint->mAddr != 0)
  2481. SetBreakpoint(breakpoint->mAddr, true);
  2482. breakpoint = (WdBreakpoint*)breakpoint->mLinkedSibling;
  2483. }
  2484. }
  2485. mNeedsRehupBreakpoints = false;
  2486. }
  2487. bool WinDebugger::WantsBreakpointAt(addr_target address)
  2488. {
  2489. if (mTempBreakpoint.Contains(address))
  2490. return true;
  2491. for (auto breakpoint : mBreakpoints)
  2492. {
  2493. WdBreakpoint* checkBreakpoint = breakpoint;
  2494. while (checkBreakpoint != NULL)
  2495. {
  2496. if (address == checkBreakpoint->mAddr)
  2497. return true;
  2498. checkBreakpoint = (WdBreakpoint*)checkBreakpoint->mLinkedSibling;
  2499. }
  2500. }
  2501. return false;
  2502. }
  2503. void WinDebugger::CheckBreakpoint(WdBreakpoint* wdBreakpoint, DbgSrcFile* srcFile, int lineNum, int hotIdx)
  2504. {
  2505. BP_ZONE("WinDebugger::CheckBreakpoint:atLoc");
  2506. if (hotIdx == -1)
  2507. {
  2508. BF_ASSERT(wdBreakpoint->mPendingHotBindIdx == -1);
  2509. }
  2510. WdBreakpoint* headBreakpoint = wdBreakpoint;
  2511. headBreakpoint->mPendingHotBindIdx = -1;
  2512. bool foundInSequence = false;
  2513. DbgSubprogram* lastFoundSubprogram = NULL;
  2514. int highestHotIdx = -1;
  2515. bool foundLine = false;
  2516. int bestLineNum = -1;
  2517. int bestLineOffset = 0x7FFFFFFF;
  2518. auto _CheckLineInfo = [&](DbgSubprogram* dbgSubprogram, DbgLineInfo* dbgLineInfo)
  2519. {
  2520. // Scan first so we can determine if we want to do fix up line data or not.
  2521. bool hasNear = false;
  2522. int maxLineDist = 6;
  2523. for (int lineIdx = 0; lineIdx < dbgLineInfo->mLines.mSize; lineIdx++)
  2524. {
  2525. auto lineData = &dbgLineInfo->mLines[lineIdx];
  2526. auto& ctx = dbgLineInfo->mContexts[lineData->mCtxIdx];
  2527. if (ctx.mSrcFile != srcFile)
  2528. continue;
  2529. int lineOffset = lineData->mLine - lineNum;
  2530. if ((lineOffset >= 0) && (lineOffset <= maxLineDist))
  2531. hasNear = true;
  2532. }
  2533. if (!hasNear)
  2534. return;
  2535. FixupLineDataForSubprogram(dbgSubprogram);
  2536. for (int lineIdx = 0; lineIdx < dbgLineInfo->mLines.mSize; lineIdx++)
  2537. {
  2538. //TODO: Do fixup lineData... ?
  2539. auto lineData = &dbgLineInfo->mLines[lineIdx];
  2540. auto& ctx = dbgLineInfo->mContexts[lineData->mCtxIdx];
  2541. if (ctx.mSrcFile != srcFile)
  2542. continue;
  2543. // if (ctx.mInlinee != NULL)
  2544. // {
  2545. // if (lineIdx + 1 < dbgLineInfo->mLines.mSize)
  2546. // {
  2547. // auto nextLineData = &dbgLineInfo->mLines[lineIdx + 1];
  2548. // if (nextLineData->mRelAddress == lineData->mRelAddress)
  2549. // {
  2550. // // Use the later entry (same logic from DisassembleAt)
  2551. // continue;
  2552. // }
  2553. // }
  2554. // }
  2555. if ((lineData->mColumn == -1) && (wdBreakpoint->mInstrOffset == -1))
  2556. continue;
  2557. int lineOffset = lineData->mLine - lineNum;
  2558. if (lineOffset == 0)
  2559. {
  2560. foundLine = true;
  2561. auto address = dbgSubprogram->GetLineAddr(*lineData);
  2562. auto subProgram = mDebugTarget->FindSubProgram(address);
  2563. if (subProgram->mNeedLineDataFixup)
  2564. FixupLineDataForSubprogram(subProgram);
  2565. if (subProgram != NULL)
  2566. highestHotIdx = BF_MAX(highestHotIdx, subProgram->mCompileUnit->mDbgModule->mHotIdx);
  2567. if ((foundInSequence) && (subProgram != lastFoundSubprogram))
  2568. foundInSequence = false;
  2569. if ((subProgram->mWasHotReplaced) && (address < subProgram->mBlock.mLowPC + sizeof(HotJumpOp)))
  2570. {
  2571. // If this breakpoint ends up on the hot jmp instruction
  2572. continue;
  2573. }
  2574. if (!foundInSequence)
  2575. {
  2576. lastFoundSubprogram = subProgram;
  2577. if ((subProgram != NULL) && (subProgram->mWasHotReplaced) && (address == subProgram->mBlock.mLowPC))
  2578. {
  2579. // This instruction is actually the hot jump, we don't need a breakpoint here
  2580. foundInSequence = true;
  2581. continue;
  2582. }
  2583. if (wdBreakpoint->mSrcFile != NULL)
  2584. {
  2585. wdBreakpoint = new WdBreakpoint();
  2586. // Insert at head
  2587. wdBreakpoint->mLinkedSibling = headBreakpoint->mLinkedSibling;
  2588. headBreakpoint->mLinkedSibling = wdBreakpoint;
  2589. wdBreakpoint->mRequestedLineNum = headBreakpoint->mRequestedLineNum;
  2590. wdBreakpoint->mLineNum = headBreakpoint->mLineNum;
  2591. wdBreakpoint->mColumn = headBreakpoint->mColumn;
  2592. wdBreakpoint->mInstrOffset = headBreakpoint->mInstrOffset;
  2593. wdBreakpoint->mIsLinkedSibling = true;
  2594. wdBreakpoint->mHead = headBreakpoint;
  2595. }
  2596. if (wdBreakpoint->mInstrOffset > 0)
  2597. {
  2598. for (int instIdx = 0; instIdx < wdBreakpoint->mInstrOffset; instIdx++)
  2599. {
  2600. CPUInst inst;
  2601. if (!mDebugTarget->DecodeInstruction(address, &inst))
  2602. break;
  2603. address += inst.mSize;
  2604. }
  2605. }
  2606. wdBreakpoint->mSrcFile = ctx.mSrcFile;
  2607. wdBreakpoint->mLineData = DbgLineDataEx(lineData, subProgram);
  2608. wdBreakpoint->mBreakpointType = BreakpointType_User;
  2609. wdBreakpoint->mAddr = address;
  2610. if ((mDebuggerWaitingThread != NULL) && (mDebuggerWaitingThread->mStoppedAtAddress == address))
  2611. {
  2612. BfLogDbg("CheckBreakpoint setting mIsAtBreakpointAddress = %p\n", address);
  2613. mDebuggerWaitingThread->mIsAtBreakpointAddress = address;
  2614. }
  2615. BfLogDbg("Breakpoint %p found at %s in %s\n", wdBreakpoint, subProgram->mName, GetFileName(subProgram->mCompileUnit->mDbgModule->mFilePath).c_str());
  2616. SetBreakpoint(address);
  2617. foundInSequence = true;
  2618. }
  2619. }
  2620. if ((lineOffset >= 0) && (lineOffset <= maxLineDist) && (lineOffset <= bestLineOffset))
  2621. {
  2622. if (lineOffset < bestLineOffset)
  2623. {
  2624. bestLineNum = lineData->mLine;
  2625. bestLineOffset = lineOffset;
  2626. }
  2627. }
  2628. }
  2629. };
  2630. for (int pass = 0; pass < 2; pass++)
  2631. {
  2632. if (lineNum == -1)
  2633. break;
  2634. bestLineNum = -1;
  2635. bestLineOffset = 0x7FFFFFFF;
  2636. if (hotIdx >= 0)
  2637. {
  2638. if (hotIdx >= srcFile->mHotReplacedDbgLineInfo.size())
  2639. return;
  2640. auto hotReplacedLineInfo = srcFile->mHotReplacedDbgLineInfo[hotIdx];
  2641. for (auto& hotReplacedEntry : hotReplacedLineInfo->mEntries)
  2642. {
  2643. _CheckLineInfo(hotReplacedEntry.mSubprogram, hotReplacedEntry.mLineInfo);
  2644. }
  2645. }
  2646. else
  2647. {
  2648. for (auto subprogram : srcFile->mLineDataRefs)
  2649. _CheckLineInfo(subprogram, subprogram->mLineInfo);
  2650. }
  2651. if (foundLine)
  2652. break;
  2653. // Don't allow the breakpoint to be inexactly bound -- only match on pass 0
  2654. if (hotIdx != -1)
  2655. break;
  2656. if (bestLineNum == -1)
  2657. break;
  2658. lineNum = bestLineNum;
  2659. wdBreakpoint->mLineNum = bestLineNum;
  2660. }
  2661. int highestCheckHotIdx = highestHotIdx - 1;
  2662. if (hotIdx != -1)
  2663. highestCheckHotIdx = hotIdx - 1;
  2664. for (int hotFileIdx = highestCheckHotIdx; hotFileIdx >= 0; hotFileIdx--)
  2665. {
  2666. auto& hotReplacedDbgLineData = wdBreakpoint->mSrcFile->mHotReplacedDbgLineInfo;
  2667. // Only try to bind to an old hot version if we haven't unloaded the hot module
  2668. if ((hotFileIdx < (int)hotReplacedDbgLineData.size()) && (hotReplacedDbgLineData[hotFileIdx]->mEntries.size() > 0))
  2669. {
  2670. headBreakpoint->mPendingHotBindIdx = hotFileIdx;
  2671. break;
  2672. }
  2673. }
  2674. }
  2675. void WinDebugger::HotBindBreakpoint(Breakpoint* breakpoint, int lineNum, int hotIdx)
  2676. {
  2677. WdBreakpoint* wdBreakpoint = (WdBreakpoint*)breakpoint;
  2678. CheckBreakpoint(wdBreakpoint, wdBreakpoint->mSrcFile, lineNum, hotIdx);
  2679. }
  2680. void WinDebugger::CheckBreakpoint(WdBreakpoint* wdBreakpoint)
  2681. {
  2682. if (!mGotStartupEvent)
  2683. return;
  2684. if (wdBreakpoint->mThreadId == 0) // Not bound to threadId yet...
  2685. {
  2686. return;
  2687. }
  2688. if (wdBreakpoint->mMemoryBreakpointInfo != NULL)
  2689. {
  2690. if (wdBreakpoint->mMemoryBreakpointInfo->mMemoryWatchSlotBitmap != 0)
  2691. return;
  2692. if (mFreeMemoryBreakIndices.size() == 0)
  2693. return;
  2694. if ((IsInRunState()) || (mActiveThread == NULL))
  2695. return;
  2696. int wantBytes[4];
  2697. int wantBindCount = 0;
  2698. int bytesLeft = wdBreakpoint->mMemoryBreakpointInfo->mByteCount;
  2699. addr_target curAddr = wdBreakpoint->mMemoryBreakpointInfo->mMemoryAddress;
  2700. while (bytesLeft > 0)
  2701. {
  2702. if (wantBindCount >= mFreeMemoryBreakIndices.size())
  2703. return;
  2704. int curByteCount = 1;
  2705. #ifdef BF_DBG_64
  2706. if ((bytesLeft >= 8) && ((curAddr & 7) == 0))
  2707. curByteCount = 8;
  2708. else
  2709. #endif
  2710. if ((bytesLeft >= 4) && ((curAddr & 3) == 0))
  2711. curByteCount = 4;
  2712. else if ((bytesLeft >= 2) && ((curAddr & 1) == 0))
  2713. curByteCount = 2;
  2714. wantBytes[wantBindCount++] = curByteCount;
  2715. bytesLeft -= curByteCount;
  2716. curAddr += curByteCount;
  2717. }
  2718. addr_target curOfs = 0;
  2719. for (int i = 0; i < wantBindCount; i++)
  2720. {
  2721. int memoryBreakIdx = mFreeMemoryBreakIndices.back();
  2722. mFreeMemoryBreakIndices.pop_back();
  2723. mMemoryBreakpoints[memoryBreakIdx].mBreakpoint = wdBreakpoint;
  2724. mMemoryBreakpoints[memoryBreakIdx].mAddress = wdBreakpoint->mMemoryBreakpointInfo->mMemoryAddress + curOfs;
  2725. mMemoryBreakpoints[memoryBreakIdx].mByteCount = wantBytes[i];
  2726. mMemoryBreakpoints[memoryBreakIdx].mOfs = curOfs;
  2727. curOfs += wantBytes[i];
  2728. wdBreakpoint->mMemoryBreakpointInfo->mMemoryWatchSlotBitmap |= 1<<memoryBreakIdx;
  2729. }
  2730. UpdateThreadDebugRegisters();
  2731. }
  2732. if (wdBreakpoint->mAddr != 0)
  2733. return;
  2734. if (!wdBreakpoint->mSymbolName.IsEmpty())
  2735. {
  2736. auto headBreakpoint = wdBreakpoint->GetHeadBreakpoint();
  2737. String symbolName = wdBreakpoint->mSymbolName;
  2738. bool onlyBindFirst = false;
  2739. if (symbolName.StartsWith("-"))
  2740. {
  2741. symbolName.Remove(0);
  2742. onlyBindFirst = true;
  2743. }
  2744. for (auto dbgModule : mDebugTarget->mDbgModules)
  2745. {
  2746. dbgModule->ParseSymbolData();
  2747. addr_target targetAddr = -1;
  2748. auto entry = dbgModule->mSymbolNameMap.Find(symbolName.c_str());
  2749. if (entry != NULL)
  2750. {
  2751. DbgSymbol* dwSymbol = entry->mValue;
  2752. targetAddr = dwSymbol->mAddress;
  2753. }
  2754. if (targetAddr == -1)
  2755. {
  2756. if (symbolName == ".")
  2757. {
  2758. targetAddr = mDebugTarget->mTargetBinary->mImageBase + mDebugTarget->mTargetBinary->mEntryPoint;
  2759. onlyBindFirst = true;
  2760. }
  2761. }
  2762. if (targetAddr != -1)
  2763. {
  2764. if (wdBreakpoint->mAddr == 0)
  2765. {
  2766. wdBreakpoint->mAddr = targetAddr;
  2767. wdBreakpoint->mBreakpointType = BreakpointType_User;
  2768. SetBreakpoint(wdBreakpoint->mAddr);
  2769. }
  2770. else
  2771. {
  2772. wdBreakpoint = new WdBreakpoint();
  2773. // Insert at head
  2774. wdBreakpoint->mLinkedSibling = headBreakpoint->mLinkedSibling;
  2775. headBreakpoint->mLinkedSibling = wdBreakpoint;
  2776. wdBreakpoint->mSymbolName = headBreakpoint->mSymbolName;
  2777. wdBreakpoint->mIsLinkedSibling = true;
  2778. wdBreakpoint->mHead = headBreakpoint;
  2779. }
  2780. if (onlyBindFirst)
  2781. break;
  2782. }
  2783. }
  2784. return;
  2785. }
  2786. BP_ZONE("WinDebugger::CheckBreakpoint");
  2787. // Rehup if we load a DLL that also uses this file we bound to (thus the mDeferredRefs check)
  2788. if (wdBreakpoint->mSrcFile == NULL)
  2789. {
  2790. DbgSrcFile* srcFile = mDebugTarget->GetSrcFile(wdBreakpoint->mFilePath);
  2791. if (srcFile == NULL)
  2792. return;
  2793. for (auto& deferredSrcFileRef : srcFile->mDeferredRefs)
  2794. {
  2795. deferredSrcFileRef.mDbgModule->ParseCompileUnit(deferredSrcFileRef.mCompileUnitId);
  2796. }
  2797. srcFile->mDeferredRefs.Clear();
  2798. CheckBreakpoint(wdBreakpoint, srcFile, wdBreakpoint->mRequestedLineNum, -1);
  2799. }
  2800. }
  2801. bool WinDebugger::IsMemoryBreakpointSizeValid(addr_target addr, int size)
  2802. {
  2803. int wantBindCount = 0;
  2804. int bytesLeft = size;
  2805. addr_target curAddr = addr;
  2806. for (int i = 0; i < 4; i++)
  2807. {
  2808. int curByteCount = 1;
  2809. #ifdef BF_DBG_64
  2810. if ((bytesLeft >= 8) && ((curAddr & 7) == 0))
  2811. curByteCount = 8;
  2812. else
  2813. #endif
  2814. if ((bytesLeft >= 4) && ((curAddr & 3) == 0))
  2815. curByteCount = 4;
  2816. else if ((bytesLeft >= 2) && ((curAddr & 1) == 0))
  2817. curByteCount = 2;
  2818. bytesLeft -= curByteCount;
  2819. curAddr += curByteCount;
  2820. if (bytesLeft == 0)
  2821. return true;
  2822. }
  2823. return false;
  2824. }
  2825. bool WinDebugger::HasMemoryBreakpoint(addr_target addr, int size)
  2826. {
  2827. for (int i = 0; i < 4; i++)
  2828. {
  2829. if ((mMemoryBreakpoints[i].mAddress == addr) &&
  2830. (mMemoryBreakpoints[i].mOfs == 0) &&
  2831. (mMemoryBreakpoints[i].mBreakpoint->mMemoryBreakpointInfo->mByteCount == size))
  2832. return true;
  2833. }
  2834. return false;
  2835. }
  2836. Breakpoint* WinDebugger::CreateBreakpoint(const StringImpl& fileName, int lineNum, int wantColumn, int instrOffset)
  2837. {
  2838. AutoCrit autoCrit(mDebugManager->mCritSect);
  2839. BfLogDbg("CreateBreakpoint %s %d %d\n", fileName.c_str(), lineNum, wantColumn);
  2840. WdBreakpoint* wdBreakpoint = new WdBreakpoint();
  2841. wdBreakpoint->mFilePath = FixPathAndCase(fileName);
  2842. wdBreakpoint->mRequestedLineNum = lineNum;
  2843. wdBreakpoint->mLineNum = lineNum;
  2844. wdBreakpoint->mColumn = wantColumn;
  2845. wdBreakpoint->mInstrOffset = instrOffset;
  2846. mBreakpoints.push_back(wdBreakpoint);
  2847. BfLogDbg("CreateBreakpoint Created %p\n", wdBreakpoint);
  2848. return wdBreakpoint;
  2849. }
  2850. void WinDebugger::CheckBreakpoint(Breakpoint* checkBreakpoint)
  2851. {
  2852. AutoCrit autoCrit(mDebugManager->mCritSect);
  2853. CheckBreakpoint((WdBreakpoint*)checkBreakpoint);
  2854. }
  2855. Breakpoint* WinDebugger::CreateMemoryBreakpoint(intptr addr, int byteCount)
  2856. {
  2857. AutoCrit autoCrit(mDebugManager->mCritSect);
  2858. BfLogDbg("CreateMemoryBreakpoint %p %d\n", addr, byteCount);
  2859. WdBreakpoint* wdBreakpoint = new WdBreakpoint();
  2860. WdMemoryBreakpointInfo* memoryBreakInfo = new WdMemoryBreakpointInfo();
  2861. memoryBreakInfo->mMemoryAddress = addr;
  2862. memoryBreakInfo->mByteCount = byteCount;
  2863. wdBreakpoint->mMemoryBreakpointInfo = memoryBreakInfo;
  2864. mBreakpoints.push_back(wdBreakpoint);
  2865. CheckBreakpoint(wdBreakpoint);
  2866. return wdBreakpoint;
  2867. }
  2868. Breakpoint* WinDebugger::CreateSymbolBreakpoint(const StringImpl& symbolName)
  2869. {
  2870. AutoCrit autoCrit(mDebugManager->mCritSect);
  2871. BfLogDbg("CreateSymbolBreakpoint %s\n", symbolName.c_str());
  2872. WdBreakpoint* wdBreakpoint = new WdBreakpoint();
  2873. wdBreakpoint->mSymbolName = symbolName;
  2874. mBreakpoints.push_back(wdBreakpoint);
  2875. CheckBreakpoint(wdBreakpoint);
  2876. return wdBreakpoint;
  2877. }
  2878. Breakpoint* WinDebugger::CreateAddressBreakpoint(intptr inAddress)
  2879. {
  2880. AutoCrit autoCrit(mDebugManager->mCritSect);
  2881. BfLogDbg("CreateAddressBreakpoint %p\n", inAddress);
  2882. addr_target address = (addr_target)inAddress;
  2883. WdBreakpoint* wdBreakpoint = new WdBreakpoint();
  2884. wdBreakpoint->mAddr = address;
  2885. SetBreakpoint(address);
  2886. if ((mDebuggerWaitingThread != NULL) && (mDebuggerWaitingThread->mStoppedAtAddress == address))
  2887. {
  2888. BfLogDbg("CreateAddressBreakpoint setting mIsAtBreakpointAddress = %p\n", address);
  2889. mDebuggerWaitingThread->mIsAtBreakpointAddress = address;
  2890. }
  2891. mBreakpoints.push_back(wdBreakpoint);
  2892. return wdBreakpoint;
  2893. }
  2894. void WinDebugger::DeleteBreakpoint(Breakpoint* breakpoint)
  2895. {
  2896. AutoCrit autoCrit(mDebugManager->mCritSect);
  2897. if (breakpoint == mActiveBreakpoint)
  2898. mActiveBreakpoint = NULL;
  2899. BfLogDbg("WinDebugger::DeleteBreakpoint %p Count:%d\n", breakpoint, mBreakpoints.size());
  2900. WdBreakpoint* wdBreakpoint = (WdBreakpoint*)breakpoint;
  2901. if (wdBreakpoint->mCondition != NULL)
  2902. {
  2903. if (!wdBreakpoint->mIsLinkedSibling)
  2904. delete wdBreakpoint->mCondition;
  2905. }
  2906. if (wdBreakpoint->mMemoryBreakpointInfo != NULL)
  2907. {
  2908. for (int memoryWatchSlot = 0; memoryWatchSlot < 4; memoryWatchSlot++)
  2909. {
  2910. if (mMemoryBreakpoints[memoryWatchSlot].mBreakpoint == wdBreakpoint)
  2911. {
  2912. mFreeMemoryBreakIndices.push_back(memoryWatchSlot);
  2913. mMemoryBreakpoints[memoryWatchSlot] = WdMemoryBreakpointBind();
  2914. UpdateThreadDebugRegisters();
  2915. }
  2916. }
  2917. wdBreakpoint->mMemoryBreakpointInfo->mMemoryWatchSlotBitmap = 0;
  2918. }
  2919. if (wdBreakpoint->mAddr != 0)
  2920. {
  2921. RemoveBreakpoint(wdBreakpoint->mAddr);
  2922. for (auto thread : mThreadList)
  2923. {
  2924. if (thread->mIsAtBreakpointAddress == wdBreakpoint->mAddr)
  2925. thread->mIsAtBreakpointAddress = NULL;
  2926. if (thread->mBreakpointAddressContinuing == wdBreakpoint->mAddr)
  2927. thread->mBreakpointAddressContinuing = NULL;
  2928. }
  2929. }
  2930. if (!wdBreakpoint->mIsLinkedSibling)
  2931. {
  2932. mBreakpoints.Remove(wdBreakpoint);
  2933. }
  2934. if (wdBreakpoint->mLinkedSibling != NULL)
  2935. DeleteBreakpoint(wdBreakpoint->mLinkedSibling);
  2936. delete wdBreakpoint;
  2937. }
  2938. void WinDebugger::DetachBreakpoint(Breakpoint* breakpoint)
  2939. {
  2940. AutoCrit autoCrit(mDebugManager->mCritSect);
  2941. BfLogDbg("WinDebugger::DetachBreakpoint %p\n", breakpoint);
  2942. WdBreakpoint* wdBreakpoint = (WdBreakpoint*)breakpoint;
  2943. if (wdBreakpoint->mAddr != 0)
  2944. {
  2945. RemoveBreakpoint(wdBreakpoint->mAddr);
  2946. if ((mDebuggerWaitingThread != NULL) && (mDebuggerWaitingThread->mIsAtBreakpointAddress == wdBreakpoint->mAddr))
  2947. mDebuggerWaitingThread->mIsAtBreakpointAddress = NULL;
  2948. if ((mDebuggerWaitingThread != NULL) && (mDebuggerWaitingThread->mBreakpointAddressContinuing == wdBreakpoint->mAddr))
  2949. mDebuggerWaitingThread->mBreakpointAddressContinuing = NULL;
  2950. wdBreakpoint->mLineData = DbgLineDataEx();
  2951. wdBreakpoint->mAddr = 0;
  2952. }
  2953. if (wdBreakpoint->mCondition != NULL)
  2954. {
  2955. delete wdBreakpoint->mCondition->mDbgEvaluationContext;
  2956. wdBreakpoint->mCondition->mDbgEvaluationContext = NULL;
  2957. }
  2958. if (wdBreakpoint->mMemoryBreakpointInfo != NULL)
  2959. {
  2960. for (int memoryWatchSlot = 0; memoryWatchSlot < 4; memoryWatchSlot++)
  2961. {
  2962. if (mMemoryBreakpoints[memoryWatchSlot].mBreakpoint == wdBreakpoint)
  2963. {
  2964. mFreeMemoryBreakIndices.push_back(memoryWatchSlot);
  2965. mMemoryBreakpoints[memoryWatchSlot] = WdMemoryBreakpointBind();
  2966. UpdateThreadDebugRegisters();
  2967. }
  2968. }
  2969. wdBreakpoint->mMemoryBreakpointInfo->mMemoryWatchSlotBitmap = 0;
  2970. }
  2971. if (wdBreakpoint->mLinkedSibling != NULL)
  2972. {
  2973. DeleteBreakpoint(wdBreakpoint->mLinkedSibling);
  2974. wdBreakpoint->mLinkedSibling = NULL;
  2975. }
  2976. wdBreakpoint->mSrcFile = NULL;
  2977. wdBreakpoint->mPendingHotBindIdx = -1;
  2978. }
  2979. void WinDebugger::MoveBreakpoint(Breakpoint* breakpoint, int lineNum, int wantColumn, bool rebindNow)
  2980. {
  2981. WdBreakpoint* wdBreakpoint = (WdBreakpoint*)breakpoint;
  2982. AutoCrit autoCrit(mDebugManager->mCritSect);
  2983. DetachBreakpoint(wdBreakpoint);
  2984. //TODO: This doesn't actually rebind correctly while the app is running
  2985. if ((lineNum != -1) && (wantColumn != -1))
  2986. {
  2987. wdBreakpoint->mRequestedLineNum = lineNum;
  2988. wdBreakpoint->mLineNum = lineNum;
  2989. wdBreakpoint->mColumn = wantColumn;
  2990. }
  2991. if (rebindNow)
  2992. CheckBreakpoint(wdBreakpoint);
  2993. }
  2994. void WinDebugger::MoveMemoryBreakpoint(Breakpoint* breakpoint, intptr addr, int byteCount)
  2995. {
  2996. AutoCrit autoCrit(mDebugManager->mCritSect);
  2997. WdBreakpoint* wdBreakpoint = (WdBreakpoint*)breakpoint;
  2998. DetachBreakpoint(wdBreakpoint);
  2999. wdBreakpoint->mMemoryBreakpointInfo->mMemoryAddress = addr;
  3000. wdBreakpoint->mMemoryBreakpointInfo->mByteCount = byteCount;
  3001. CheckBreakpoint(wdBreakpoint);
  3002. }
  3003. void WinDebugger::DisableBreakpoint(Breakpoint* breakpoint)
  3004. {
  3005. AutoCrit autoCrit(mDebugManager->mCritSect);
  3006. WdBreakpoint* wdBreakpoint = (WdBreakpoint*)breakpoint;
  3007. DetachBreakpoint(wdBreakpoint);
  3008. delete wdBreakpoint->mMemoryBreakpointInfo;
  3009. wdBreakpoint->mMemoryBreakpointInfo = NULL;
  3010. }
  3011. void WinDebugger::SetBreakpointCondition(Breakpoint* breakpoint, const StringImpl& conditionExpr)
  3012. {
  3013. AutoCrit autoCrit(mDebugManager->mCritSect);
  3014. WdBreakpoint* wdBreakpoint = (WdBreakpoint*)breakpoint;
  3015. BF_ASSERT(!wdBreakpoint->mIsLinkedSibling);
  3016. if (conditionExpr.empty())
  3017. {
  3018. delete wdBreakpoint->mCondition;
  3019. WdBreakpoint* curBreakpoint = wdBreakpoint;
  3020. wdBreakpoint->mCondition = NULL;
  3021. }
  3022. else
  3023. {
  3024. delete wdBreakpoint->mCondition;
  3025. auto condition = new WdBreakpointCondition();
  3026. condition->mExpr = conditionExpr;
  3027. wdBreakpoint->mCondition = condition;
  3028. }
  3029. }
  3030. void WinDebugger::SetBreakpointLogging(Breakpoint* breakpoint, const StringImpl& logging, bool breakAfterLogging)
  3031. {
  3032. AutoCrit autoCrit(mDebugManager->mCritSect);
  3033. WdBreakpoint* wdBreakpoint = (WdBreakpoint*)breakpoint;
  3034. BF_ASSERT(!wdBreakpoint->mIsLinkedSibling);
  3035. wdBreakpoint->mLogging = logging;
  3036. wdBreakpoint->mBreakAfterLogging = breakAfterLogging;
  3037. }
  3038. bool WinDebugger::CheckConditionalBreakpoint(WdBreakpoint* breakpoint, DbgSubprogram* dbgSubprogram, addr_target pcAddress)
  3039. {
  3040. // What was this assertion for?
  3041. //BF_ASSERT(mCallStack.size() == 0);
  3042. auto headBreakpoint = breakpoint->GetHeadBreakpoint();
  3043. if (headBreakpoint->mThreadId != -1)
  3044. {
  3045. if ((mActiveThread != NULL) && (mActiveThread->mThreadId != headBreakpoint->mThreadId))
  3046. return false;
  3047. }
  3048. auto _SplitExpr = [&](const StringImpl& expr, String& outExpr, String& outSubject)
  3049. {
  3050. int crPos = expr.IndexOf('\n');
  3051. if (crPos != -1)
  3052. {
  3053. outExpr = expr.Substring(0, crPos);
  3054. outSubject = expr.Substring(crPos + 1);
  3055. }
  3056. else
  3057. {
  3058. outExpr = expr;
  3059. }
  3060. };
  3061. if (headBreakpoint->mCondition != NULL)
  3062. {
  3063. ClearCallStack();
  3064. auto conditional = headBreakpoint->mCondition;
  3065. if (conditional->mDbgEvaluationContext == NULL)
  3066. {
  3067. CPURegisters registers;
  3068. PopulateRegisters(&registers);
  3069. auto pcAddress = registers.GetPC();
  3070. DbgSubprogram* subprogram = mDebugTarget->FindSubProgram(pcAddress);
  3071. if (subprogram == NULL)
  3072. {
  3073. return false;
  3074. }
  3075. String expr;
  3076. String subjectExpr;
  3077. _SplitExpr(conditional->mExpr, expr, subjectExpr);
  3078. DbgLanguage language = DbgLanguage_Unknown;
  3079. if (expr.StartsWith("@Beef:"))
  3080. {
  3081. expr.Remove(0, 6);
  3082. language = DbgLanguage_Beef;
  3083. }
  3084. else if (expr.StartsWith("@C:"))
  3085. {
  3086. expr.Remove(0, 3);
  3087. language = DbgLanguage_C;
  3088. }
  3089. conditional->mDbgEvaluationContext = new DbgEvaluationContext(this, subprogram->mCompileUnit->mDbgModule, expr);
  3090. if (language != DbgLanguage_Unknown)
  3091. conditional->mDbgEvaluationContext->mDbgExprEvaluator->mLanguage = language;
  3092. conditional->mDbgEvaluationContext->mDbgExprEvaluator->mSubjectExpr = subjectExpr;
  3093. conditional->mDbgEvaluationContext->mDbgExprEvaluator->mDbgCompileUnit = subprogram->mCompileUnit;
  3094. conditional->mDbgEvaluationContext->mDbgExprEvaluator->mCallStackIdx = 0;
  3095. conditional->mDbgEvaluationContext->mDbgExprEvaluator->mExpressionFlags = (DwEvalExpressionFlags)(DwEvalExpressionFlag_AllowSideEffects | DwEvalExpressionFlag_AllowCalls);
  3096. }
  3097. WdStackFrame* wdStackFrame = new WdStackFrame();
  3098. PopulateRegisters(&wdStackFrame->mRegisters);
  3099. mCallStack.Add(wdStackFrame);
  3100. DbgTypedValue result = conditional->mDbgEvaluationContext->EvaluateInContext(DbgTypedValue());
  3101. ClearCallStack();
  3102. if (conditional->mDbgEvaluationContext->mPassInstance->HasFailed())
  3103. {
  3104. String errorStr = "FAILED";
  3105. for (auto error : conditional->mDbgEvaluationContext->mPassInstance->mErrors)
  3106. {
  3107. if (!error->mIsWarning)
  3108. errorStr = error->mError;
  3109. }
  3110. String condError = StrFormat("error Conditional breakpoint expression '%s' failed: %s", conditional->mExpr.c_str(), errorStr.c_str());
  3111. mDebugManager->mOutMessages.push_back(condError);
  3112. return true;
  3113. }
  3114. else if ((!result) || (!result.mType->IsBoolean()))
  3115. {
  3116. mDebugManager->mOutMessages.push_back(StrFormat("error Conditional breakpoint expression '%s' must result in a boolean value", conditional->mExpr.c_str()));
  3117. return true;
  3118. }
  3119. else if (!result.mBool)
  3120. return false;
  3121. }
  3122. headBreakpoint->mHitCount++;
  3123. switch (headBreakpoint->mHitCountBreakKind)
  3124. {
  3125. case DbgHitCountBreakKind_Equals:
  3126. if (headBreakpoint->mHitCount != headBreakpoint->mTargetHitCount)
  3127. return false;
  3128. break;
  3129. case DbgHitCountBreakKind_GreaterEquals:
  3130. if (headBreakpoint->mHitCount < headBreakpoint->mTargetHitCount)
  3131. return false;
  3132. break;
  3133. case DbgHitCountBreakKind_Multiple:
  3134. if ((headBreakpoint->mHitCount % headBreakpoint->mTargetHitCount) != 0)
  3135. return false;
  3136. break;
  3137. }
  3138. mActiveBreakpoint = breakpoint;
  3139. mBreakStackFrameIdx = -1;
  3140. if (!headBreakpoint->mLogging.IsEmpty())
  3141. {
  3142. ClearCallStack();
  3143. DwFormatInfo formatInfo;
  3144. formatInfo.mCallStackIdx = 0;
  3145. DbgCompileUnit* dbgCompileUnit = NULL;
  3146. if (dbgSubprogram == NULL)
  3147. dbgSubprogram = mDebugTarget->FindSubProgram(pcAddress);
  3148. if (dbgSubprogram != NULL)
  3149. {
  3150. dbgCompileUnit = dbgSubprogram->mCompileUnit;
  3151. formatInfo.mLanguage = dbgSubprogram->GetLanguage();
  3152. }
  3153. auto prevRunState = mRunState;
  3154. mRunState = RunState_Paused; // We need to be paused to avoid certain errors in the eval
  3155. String displayString;
  3156. String expr;
  3157. _SplitExpr(headBreakpoint->mLogging, expr, formatInfo.mSubjectExpr);
  3158. if (expr.StartsWith("@Beef:"))
  3159. {
  3160. expr.Remove(0, 6);
  3161. formatInfo.mLanguage = DbgLanguage_Beef;
  3162. }
  3163. else if (expr.StartsWith("@C:"))
  3164. {
  3165. expr.Remove(0, 3);
  3166. formatInfo.mLanguage = DbgLanguage_C;
  3167. }
  3168. ProcessEvalString(dbgCompileUnit, DbgTypedValue(), expr, displayString, formatInfo, NULL, false);
  3169. mRunState = prevRunState;
  3170. displayString.Insert(0, "log ");
  3171. displayString.Append("\n");
  3172. mDebugManager->mOutMessages.push_back(displayString);
  3173. if (!headBreakpoint->mBreakAfterLogging)
  3174. return false;
  3175. }
  3176. return true;
  3177. }
  3178. void WinDebugger::CleanupDebugEval(bool restoreRegisters)
  3179. {
  3180. BfLogDbg("CleanupDebugEval ThreadId=%d\n", mDebugEvalThreadInfo.mThreadId);
  3181. WdThreadInfo* evalThreadInfo = NULL;
  3182. if (mThreadMap.TryGetValue(mDebugEvalThreadInfo.mThreadId, &evalThreadInfo))
  3183. {
  3184. if ((restoreRegisters) && (!mDbgBreak))
  3185. {
  3186. SetAndRestoreValue<WdThreadInfo*> activeThread(mActiveThread, evalThreadInfo);
  3187. RestoreAllRegisters();
  3188. // if (mRunState == RunState_Running_ToTempBreakpoint)
  3189. // mRunState = RunState_Paused;
  3190. }
  3191. evalThreadInfo->mStartSP = mDebugEvalThreadInfo.mStartSP;
  3192. evalThreadInfo->mStoppedAtAddress = mDebugEvalThreadInfo.mStoppedAtAddress;
  3193. evalThreadInfo->mIsAtBreakpointAddress = mDebugEvalThreadInfo.mIsAtBreakpointAddress;
  3194. evalThreadInfo->mBreakpointAddressContinuing = mDebugEvalThreadInfo.mBreakpointAddressContinuing;
  3195. }
  3196. delete mDebugPendingExpr;
  3197. mDebugPendingExpr = NULL;
  3198. mDebugEvalThreadInfo = WdThreadInfo();
  3199. OutputRawMessage("rehupLoc");
  3200. }
  3201. bool WinDebugger::FixCallStackIdx(int& callStackIdx)
  3202. {
  3203. callStackIdx = BF_MAX(callStackIdx, 0);
  3204. if (mCallStack.IsEmpty())
  3205. UpdateCallStack();
  3206. int stackSize = (int)mCallStack.size();
  3207. while (callStackIdx >= mCallStack.size())
  3208. {
  3209. UpdateCallStack();
  3210. if (stackSize == (int)mCallStack.size())
  3211. break; // Didn't change
  3212. stackSize = (int)mCallStack.size();
  3213. }
  3214. if (callStackIdx >= stackSize)
  3215. {
  3216. callStackIdx = 0;
  3217. return false;
  3218. }
  3219. return true;
  3220. }
  3221. bool WinDebugger::HasLineInfoAt(addr_target address)
  3222. {
  3223. BP_ZONE("WinDebugger::HasLineInfoAt");
  3224. DbgSubprogram* dbgSubprogram = NULL;
  3225. auto dwLineData = FindLineDataAtAddress(address, &dbgSubprogram);
  3226. return (dwLineData != NULL) && (dwLineData->IsStackFrameSetup()) && (dbgSubprogram->GetLineAddr(*dwLineData) == address);
  3227. }
  3228. void WinDebugger::StepLineTryPause(addr_target address, bool requireExactMatch)
  3229. {
  3230. if (mStepInAssembly)
  3231. return;
  3232. if (mStepLineData.mLineData != NULL)
  3233. {
  3234. DbgSubprogram* dbgSubprogram = NULL;
  3235. DbgSrcFile* dbgSrcFile = NULL;
  3236. auto dwLineData = FindLineDataAtAddress(address, &dbgSubprogram, &dbgSrcFile);
  3237. if ((dwLineData != NULL) && (dwLineData->IsStackFrameSetup()) && ((!requireExactMatch) || (dbgSubprogram->GetLineAddr(*dwLineData) == address)))
  3238. {
  3239. // "Invalid" line
  3240. if (dwLineData->mColumn == -1)
  3241. {
  3242. SetupStep(mStepType);
  3243. mRunState = RunState_Running;
  3244. return;
  3245. }
  3246. // If we're on the same line but a different column or a <= address then keep it keep looking
  3247. if ((dbgSrcFile == mStepLineData.GetSrcFile()) &&
  3248. ((!requireExactMatch) || (dwLineData != mStepLineData.mLineData) || (address <= mStepStartPC)) &&
  3249. (dwLineData->mLine == mStepLineData.mLineData->mLine))
  3250. {
  3251. SetupStep(mStepType);
  3252. mRunState = RunState_Running;
  3253. return;
  3254. }
  3255. }
  3256. }
  3257. mRunState = RunState_Paused;
  3258. }
  3259. void WinDebugger::BreakAll()
  3260. {
  3261. AutoCrit autoCrit(mDebugManager->mCritSect);
  3262. ::DebugBreakProcess(mProcessInfo.hProcess);
  3263. }
  3264. void WinDebugger::StepInto(bool inAssembly)
  3265. {
  3266. AutoCrit autoCrit(mDebugManager->mCritSect);
  3267. if (!TryRunContinue())
  3268. return;
  3269. BfLogDbg("StepInto\n");
  3270. mCurNoInfoStepTries = 0; // Reset
  3271. mStepInAssembly = inAssembly;
  3272. SetupStep(StepType_StepInto);
  3273. ContinueDebugEvent();
  3274. }
  3275. void WinDebugger::StepIntoSpecific(intptr inAddr)
  3276. {
  3277. addr_target addr = (addr_target)inAddr;
  3278. AutoCrit autoCrit(mDebugManager->mCritSect);
  3279. if (!TryRunContinue())
  3280. return;
  3281. BfLogDbg("StepIntoSpecific %p\n", addr);
  3282. mCurNoInfoStepTries = 0; // Reset
  3283. mStepInAssembly = false;
  3284. SetupStep(StepType_StepInto);
  3285. mIsStepIntoSpecific = true;
  3286. mStepType = StepType_StepInto_Unfiltered;
  3287. if (mStepStartPC != addr)
  3288. {
  3289. RemoveTempBreakpoints();
  3290. SetTempBreakpoint(addr);
  3291. mStepBreakpointAddrs.push_back(addr);
  3292. }
  3293. ContinueDebugEvent();
  3294. }
  3295. void WinDebugger::PushValue(CPURegisters* registers, int64 val)
  3296. {
  3297. addr_target* regSP = registers->GetSPRegisterRef();
  3298. *regSP -= sizeof(addr_target);
  3299. WriteMemory<addr_target>(*regSP, (addr_target)val);
  3300. }
  3301. void WinDebugger::PushValue(CPURegisters* registers, const DbgTypedValue& typedValue)
  3302. {
  3303. addr_target* regSP = registers->GetSPRegisterRef();
  3304. int byteCount = typedValue.mType->GetByteCount();
  3305. if ((byteCount == 8) || (sizeof(addr_target) == 8))
  3306. {
  3307. *regSP -= sizeof(int64);
  3308. addr_target val = typedValue.mInt64;
  3309. if (typedValue.mType->IsCompositeType())
  3310. val = typedValue.mSrcAddress;
  3311. WriteMemory<int64>(*regSP, val);
  3312. }
  3313. else
  3314. {
  3315. *regSP -= sizeof(int32);
  3316. addr_target val = typedValue.mInt32;
  3317. if (typedValue.mType->IsCompositeType())
  3318. val = typedValue.mSrcAddress;
  3319. WriteMemory<int32>(*regSP, val);
  3320. }
  3321. }
  3322. void WinDebugger::SetThisRegister(CPURegisters* registers, addr_target val)
  3323. {
  3324. #if BF_DBG_32
  3325. registers->mIntRegs.ecx = val;
  3326. #else
  3327. registers->mIntRegs.rcx = val;
  3328. #endif
  3329. }
  3330. void WinDebugger::AddParamValue(int paramIdx, bool hadThis, CPURegisters* registers, const DbgTypedValue& typedValue)
  3331. {
  3332. #if BF_DBG_32
  3333. PushValue(registers, typedValue);
  3334. #else
  3335. int regIdx = paramIdx + (hadThis ? 1 : 0);
  3336. if (typedValue.mType->IsFloat())
  3337. {
  3338. PushValue(registers, typedValue);
  3339. if (regIdx < 4)
  3340. {
  3341. if (typedValue.mType->mTypeCode == DbgType_Single)
  3342. {
  3343. registers->mXmmRegsArray[regIdx].f[0] = typedValue.mSingle;
  3344. }
  3345. else
  3346. {
  3347. registers->mXmmDRegsArray[regIdx].d[0] = typedValue.mDouble;
  3348. }
  3349. }
  3350. }
  3351. else
  3352. {
  3353. PushValue(registers, typedValue);
  3354. if (regIdx < 4)
  3355. {
  3356. int64 val;
  3357. if (typedValue.mType->IsCompositeType())
  3358. val = typedValue.mSrcAddress;
  3359. else
  3360. val = typedValue.mPtr;
  3361. if (regIdx == 0)
  3362. registers->mIntRegs.rcx = val;
  3363. else if (regIdx == 1)
  3364. registers->mIntRegs.rdx = val;
  3365. else if (regIdx == 2)
  3366. registers->mIntRegs.r8 = val;
  3367. else if (regIdx == 3)
  3368. registers->mIntRegs.r9 = val;
  3369. }
  3370. }
  3371. #endif
  3372. }
  3373. bool WinDebugger::CheckNeedsSRetArgument(DbgType* retType)
  3374. {
  3375. if (!retType->IsCompositeType())
  3376. return false;
  3377. //TODO: Change when we change the calling convention
  3378. if (retType->GetLanguage() == DbgLanguage_Beef)
  3379. return true;
  3380. int retSize = retType->GetByteCount();
  3381. //TODO: Check for 'POD' type?
  3382. if ((retSize == 1) || (retSize == 2) || (retSize == 4) || (retSize == sizeof(addr_target)))
  3383. return false;
  3384. return true;
  3385. }
  3386. DbgTypedValue WinDebugger::ReadReturnValue(CPURegisters* registers, DbgType* type)
  3387. {
  3388. DbgTypedValue retValue;
  3389. if (type->IsFloat())
  3390. {
  3391. retValue.mType = type;
  3392. #if BF_DBG_32
  3393. retValue.mDouble = ConvertFloat80ToDouble(registers->mFpMmRegsArray[0].fp.fp80);
  3394. if (type->mSize == 4)
  3395. retValue.mSingle = (float)retValue.mDouble;
  3396. #else
  3397. if (retValue.mType->mTypeCode == DbgType_Single)
  3398. retValue.mSingle = registers->mXmmRegsArray[0].f[0];
  3399. else
  3400. retValue.mDouble = registers->mXmmDRegsArray[0].d[0];
  3401. #endif
  3402. }
  3403. else if (type->IsCompositeType())
  3404. {
  3405. retValue.mType = type;
  3406. if (CheckNeedsSRetArgument(type))
  3407. {
  3408. #ifdef BF_DBG_32
  3409. retValue.mSrcAddress = mSavedContext.Esp - BF_ALIGN(type->GetByteCount(), 16);
  3410. #else
  3411. retValue.mSrcAddress = mSavedContext.Rsp - BF_ALIGN(type->GetByteCount(), 16);
  3412. #endif
  3413. }
  3414. else
  3415. {
  3416. #ifdef BF_DBG_32
  3417. retValue.mInt32 = mSavedContext.Eax;
  3418. #else
  3419. retValue.mInt64 = mSavedContext.Rax;
  3420. #endif
  3421. }
  3422. }
  3423. else
  3424. {
  3425. #ifdef BF_DBG_32
  3426. retValue.mType = type;
  3427. retValue.mInt32 = registers->mIntRegs.eax;
  3428. if (type->mSize == 8)
  3429. (&retValue.mInt32)[1] = registers->mIntRegs.edx;
  3430. #else
  3431. retValue.mType = type;
  3432. retValue.mInt64 = registers->mIntRegs.rax;
  3433. #endif
  3434. return retValue;
  3435. }
  3436. return retValue;
  3437. }
  3438. bool WinDebugger::SetRegisters(CPURegisters* registers)
  3439. {
  3440. BF_CONTEXT lcContext;
  3441. lcContext.ContextFlags = BF_CONTEXT_CONTROL | BF_CONTEXT_INTEGER | BF_CONTEXT_FLOATING_POINT | BF_CONTEXT_EXTENDED_REGISTERS | BF_CONTEXT_SEGMENTS;
  3442. lcContext.ContextFlags |= BF_CONTEXT_EXCEPTION_REQUEST;
  3443. BF_GetThreadContext(mActiveThread->mHThread, &lcContext);
  3444. #ifdef BF_DBG_32
  3445. lcContext.Eax = registers->mIntRegs.eax;
  3446. lcContext.Ecx = registers->mIntRegs.ecx;
  3447. lcContext.Edx = registers->mIntRegs.edx;
  3448. lcContext.Ebx = registers->mIntRegs.ebx;
  3449. lcContext.Esp = registers->mIntRegs.esp;
  3450. lcContext.Ebp = registers->mIntRegs.ebp;
  3451. lcContext.Esi = registers->mIntRegs.esi;
  3452. lcContext.Edi = registers->mIntRegs.edi;
  3453. lcContext.Eip = registers->mIntRegs.eip;
  3454. lcContext.EFlags = registers->mIntRegs.efl;
  3455. BF_ASSERT(sizeof(lcContext.FloatSave.RegisterArea) == sizeof(registers->mFpMmRegsArray));
  3456. memcpy(lcContext.FloatSave.RegisterArea, registers->mFpMmRegsArray, sizeof(lcContext.FloatSave.RegisterArea));
  3457. BF_ASSERT(sizeof(registers->mXmmRegsArray) == 32*sizeof(float));
  3458. memcpy(&lcContext.ExtendedRegisters[160], registers->mXmmRegsArray, sizeof(registers->mXmmRegsArray));
  3459. #else
  3460. lcContext.Rax = registers->mIntRegs.rax;
  3461. lcContext.Rcx = registers->mIntRegs.rcx;
  3462. lcContext.Rdx = registers->mIntRegs.rdx;
  3463. lcContext.Rbx = registers->mIntRegs.rbx;
  3464. lcContext.Rsp = registers->mIntRegs.rsp;
  3465. lcContext.Rbp = registers->mIntRegs.rbp;
  3466. lcContext.Rsi = registers->mIntRegs.rsi;
  3467. lcContext.Rdi = registers->mIntRegs.rdi;
  3468. lcContext.Rip = registers->mIntRegs.rip;
  3469. lcContext.EFlags = (DWORD)registers->mIntRegs.efl;
  3470. lcContext.R8 = registers->mIntRegs.r8;
  3471. lcContext.R9 = registers->mIntRegs.r9;
  3472. lcContext.R10 = registers->mIntRegs.r10;
  3473. lcContext.R11 = registers->mIntRegs.r11;
  3474. lcContext.R12 = registers->mIntRegs.r12;
  3475. lcContext.R13 = registers->mIntRegs.r13;
  3476. lcContext.R14 = registers->mIntRegs.r14;
  3477. lcContext.R15 = registers->mIntRegs.r15;
  3478. for (int i = 0; i < 8; i++)
  3479. {
  3480. memcpy(&lcContext.FltSave.FloatRegisters[i], &registers->mFpMmRegsArray[i], 10);
  3481. }
  3482. BF_ASSERT(sizeof(registers->mXmmRegsArray) == 64 * sizeof(float));
  3483. memcpy(BF_CONTEXT_XMMDATA(lcContext), registers->mXmmRegsArray, sizeof(registers->mXmmRegsArray));
  3484. #endif
  3485. //lcContext.ContextFlags |= BF_CONTEXT_EXCEPTION_REQUEST;
  3486. BF_SetThreadContext(mActiveThread->mHThread, &lcContext);
  3487. return (lcContext.ContextFlags & (BF_CONTEXT_EXCEPTION_ACTIVE | BF_CONTEXT_SERVICE_ACTIVE)) == 0;
  3488. }
  3489. void WinDebugger::SaveAllRegisters()
  3490. {
  3491. BfLogDbg("SaveAllRegisters setting mSavedAtBreakpointAddress = %p\n", mActiveThread->mIsAtBreakpointAddress);
  3492. mSavedAtBreakpointAddress = mActiveThread->mIsAtBreakpointAddress;
  3493. mSavedBreakpointAddressContinuing = mActiveThread->mBreakpointAddressContinuing;
  3494. mSavedContext.ContextFlags = BF_CONTEXT_ALL;
  3495. BF_GetThreadContext(mActiveThread->mHThread, &mSavedContext);
  3496. }
  3497. void WinDebugger::RestoreAllRegisters()
  3498. {
  3499. BfLogDbg("RestoreAllRegisters setting mIsAtBreakpointAddress = %p\n", mSavedAtBreakpointAddress);
  3500. mActiveThread->mIsAtBreakpointAddress = mSavedAtBreakpointAddress;
  3501. mActiveThread->mBreakpointAddressContinuing = mSavedBreakpointAddressContinuing;
  3502. BF_SetThreadContext(mActiveThread->mHThread, &mSavedContext);
  3503. #ifdef BF_DBG_32
  3504. //TODO: Find the test that this was required for...
  3505. // if (mActiveThread->mIsAtBreakpointAddress == mSavedContext.Eip)
  3506. // {
  3507. // if (mRunState == RunState_Running_ToTempBreakpoint)
  3508. // mRunState = RunState_Paused;
  3509. // }
  3510. // else
  3511. // {
  3512. // SetTempBreakpoint(mSavedContext.Eip);
  3513. // mRunState = RunState_Running_ToTempBreakpoint;
  3514. // mStepType = StepType_ToTempBreakpoint;
  3515. // mSteppingThread = mActiveThread;
  3516. // }
  3517. #endif
  3518. }
  3519. void WinDebugger::OutputMessage(const StringImpl& msg)
  3520. {
  3521. if (this == NULL)
  3522. return;
  3523. AutoCrit autoCrit(mDebugManager->mCritSect);
  3524. mDebugManager->mOutMessages.push_back("msg " + msg);
  3525. }
  3526. void WinDebugger::OutputRawMessage(const StringImpl& msg)
  3527. {
  3528. if (this == NULL)
  3529. return;
  3530. AutoCrit autoCrit(mDebugManager->mCritSect);
  3531. mDebugManager->mOutMessages.push_back(msg);
  3532. }
  3533. void WinDebugger::SetRunState(RunState runState)
  3534. {
  3535. mRunState = runState;
  3536. }
  3537. bool WinDebugger::TryRunContinue()
  3538. {
  3539. if (mRunState == RunState_Exception)
  3540. {
  3541. mIsContinuingFromException = true;
  3542. mRunState = RunState_Paused;
  3543. }
  3544. if (((mRunState == RunState_Paused) || (mRunState == RunState_Breakpoint)) && (mNeedsRehupBreakpoints))
  3545. RehupBreakpoints(true);
  3546. return true;
  3547. }
  3548. void WinDebugger::ClearStep()
  3549. {
  3550. BfLogDbg("ClearStep\n");
  3551. RemoveTempBreakpoints();
  3552. mOrigStepType = StepType_None;
  3553. mStepType = StepType_None;
  3554. mStepStartPC = 0;
  3555. mStepSP = 0;
  3556. mStepPC = 0;
  3557. mIsStepIntoSpecific = false;
  3558. mStepIsRecursing = false;
  3559. mStepStopOnNextInstruction = false;
  3560. mStepLineData = DbgLineDataEx();
  3561. }
  3562. bool WinDebugger::SetupStep(StepType stepType)
  3563. {
  3564. BP_ZONE("SetupStep");
  3565. RemoveTempBreakpoints();
  3566. if (mNeedsRehupBreakpoints)
  3567. RehupBreakpoints(true);
  3568. if (mOrigStepType == StepType_None)
  3569. mOrigStepType = stepType;
  3570. mStepType = stepType;
  3571. mSteppingThread = mActiveThread;
  3572. mStepSwitchedThreads = false;
  3573. mContinueFromBreakpointFailed = false;
  3574. CPURegisters registers;
  3575. PopulateRegisters(&registers);
  3576. addr_target pcAddress = registers.GetPC();
  3577. if (mStepLineData.IsNull())
  3578. {
  3579. DbgSubprogram* dbgSubprogram = NULL;
  3580. auto dbgLineData = FindLineDataAtAddress(pcAddress, &dbgSubprogram);
  3581. mStepLineData = DbgLineDataEx(dbgLineData, dbgSubprogram);
  3582. mStepStartPC = registers.GetPC();
  3583. }
  3584. bool isDeeper = mStepSP > registers.GetSP();
  3585. BfLogDbg("SetupStep %d PC:%p SP:%p StepStartSP:%p Thread:%d\n", stepType, (addr_target)registers.GetPC(), (addr_target)registers.GetSP(), (addr_target)mStepSP, mSteppingThread->mThreadId);
  3586. mStepSP = registers.GetSP();
  3587. mStepPC = registers.GetPC();
  3588. if ((mStepType == StepType_StepOut) || (mStepType == StepType_StepOut_NoFrame) || (mStepType == StepType_StepOut_ThenInto))
  3589. {
  3590. if (mStepType != StepType_StepOut_NoFrame)
  3591. {
  3592. // Test for stepping out of an inline method
  3593. DbgSubprogram* dwSubprogram = mDebugTarget->FindSubProgram(pcAddress);
  3594. if ((dwSubprogram != NULL) && (dwSubprogram->mInlineeInfo != NULL))
  3595. {
  3596. DbgSubprogram* topSubprogram = dwSubprogram->GetRootInlineParent();
  3597. if ((mOrigStepType == StepType_StepInto) || (mOrigStepType == StepType_StepInto_Unfiltered))
  3598. {
  3599. mStepType = mOrigStepType;
  3600. }
  3601. else
  3602. {
  3603. mStepType = StepType_StepOut_Inline;
  3604. // Set up pcAddress to detect recursion
  3605. //TODO: We can't set a physical breakpoint here because we will immediately hit it when attempting to step over an inlined method.
  3606. // An inlined method can't recurse anyway, but store the pcAddress in mTempBreakpoints because we still check that for recursion
  3607. // SetTempBreakpoint(pcAddress);
  3608. //mTempBreakpoint.push_back(pcAddress);
  3609. mStepBreakpointAddrs.push_back(pcAddress);
  3610. }
  3611. addr_target endAddress = dwSubprogram->mBlock.mHighPC;
  3612. if (dwSubprogram->mHasLineAddrGaps)
  3613. {
  3614. // Keep bumping out the address as long as we can find lines that contain the nextPC
  3615. addr_target nextAddr = pcAddress;
  3616. for (auto& lineInfo : topSubprogram->mLineInfo->mLines)
  3617. {
  3618. auto lineAddr = topSubprogram->GetLineAddr(lineInfo);
  3619. if ((nextAddr >= lineAddr) && (nextAddr < lineAddr + lineInfo.mContribSize))
  3620. {
  3621. auto ctx = topSubprogram->mLineInfo->mContexts[lineInfo.mCtxIdx];
  3622. if (ctx.mInlinee == dwSubprogram)
  3623. {
  3624. nextAddr = lineAddr + lineInfo.mContribSize;
  3625. }
  3626. }
  3627. }
  3628. if (nextAddr != pcAddress)
  3629. endAddress = nextAddr;
  3630. }
  3631. BfLogDbg("Stepping out of inlined method, end address: %p\n", endAddress);
  3632. SetTempBreakpoint(endAddress);
  3633. mStepBreakpointAddrs.push_back(endAddress);
  3634. addr_target decodeAddress = dwSubprogram->mBlock.mLowPC;
  3635. while (decodeAddress < endAddress)
  3636. {
  3637. CPUInst inst;
  3638. if (!mDebugTarget->DecodeInstruction(decodeAddress, &inst))
  3639. break;
  3640. addr_target targetAddress = inst.GetTarget();
  3641. // We need to find a targetAddress
  3642. if ((targetAddress != 0) &&
  3643. !((targetAddress >= dwSubprogram->mBlock.mLowPC) && (targetAddress < dwSubprogram->mBlock.mHighPC)) &&
  3644. ((targetAddress >= topSubprogram->mBlock.mLowPC) && (targetAddress < topSubprogram->mBlock.mHighPC)))
  3645. {
  3646. BfLogDbg("Stepping out of inlined method, branch address: %p\n", targetAddress);
  3647. SetTempBreakpoint(targetAddress);
  3648. mStepBreakpointAddrs.push_back(targetAddress);
  3649. }
  3650. decodeAddress += inst.GetLength();
  3651. }
  3652. return true;
  3653. }
  3654. }
  3655. if ((mStepType != StepType_StepOut_NoFrame) && (RollBackStackFrame(&registers, true)))
  3656. {
  3657. pcAddress = registers.GetPC();
  3658. addr_target oldAddress = pcAddress;
  3659. CPUInst inst;
  3660. while (true)
  3661. {
  3662. if (!mDebugTarget->DecodeInstruction(pcAddress, &inst))
  3663. break;
  3664. if ((inst.IsBranch()) || (inst.IsCall()) || (inst.IsReturn()))
  3665. break;
  3666. DbgSubprogram* checkSubprogram = NULL;
  3667. auto checkLineData = FindLineDataAtAddress(pcAddress, &checkSubprogram, NULL, NULL, DbgOnDemandKind_LocalOnly);
  3668. if (checkLineData == NULL)
  3669. break;
  3670. if (checkSubprogram->GetLineAddr(*checkLineData) == pcAddress)
  3671. break;
  3672. pcAddress += inst.GetLength();
  3673. }
  3674. if (pcAddress != oldAddress)
  3675. {
  3676. BfLogDbg("Adjusting stepout address from %p to %p\n", oldAddress, pcAddress);
  3677. }
  3678. #ifdef BF_DBG_32
  3679. // if (mDebugTarget->DecodeInstruction(pcAddress, &inst))
  3680. // {
  3681. // if (inst.IsStackAdjust())
  3682. // {
  3683. // auto oldAddress = pcAddress;
  3684. // pcAddress += inst.GetLength();
  3685. // BfLogDbg("Adjusting stepout address from %p to %p\n", oldAddress, pcAddress);
  3686. // }
  3687. // }
  3688. #endif
  3689. BfLogDbg("SetupStep Stepout SetTempBreakpoint %p\n", pcAddress);
  3690. SetTempBreakpoint(pcAddress);
  3691. mStepBreakpointAddrs.push_back(pcAddress);
  3692. if (mStepType != StepType_StepOut_ThenInto)
  3693. mStepType = StepType_StepOut;
  3694. }
  3695. else
  3696. {
  3697. // Try to handle the case where we just entered this call so the return address is the first entry on the stack
  3698. addr_target* regSP = registers.GetSPRegisterRef();
  3699. pcAddress = ReadMemory<addr_target>(*regSP);
  3700. *regSP += sizeof(addr_target);
  3701. if (mDebugTarget->FindSubProgram(pcAddress) != NULL)
  3702. {
  3703. BfLogDbg("SetupStep Stepout SetTempBreakpoint (2) %p\n", pcAddress);
  3704. SetTempBreakpoint(pcAddress);
  3705. mStepBreakpointAddrs.push_back(pcAddress);
  3706. if (mOrigStepType == StepType_StepInto)
  3707. mStepType = StepType_StepInto;
  3708. else
  3709. mStepType = StepType_StepOver;
  3710. return true;
  3711. }
  3712. else
  3713. {
  3714. // Just do stepovers until we eventually step out
  3715. //BF_DBG_FATAL("StepOut Failed");
  3716. BfLogDbg("StepOut Failed\n");
  3717. if (mLastValidStepIntoPC != 0)
  3718. {
  3719. BfLogDbg("Using mLastValidStepIntoPC: %p\n", mLastValidStepIntoPC);
  3720. if (mOrigStepType == StepType_StepInto)
  3721. mStepType = StepType_StepInto;
  3722. else
  3723. mStepType = StepType_StepOver;
  3724. SetTempBreakpoint(mLastValidStepIntoPC);
  3725. mStepBreakpointAddrs.push_back(0);
  3726. mStepBreakpointAddrs.push_back(mLastValidStepIntoPC);
  3727. mLastValidStepIntoPC = 0;
  3728. return true;
  3729. }
  3730. else
  3731. {
  3732. BfLogDbg("Stopping");
  3733. mStepType = StepType_None;
  3734. mRunState = RunState_Paused;
  3735. return true;
  3736. }
  3737. }
  3738. }
  3739. }
  3740. if ((mStepType != StepType_StepOut) && (mStepType != StepType_StepOut_ThenInto))
  3741. {
  3742. if (mDebuggerWaitingThread != mSteppingThread)
  3743. {
  3744. // We've switched threads, so there's a possible race condition:
  3745. // This new thread may already have an EXCEPTION_BREAKPOINT queued up so the PC is actually
  3746. // located one byte past the BREAK instruction, which is one byte into whatever instruction
  3747. // was previously there. We can't insert normal BREAK instructions because we don't know
  3748. // if the current PC is actually at an instruction start, so we do a single step with a
  3749. // slower stack call check to see if we need to step out after a "step over"
  3750. BfLogDbg("Step - switched threads mIsAtBreakpointAddress:%p\n", mSteppingThread->mIsAtBreakpointAddress);
  3751. mStepSwitchedThreads = true;
  3752. SingleStepX86();
  3753. return true;
  3754. }
  3755. bool breakOnNext = false;
  3756. int instIdx = 0;
  3757. for (instIdx = 0; true; instIdx++)
  3758. {
  3759. bool isAtLine = false;
  3760. DbgSubprogram* dwSubprogram = NULL;
  3761. auto dwLineData = FindLineDataAtAddress(pcAddress, &dwSubprogram, NULL, NULL, DbgOnDemandKind_LocalOnly);
  3762. isAtLine = (instIdx > 0) && (dwLineData != NULL) && (dwLineData->IsStackFrameSetup()) && (dwSubprogram->GetLineAddr(*dwLineData) == pcAddress);
  3763. // "Never step into" line
  3764. if ((dwLineData != NULL) && (dwLineData->mColumn == -2) && (stepType == StepType_StepInto))
  3765. stepType = StepType_StepOver;
  3766. CPUInst inst;
  3767. if (!mDebugTarget->DecodeInstruction(pcAddress, &inst))
  3768. {
  3769. BfLogDbg("Decode failed, set up SingleStepX86 %p\n", pcAddress);
  3770. SingleStepX86();
  3771. mStepStopOnNextInstruction = true;
  3772. return true;
  3773. }
  3774. if (instIdx > 256)
  3775. {
  3776. BfLogDbg("Too many SetupStep iterations");
  3777. breakOnNext = true;
  3778. }
  3779. if ((inst.IsReturn()) && (instIdx == 0) && (!mStepInAssembly))
  3780. {
  3781. // Do actual STEP OUT so we set up proper "stepping over unimportant post-return instructions"
  3782. return SetupStep(StepType_StepOut);
  3783. }
  3784. if ((breakOnNext) || (mStepInAssembly) || (isAtLine) || (inst.IsBranch()) || (inst.IsCall()) || (inst.IsReturn()))
  3785. {
  3786. if (((instIdx == 0) || (mStepInAssembly)) && (!breakOnNext))
  3787. {
  3788. if ((stepType == StepType_StepOver) && (inst.IsCall()))
  3789. {
  3790. // Continue - sets a breakpoint on the call line to detect recursion.
  3791. // The next loop through will set a breakpoint on the line after the return
  3792. BfLogDbg("StepHadCall\n");
  3793. breakOnNext = true;
  3794. BfLogDbg("StepHadCall setting mIsAtBreakpointAddress = %p\n", pcAddress);
  3795. mSteppingThread->mIsAtBreakpointAddress = pcAddress;
  3796. SetTempBreakpoint(pcAddress);
  3797. mStepBreakpointAddrs.push_back(pcAddress);
  3798. }
  3799. else
  3800. {
  3801. if (inst.IsCall())
  3802. {
  3803. if ((mLastValidStepIntoPC == 0) || (dwSubprogram != NULL))
  3804. mLastValidStepIntoPC = pcAddress + inst.mSize;
  3805. }
  3806. if ((dwLineData != NULL) && (inst.IsBranch()))
  3807. {
  3808. addr_target targetAddr = inst.GetTarget();
  3809. if (targetAddr < dwSubprogram->GetLineAddr(*dwLineData))
  3810. {
  3811. // Jumping backwards, stop at next instruction
  3812. mStepStopOnNextInstruction = true;
  3813. }
  3814. }
  3815. bool isPrefixOnly = false;
  3816. if ((mStepInAssembly) && (stepType == StepType_StepOver) && (inst.IsRep(isPrefixOnly)))
  3817. {
  3818. if (isPrefixOnly)
  3819. {
  3820. CPUInst nextInst;
  3821. if (mDebugTarget->DecodeInstruction(pcAddress + inst.GetLength(), &nextInst))
  3822. {
  3823. if (nextInst.IsBranch())
  3824. {
  3825. // repne jmp - this appears in __chkstk (for example)
  3826. // We don't have a good way to "step over" this one, so just do a single step
  3827. }
  3828. else
  3829. {
  3830. // Step over the rep + target instruction
  3831. auto doneAddr = pcAddress + inst.GetLength() + nextInst.GetLength();
  3832. BfLogDbg("SetupStep SetTempBreakpoint %p\n", doneAddr);
  3833. SetTempBreakpoint(doneAddr);
  3834. mStepBreakpointAddrs.push_back(doneAddr);
  3835. break;
  3836. }
  3837. }
  3838. }
  3839. else
  3840. {
  3841. // Step over the instruction
  3842. auto doneAddr = pcAddress + inst.GetLength();
  3843. BfLogDbg("SetupStep SetTempBreakpoint %p\n", doneAddr);
  3844. SetTempBreakpoint(doneAddr);
  3845. mStepBreakpointAddrs.push_back(doneAddr);
  3846. break;
  3847. }
  3848. }
  3849. // Just step a single instruction
  3850. BfLogDbg("SetupStep SingleStepX86 %p\n", pcAddress);
  3851. SingleStepX86();
  3852. if (inst.IsReturn())
  3853. mStepStopOnNextInstruction = true;
  3854. break;
  3855. }
  3856. }
  3857. else
  3858. {
  3859. // Move us to this instruction so we can hardware single-step into it
  3860. BfLogDbg("SetupStep SetTempBreakpoint %p\n", pcAddress);
  3861. SetTempBreakpoint(pcAddress);
  3862. mStepBreakpointAddrs.push_back(pcAddress);
  3863. break;
  3864. }
  3865. }
  3866. // Not an interesting instruction - move to next
  3867. pcAddress += inst.mSize;
  3868. if ((dwSubprogram != NULL) && (dwSubprogram->mInlineeInfo != NULL) && (pcAddress >= dwSubprogram->mBlock.mHighPC))
  3869. {
  3870. auto endAddress = dwSubprogram->mBlock.mHighPC;
  3871. BfLogDbg("Stepping past end of inlined method, end address: %p\n", endAddress);
  3872. mStepType = StepType_StepOut_Inline;
  3873. SetTempBreakpoint(endAddress);
  3874. mStepBreakpointAddrs.push_back(endAddress);
  3875. return true;
  3876. }
  3877. }
  3878. if (instIdx > 1)
  3879. BfLogDbg("SetupStep instIdx: %d\n", instIdx);
  3880. }
  3881. return true;
  3882. }
  3883. void WinDebugger::CheckNonDebuggerBreak()
  3884. {
  3885. enum MessageType
  3886. {
  3887. MessageType_None = 0,
  3888. MessageType_Error = 1,
  3889. MessageType_ProfilerCmd = 2
  3890. };
  3891. CPURegisters registers;
  3892. PopulateRegisters(&registers);
  3893. addr_target pcAddress = registers.GetPC();
  3894. mDebugTarget->mTargetBinary->ParseSymbolData();
  3895. addr_target debugMessageDataAddr = mDebugTarget->FindSymbolAddr("gBfDebugMessageData");
  3896. if (debugMessageDataAddr != (addr_target)-1)
  3897. {
  3898. struct BfDebugMessageData
  3899. {
  3900. int mMessageType; // 0 = none, 1 = error
  3901. int mStackWindbackCount;
  3902. int mBufParamLen;
  3903. addr_target mBufParam;
  3904. addr_target mPCOverride;
  3905. };
  3906. BfDebugMessageData messageData = ReadMemory<BfDebugMessageData>(debugMessageDataAddr);
  3907. WriteMemory<int>(debugMessageDataAddr, 0); // Zero out type so we won't trigger again
  3908. if (messageData.mMessageType != 0)
  3909. {
  3910. llvm::SmallVector<char, 4096> strBuf;
  3911. int strLen = messageData.mBufParamLen;
  3912. strBuf.resize(strLen + 1);
  3913. char* str = &strBuf[0];
  3914. str[strLen] = 0;
  3915. if (ReadMemory(messageData.mBufParam, strLen, str))
  3916. {
  3917. if (messageData.mMessageType == MessageType_Error)
  3918. {
  3919. mRequestedStackFrameIdx = messageData.mStackWindbackCount;
  3920. if (messageData.mPCOverride != 0)
  3921. {
  3922. mShowPCOverride = messageData.mPCOverride;
  3923. mRequestedStackFrameIdx = -2;
  3924. }
  3925. mDebugManager->mOutMessages.push_back(StrFormat("error %s", str));
  3926. }
  3927. else if (messageData.mMessageType == MessageType_ProfilerCmd)
  3928. {
  3929. // It's important to set this here, because we unlock the critSect during StopSampling and we can't have the
  3930. // IDE thinking that we're actually paused when it checks the mRunState
  3931. mRunState = RunState_Running;
  3932. char* cmd = strtok(str, "\t");
  3933. if (strcmp(cmd, "StartSampling") == 0)
  3934. {
  3935. char* sessionIdStr = strtok(NULL, "\t");
  3936. char* threadIdStr = strtok(NULL, "\t");
  3937. char* sampleRateStr = strtok(NULL, "\t");
  3938. char* descStr = strtok(NULL, "\t");
  3939. if (threadIdStr != NULL)
  3940. {
  3941. int threadId = atoi(threadIdStr);
  3942. int sampleRate = atoi(sampleRateStr);
  3943. int sessionId = atoi(sessionIdStr);
  3944. Profiler** profilerPtr;
  3945. if (mPendingProfilerMap.TryAdd(sessionId, NULL, &profilerPtr))
  3946. {
  3947. DbgProfiler* profiler = new DbgProfiler(this);
  3948. if (descStr != NULL)
  3949. profiler->mDescription = descStr;
  3950. if (sampleRate > 0)
  3951. profiler->mSamplesPerSecond = sampleRate;
  3952. profiler->Start();
  3953. *profilerPtr = profiler;
  3954. mDebugManager->mOutMessages.push_back("newProfiler");
  3955. mNewProfilerList.push_back(profiler);
  3956. }
  3957. }
  3958. }
  3959. else if (strcmp(cmd, "StopSampling") == 0)
  3960. {
  3961. char* sessionIdStr = strtok(NULL, "\t");
  3962. if (sessionIdStr != NULL)
  3963. {
  3964. int sessionId = atoi(sessionIdStr);
  3965. Profiler* profiler;
  3966. if (mPendingProfilerMap.Remove(sessionId, &profiler))
  3967. {
  3968. if (profiler->IsSampling())
  3969. {
  3970. // Need to unlock so we don't deadlock
  3971. mDebugManager->mCritSect.Unlock();
  3972. profiler->Stop();
  3973. mDebugManager->mCritSect.Lock();
  3974. }
  3975. }
  3976. }
  3977. }
  3978. else if (strcmp(cmd, "ClearSampling") == 0)
  3979. {
  3980. for (auto& kv : mPendingProfilerMap)
  3981. {
  3982. auto profiler = kv.mValue;
  3983. profiler->Clear();
  3984. }
  3985. }
  3986. else if (strcmp(cmd, "ClearOutput") == 0)
  3987. {
  3988. mDebugManager->mOutMessages.push_back("clearOutput");
  3989. }
  3990. }
  3991. return;
  3992. }
  3993. }
  3994. }
  3995. intptr_target objAddr;
  3996. if (mDebugTarget->IsObjectAccessBreak(pcAddress, &registers, &objAddr))
  3997. {
  3998. String errorStr = "error Attempted to access deleted object";
  3999. String objectAddr = EncodeDataPtr((addr_target)objAddr, true);
  4000. errorStr += StrFormat("\x1LEAK\t(System.Object)%s\n (%s)%s\n", objectAddr.c_str(), "System.Object", objectAddr.c_str());
  4001. mDebugManager->mOutMessages.push_back(errorStr);
  4002. return;
  4003. }
  4004. bool showMainThread = false;
  4005. String symbol;
  4006. addr_target offset;
  4007. DbgModule* dbgModule;
  4008. if (mDebugTarget->FindSymbolAt(pcAddress, &symbol, &offset, &dbgModule))
  4009. {
  4010. if (symbol == "DbgBreakPoint")
  4011. {
  4012. showMainThread = true;
  4013. }
  4014. }
  4015. #ifdef BF_DBG_32
  4016. else if ((dbgModule != NULL) && (dbgModule->mDisplayName.Equals("kernel32.dll", StringImpl::CompareKind_OrdinalIgnoreCase)))
  4017. {
  4018. showMainThread = true;
  4019. }
  4020. #endif
  4021. if (showMainThread)
  4022. {
  4023. // This is a manual break, show the main thread
  4024. mActiveThread = mThreadList.front();
  4025. if (mDebugPendingExpr != NULL)
  4026. {
  4027. for (auto thread : mThreadList)
  4028. {
  4029. if (thread->mThreadId == mDebugEvalThreadInfo.mThreadId)
  4030. {
  4031. mActiveThread = thread;
  4032. break;
  4033. }
  4034. }
  4035. }
  4036. }
  4037. }
  4038. bool WinDebugger::HasSteppedIntoCall()
  4039. {
  4040. // Some calls (like __chkstk) actually push results to the stack, so we need to check
  4041. // if we're REALLY deeper or not, by rolling back the callstack once
  4042. CPURegisters registers;
  4043. PopulateRegisters(&registers);
  4044. if (RollBackStackFrame(&registers, true))
  4045. {
  4046. // If the previous frames SP is equal or deeper than our step start then we are indeed inside a call!
  4047. if (mStepSP >= registers.GetSP())
  4048. return true;
  4049. }
  4050. return false;
  4051. }
  4052. void WinDebugger::StepOver(bool inAssembly)
  4053. {
  4054. AutoCrit autoCrit(mDebugManager->mCritSect);
  4055. BfLogDbg("StepOver\n");
  4056. if (!TryRunContinue())
  4057. return;
  4058. mCurNoInfoStepTries = 0; // Reset
  4059. mStepInAssembly = inAssembly;
  4060. SetupStep(StepType_StepOver);
  4061. ContinueDebugEvent();
  4062. }
  4063. void WinDebugger::StepOut(bool inAssembly)
  4064. {
  4065. AutoCrit autoCrit(mDebugManager->mCritSect);
  4066. BfLogDbg("StepOut\n");
  4067. if (!TryRunContinue())
  4068. return;
  4069. mCurNoInfoStepTries = 0; // Reset
  4070. mStepInAssembly = inAssembly;
  4071. SetupStep(StepType_StepOut);
  4072. ContinueDebugEvent();
  4073. }
  4074. void WinDebugger::SetNextStatement(bool inAssembly, const StringImpl& fileName, int64 lineNumOrAsmAddr, int wantColumn)
  4075. {
  4076. AutoCrit autoCrit(mDebugManager->mCritSect);
  4077. DbgSubprogram* subProgram = NULL;
  4078. if (!inAssembly)
  4079. {
  4080. if (mCallStack.size() == 0)
  4081. UpdateCallStack();
  4082. if (mCallStack.size() > 0)
  4083. {
  4084. UpdateCallStackMethod(0);
  4085. subProgram = mCallStack[0]->mSubProgram;
  4086. }
  4087. if (subProgram == NULL)
  4088. return;
  4089. }
  4090. DbgSubprogram* rootInlineParent = NULL;
  4091. if (subProgram != NULL)
  4092. rootInlineParent = subProgram->GetRootInlineParent();
  4093. String result;
  4094. if (mDebugTarget == NULL)
  4095. return;
  4096. DbgSrcFile* srcFile = NULL;
  4097. if (!fileName.IsEmpty())
  4098. {
  4099. srcFile = mDebugTarget->GetSrcFile(fileName);
  4100. if (srcFile == NULL)
  4101. return;
  4102. }
  4103. addr_target pcAddress = 0;
  4104. if (inAssembly)
  4105. {
  4106. pcAddress = lineNumOrAsmAddr;
  4107. }
  4108. else
  4109. {
  4110. int lineNum = (int)lineNumOrAsmAddr;
  4111. addr_target bestAddr[2] = { 0, 0 };
  4112. int checkLineNum[2] = { lineNum - 1, lineNum };
  4113. auto _CheckLineInfo = [&](DbgSubprogram* dbgSubprogram, DbgLineInfo* dbgLineInfo)
  4114. {
  4115. for (int iPass = 0; iPass < 2; ++iPass)
  4116. {
  4117. int bestLineOffset = 0x7FFFFFFF;
  4118. for (auto& lineData : dbgLineInfo->mLines)
  4119. {
  4120. auto addr = dbgSubprogram->GetLineAddr(lineData);
  4121. if ((addr < subProgram->mBlock.mLowPC) || (addr >= subProgram->mBlock.mHighPC))
  4122. continue;
  4123. int lineOffset = lineData.mLine - checkLineNum[iPass];
  4124. if ((lineOffset >= 0) && (lineOffset <= 6) && (lineOffset <= bestLineOffset))
  4125. {
  4126. if (lineOffset < bestLineOffset)
  4127. {
  4128. bestLineOffset = lineOffset;
  4129. bestAddr[iPass] = addr;
  4130. }
  4131. }
  4132. }
  4133. }
  4134. };
  4135. for (int checkHotIdx = -1; checkHotIdx < (int)srcFile->mHotReplacedDbgLineInfo.size(); checkHotIdx++)
  4136. {
  4137. if (checkHotIdx >= 0)
  4138. {
  4139. auto hotReplacedLineInfo = srcFile->mHotReplacedDbgLineInfo[checkHotIdx];
  4140. for (auto& hotReplacedEntry : hotReplacedLineInfo->mEntries)
  4141. {
  4142. _CheckLineInfo(hotReplacedEntry.mSubprogram, hotReplacedEntry.mLineInfo);
  4143. }
  4144. }
  4145. else
  4146. {
  4147. for (auto subprogram : srcFile->mLineDataRefs)
  4148. _CheckLineInfo(subprogram, subprogram->mLineInfo);
  4149. }
  4150. if (bestAddr[1] != 0)
  4151. break;
  4152. }
  4153. if (bestAddr[1] != 0)
  4154. {
  4155. const int kMaxAddrDist = 64; // within reasonable range
  4156. if ((bestAddr[0] != 0) && (bestAddr[1] - bestAddr[0] <= kMaxAddrDist))
  4157. {
  4158. addr_target addrStart = bestAddr[0];
  4159. addr_target addrEnd = bestAddr[1];
  4160. addr_target addr = addrStart;
  4161. BF_ASSERT(addrEnd - addr <= kMaxAddrDist);
  4162. addr_target lastOp = 0;
  4163. while (addr < addrEnd)
  4164. {
  4165. CPUInst inst;
  4166. if (!mDebugTarget->DecodeInstruction(addr, &inst))
  4167. break;
  4168. lastOp = addr;
  4169. addr += inst.GetLength();
  4170. }
  4171. }
  4172. pcAddress = (uint64)bestAddr[1];
  4173. }
  4174. }
  4175. if (pcAddress)
  4176. {
  4177. BF_ASSERT(mActiveThread->mBreakpointAddressContinuing == 0);
  4178. mActiveThread->mIsAtBreakpointAddress = 0;
  4179. mActiveThread->mStoppedAtAddress = pcAddress;
  4180. if (mCallStack.size() == 0)
  4181. UpdateCallStack();
  4182. CPURegisters* regs = &mCallStack.front()->mRegisters;
  4183. *regs->GetPCRegisterRef() = pcAddress;
  4184. SetRegisters(regs);
  4185. WdBreakpoint* breakpoint = (WdBreakpoint*)FindBreakpointAt(pcAddress);
  4186. if (breakpoint != NULL)
  4187. {
  4188. BfLogDbg("SetNextStatement setting mIsAtBreakpointAddress = %p\n", breakpoint->mAddr);
  4189. mActiveThread->mIsAtBreakpointAddress = breakpoint->mAddr;
  4190. }
  4191. }
  4192. }
  4193. bool WinDebugger::PopulateRegisters(CPURegisters* registers, BF_CONTEXT& lcContext)
  4194. {
  4195. #ifdef BF_DBG_32
  4196. registers->mIntRegs.eax = lcContext.Eax;
  4197. registers->mIntRegs.ecx = lcContext.Ecx;
  4198. registers->mIntRegs.edx = lcContext.Edx;
  4199. registers->mIntRegs.ebx = lcContext.Ebx;
  4200. registers->mIntRegs.esp = lcContext.Esp;
  4201. registers->mIntRegs.ebp = lcContext.Ebp;
  4202. registers->mIntRegs.esi = lcContext.Esi;
  4203. registers->mIntRegs.edi = lcContext.Edi;
  4204. registers->mIntRegs.eip = lcContext.Eip;
  4205. registers->mIntRegs.efl = lcContext.EFlags;
  4206. BF_ASSERT(sizeof(lcContext.FloatSave.RegisterArea) == sizeof(registers->mFpMmRegsArray));
  4207. memcpy(registers->mFpMmRegsArray, lcContext.FloatSave.RegisterArea, sizeof(lcContext.FloatSave.RegisterArea));
  4208. BF_ASSERT(sizeof(registers->mXmmRegsArray) == 32 * sizeof(float));
  4209. memcpy(registers->mXmmRegsArray, &lcContext.ExtendedRegisters[160], sizeof(registers->mXmmRegsArray));
  4210. #else
  4211. registers->mIntRegs.rax = lcContext.Rax;
  4212. registers->mIntRegs.rcx = lcContext.Rcx;
  4213. registers->mIntRegs.rdx = lcContext.Rdx;
  4214. registers->mIntRegs.rbx = lcContext.Rbx;
  4215. registers->mIntRegs.rsp = lcContext.Rsp;
  4216. registers->mIntRegs.rbp = lcContext.Rbp;
  4217. registers->mIntRegs.rsi = lcContext.Rsi;
  4218. registers->mIntRegs.rdi = lcContext.Rdi;
  4219. registers->mIntRegs.rip = lcContext.Rip;
  4220. registers->mIntRegs.efl = lcContext.EFlags;
  4221. registers->mIntRegs.r8 = lcContext.R8;
  4222. registers->mIntRegs.r9 = lcContext.R9;
  4223. registers->mIntRegs.r10 = lcContext.R10;
  4224. registers->mIntRegs.r11 = lcContext.R11;
  4225. registers->mIntRegs.r12 = lcContext.R12;
  4226. registers->mIntRegs.r13 = lcContext.R13;
  4227. registers->mIntRegs.r14 = lcContext.R14;
  4228. registers->mIntRegs.r15 = lcContext.R15;
  4229. registers->mIntRegs.gs = lcContext.SegGs;
  4230. for (int i = 0; i < 8; i++)
  4231. {
  4232. memcpy(&registers->mFpMmRegsArray[i], &lcContext.FltSave.FloatRegisters[i], 10);
  4233. }
  4234. BF_ASSERT(sizeof(registers->mXmmRegsArray) == 64 * sizeof(float));
  4235. memcpy(registers->mXmmRegsArray, BF_CONTEXT_XMMDATA(lcContext), sizeof(registers->mXmmRegsArray));
  4236. #endif
  4237. return (lcContext.ContextFlags & (BF_CONTEXT_EXCEPTION_ACTIVE | BF_CONTEXT_SERVICE_ACTIVE)) == 0;
  4238. }
  4239. bool WinDebugger::PopulateRegisters(CPURegisters* registers)
  4240. {
  4241. /*static bool sCheckedProcessorFeatures = false;
  4242. static bool sMmxAvailable = false;
  4243. static bool sXmmAvailable = false;
  4244. if (!sCheckedProcessorFeatures)
  4245. {
  4246. //CDH we don't do anything with these yet since we grab BF_CONTEXT_ALL anyway, but could be useful
  4247. sMmxAvailable = ::IsProcessorFeaturePresent(PF_MMX_INSTRUCTIONS_AVAILABLE) != 0;
  4248. sXmmAvailable = ::IsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE) != 0;
  4249. sCheckedProcessorFeatures = true;
  4250. }*/
  4251. BF_ASSERT(registers != nullptr);
  4252. BF_CONTEXT lcContext;
  4253. lcContext.ContextFlags = BF_CONTEXT_ALL | BF_CONTEXT_EXCEPTION_REQUEST;
  4254. BF_GetThreadContext(mActiveThread->mHThread, &lcContext);
  4255. return PopulateRegisters(registers, lcContext);
  4256. }
  4257. bool WinDebugger::RollBackStackFrame(CPURegisters* registers, bool isStackStart)
  4258. {
  4259. BF_ASSERT(registers != nullptr);
  4260. return mDebugTarget->RollBackStackFrame(registers, NULL, isStackStart);
  4261. }
  4262. bool WinDebugger::SetHotJump(DbgSubprogram* oldSubprogram, DbgSubprogram* newSubprogram)
  4263. {
  4264. //AutoCrit autoCrit(mDebugManager->mCritSect);
  4265. BF_ASSERT(mDebugManager->mCritSect.mLockCount == 1);
  4266. addr_target jmpInstStart = oldSubprogram->mBlock.mLowPC;
  4267. addr_target jmpInstEnd = jmpInstStart + sizeof(HotJumpOp);
  4268. if (jmpInstEnd > oldSubprogram->mBlock.mHighPC)
  4269. {
  4270. if ((oldSubprogram->mBlock.mHighPC - oldSubprogram->mBlock.mLowPC == 1) &&
  4271. (newSubprogram->mBlock.mHighPC - newSubprogram->mBlock.mLowPC == 1))
  4272. return true; // Special case for just stub 'ret' methods
  4273. String err = StrFormat("Failed to hot replace method, method '%s' too small to insert hot thunk", newSubprogram->ToString().c_str());
  4274. Fail(err);
  4275. return false;
  4276. }
  4277. if (!oldSubprogram->mWasHotReplaced)
  4278. {
  4279. for (int threadIdx = 0; threadIdx < (int)mThreadList.size(); threadIdx++)
  4280. {
  4281. CPURegisters* cpuRegisters = &mHotThreadStates[threadIdx];
  4282. int tryStart = GetTickCount();
  4283. while ((cpuRegisters->GetPC() >= jmpInstStart) && (cpuRegisters->GetPC() < jmpInstEnd))
  4284. {
  4285. if (GetTickCount() - tryStart >= 8000)
  4286. {
  4287. Fail("Failed to hot replace method, can't move past prelude");
  4288. return false;
  4289. }
  4290. BfLogDbg("SetHotJump skipping through %p\n", cpuRegisters->GetPC());
  4291. bool removedBreakpoint = false;
  4292. mActiveThread = mThreadList[threadIdx];
  4293. if ((mActiveThread->mStoppedAtAddress >= jmpInstStart) && (mActiveThread->mStoppedAtAddress < jmpInstEnd))
  4294. {
  4295. for (addr_target addr = jmpInstStart; addr < jmpInstEnd; addr++)
  4296. {
  4297. if (mBreakpointAddrMap.ContainsKey(addr))
  4298. {
  4299. removedBreakpoint = true;
  4300. RemoveBreakpoint(addr);
  4301. }
  4302. }
  4303. }
  4304. RunState oldRunState = mRunState;
  4305. mRunState = RunState_HotStep;
  4306. if (mWantsDebugContinue)
  4307. {
  4308. mWantsDebugContinue = false;
  4309. BF_ASSERT_REL(mActiveThread->mIsAtBreakpointAddress == 0);
  4310. mContinueEvent.Set();
  4311. }
  4312. BF_CONTEXT lcContext;
  4313. lcContext.ContextFlags = BF_CONTEXT_ALL;
  4314. BF_GetThreadContext(mActiveThread->mHThread, &lcContext);
  4315. lcContext.EFlags |= 0x100; // Set trap flag, which raises "single-step" exception
  4316. BF_SetThreadContext(mActiveThread->mHThread, &lcContext);
  4317. ::ResumeThread(mActiveThread->mHThread);
  4318. BfLogDbg("ResumeThread %d\n", mActiveThread->mThreadId);
  4319. while (mRunState != RunState_Terminated)
  4320. {
  4321. mDebugManager->mCritSect.Unlock();
  4322. Sleep(0);
  4323. mDebugManager->mCritSect.Lock();
  4324. if (IsPaused())
  4325. break;
  4326. if (mWantsDebugContinue)
  4327. {
  4328. BF_GetThreadContext(mActiveThread->mHThread, &lcContext);
  4329. mWantsDebugContinue = false;
  4330. BF_ASSERT_REL(mActiveThread->mIsAtBreakpointAddress == 0);
  4331. mContinueEvent.Set();
  4332. }
  4333. }
  4334. BF_GetThreadContext(mActiveThread->mHThread, &lcContext);
  4335. ::SuspendThread(mActiveThread->mHThread);
  4336. BfLogDbg("SuspendThread %d\n", mActiveThread->mThreadId);
  4337. mRunState = oldRunState;
  4338. if ((mRunState != RunState_Terminated) && (mRunState != RunState_Terminating))
  4339. {
  4340. if (!IsPaused())
  4341. {
  4342. BF_ASSERT(mWantsDebugContinue);
  4343. mWantsDebugContinue = false;
  4344. BF_ASSERT_REL(mActiveThread->mIsAtBreakpointAddress == 0);
  4345. mContinueEvent.Set();
  4346. }
  4347. }
  4348. PopulateRegisters(cpuRegisters);
  4349. }
  4350. }
  4351. }
  4352. HotJumpOp jumpOp;
  4353. jumpOp.mOpCode = 0xE9;
  4354. jumpOp.mRelTarget = newSubprogram->mBlock.mLowPC - oldSubprogram->mBlock.mLowPC - sizeof(HotJumpOp);
  4355. WriteMemory(oldSubprogram->mBlock.mLowPC, jumpOp);
  4356. ::FlushInstructionCache(mProcessInfo.hProcess, (void*)(intptr)oldSubprogram->mBlock.mLowPC, sizeof(HotJumpOp));
  4357. return true;
  4358. }
  4359. DbgSubprogram* WinDebugger::TryFollowHotJump(DbgSubprogram* subprogram, addr_target addr)
  4360. {
  4361. if (!subprogram->mWasHotReplaced)
  4362. return subprogram;
  4363. if (addr != subprogram->mBlock.mLowPC)
  4364. return subprogram;
  4365. auto dbgModule = subprogram->mCompileUnit->mDbgModule;
  4366. HotJumpOp jumpOp = ReadMemory<HotJumpOp>(addr);
  4367. if (jumpOp.mOpCode != 0xE9)
  4368. return subprogram;
  4369. addr_target jumpAddr = addr + jumpOp.mRelTarget + sizeof(HotJumpOp);
  4370. auto jumpSubprogram = mDebugTarget->FindSubProgram(jumpAddr);
  4371. if (jumpSubprogram == NULL)
  4372. return subprogram;
  4373. return jumpSubprogram;
  4374. }
  4375. bool WinDebugger::ShouldShowStaticMember(DbgType* dbgType, DbgVariable* member)
  4376. {
  4377. // If locationData is non-null, that means it was added in addition to the static declaration in the CV type info,
  4378. // so only add the names from the type definition
  4379. auto flavor = dbgType->mCompileUnit->mDbgModule->mDbgFlavor;
  4380. return ((((dbgType->IsNamespace()) || (flavor != DbgFlavor_MS)) && ((member->mLocationData != NULL) || member->mIsConst)) ||
  4381. ((flavor == DbgFlavor_MS) && (member->mLocationData == NULL)));
  4382. }
  4383. String WinDebugger::GetMemberList(DbgType* dbgType, const StringImpl& expr, bool isPtr, bool isStatic, bool forceCast, bool isSplat, bool isReadOnly)
  4384. {
  4385. auto dbgModule = dbgType->GetDbgModule();
  4386. dbgType->PopulateType();
  4387. auto language = dbgType->GetLanguage();
  4388. if (!isStatic)
  4389. {
  4390. String retVal;
  4391. bool needsNewline = false;
  4392. bool isBfObject = false;
  4393. if (dbgType->IsBfObjectPtr())
  4394. {
  4395. isBfObject = true;
  4396. dbgType = dbgType->mTypeParam;
  4397. }
  4398. int baseIdx = 0;
  4399. for (auto baseTypeEntry : dbgType->mBaseTypes)
  4400. {
  4401. auto baseType = baseTypeEntry->mBaseType;
  4402. if ((baseType->mSize > 0) || (baseType->mTypeCode != DbgType_Struct) || (strcmp(baseType->mTypeName, "ValueType") != 0))
  4403. {
  4404. String baseTypeStr = baseType->ToStringRaw(language);
  4405. if (baseIdx > 0)
  4406. retVal += "\n";
  4407. if (isSplat)
  4408. retVal += "[base]\t((" + baseTypeStr + ")" + expr + "), nv";
  4409. else if (dbgType->WantsRefThis())
  4410. retVal += "[base]\t((" + baseTypeStr + ")this), nd, na, nv, this=" + expr;
  4411. else
  4412. retVal += "[base]\t((" + baseTypeStr + "*)this), nd, na, nv, this=" + expr;
  4413. if (isReadOnly)
  4414. retVal += ", ne";
  4415. }
  4416. needsNewline = true;
  4417. baseIdx++;
  4418. }
  4419. String thisExpr = expr;
  4420. String castString;
  4421. if (dbgType->IsBfObject())
  4422. {
  4423. auto ptrType = dbgType->GetDbgModule()->GetPointerType(dbgType);
  4424. castString = ptrType->ToStringRaw(language);
  4425. }
  4426. else
  4427. castString = dbgType->ToStringRaw(language);
  4428. bool hadStatics = false;
  4429. for (auto member : dbgType->mMemberList)
  4430. {
  4431. if (member->mMemberOffset < 0)
  4432. continue;
  4433. if (member->mIsStatic)
  4434. {
  4435. if (ShouldShowStaticMember(dbgType, member))
  4436. hadStatics = true;
  4437. }
  4438. else
  4439. {
  4440. bool ignoreMember = false;
  4441. if (member->mName != NULL)
  4442. {
  4443. if ((member->mName[0] == '?') ||
  4444. (strncmp(member->mName, "_vptr$", 6) == 0))
  4445. ignoreMember = true;
  4446. }
  4447. if (!ignoreMember)
  4448. {
  4449. if (needsNewline)
  4450. retVal += "\n";
  4451. if (member->mName == NULL)
  4452. {
  4453. retVal += GetMemberList(member->mType, expr, isPtr, isStatic, forceCast, isSplat, isReadOnly);
  4454. }
  4455. else
  4456. {
  4457. retVal += String(member->mName);
  4458. if (isSplat)
  4459. {
  4460. retVal += "\t(" + thisExpr + ")." + String(member->mName);
  4461. // We don't want to rely on this being enforced here. For one, ref types shouldn't get ", ne" added,
  4462. // and this doesn't solve the issue of attempting to assign via the Immediate window
  4463. /*if (isReadOnly)
  4464. retVal += ", ne";*/
  4465. }
  4466. else
  4467. {
  4468. if (forceCast)
  4469. retVal += "\t((" + castString + ")this)." + String(member->mName);
  4470. else if ((member->mName[0] >= '0') && (member->mName[0] <= '9')) // Numbered tuple member?
  4471. retVal += "\tthis." + String(member->mName);
  4472. else
  4473. retVal += "\t" + String(member->mName);
  4474. retVal += ", this=" + thisExpr;
  4475. // if (isReadOnly)
  4476. // retVal += ", ne";
  4477. }
  4478. }
  4479. needsNewline = true;
  4480. }
  4481. }
  4482. }
  4483. if (hadStatics)
  4484. {
  4485. if (needsNewline)
  4486. retVal += "\n";
  4487. retVal += "Static values\t" + castString;
  4488. }
  4489. return retVal;
  4490. }
  4491. else
  4492. {
  4493. if (dbgType->IsBfObjectPtr())
  4494. dbgType = dbgType->mTypeParam;
  4495. String retVal;
  4496. String memberPrefix = expr;
  4497. bool needsNewline = false;
  4498. bool hadStatics = false;
  4499. for (auto member : dbgType->mMemberList)
  4500. {
  4501. if (member->mIsStatic)
  4502. {
  4503. if (ShouldShowStaticMember(dbgType, member))
  4504. {
  4505. if (needsNewline)
  4506. retVal += "\n";
  4507. retVal += String(member->mName) + "\t" + memberPrefix + "." + String(member->mName);
  4508. needsNewline = true;
  4509. }
  4510. }
  4511. }
  4512. return retVal;
  4513. }
  4514. return "";
  4515. }
  4516. bool WinDebugger::ParseFormatInfo(DbgModule* dbgModule, const StringImpl& formatInfoStr, DwFormatInfo* formatInfo, BfPassInstance* bfPassInstance, int* assignExprOffset, String* assignExprString, String* errorString, DbgTypedValue contextTypedValue)
  4517. {
  4518. String formatFlags = formatInfoStr;
  4519. if (assignExprOffset != NULL)
  4520. *assignExprOffset = -1;
  4521. while (formatFlags.length() > 0)
  4522. {
  4523. formatFlags = Trim(formatFlags);
  4524. if (formatFlags[0] != ',')
  4525. {
  4526. return false;
  4527. }
  4528. else
  4529. {
  4530. int nextComma = formatFlags.IndexOf(',', 1);
  4531. int quotePos = formatFlags.IndexOf('"', 1);
  4532. if ((quotePos != -1) && (quotePos < nextComma))
  4533. {
  4534. int nextQuotePos = formatFlags.IndexOf('"', quotePos + 1);
  4535. if (nextQuotePos != -1)
  4536. nextComma = formatFlags.IndexOf(',', nextQuotePos + 1);
  4537. }
  4538. if (nextComma == -1)
  4539. nextComma = formatFlags.length();
  4540. String formatCmd = formatFlags.Substring(1, nextComma - 1);
  4541. formatCmd = Trim(formatCmd);
  4542. bool hadError = false;
  4543. if (strncmp(formatCmd.c_str(), "this=", 5) == 0)
  4544. {
  4545. formatCmd = formatFlags.Substring(1);
  4546. formatCmd = Trim(formatCmd);
  4547. String thisExpr = formatCmd.Substring(5);
  4548. if (thisExpr.empty())
  4549. break;
  4550. DbgEvaluationContext dbgEvaluationContext(this, dbgModule, thisExpr, formatInfo);
  4551. formatInfo->mExplicitThis = dbgEvaluationContext.EvaluateInContext(contextTypedValue);
  4552. if (dbgEvaluationContext.HadError())
  4553. {
  4554. if (errorString != NULL)
  4555. *errorString = dbgEvaluationContext.GetErrorStr();
  4556. return false;
  4557. }
  4558. formatFlags = thisExpr.Substring(dbgEvaluationContext.mExprNode->GetSrcEnd());
  4559. continue;
  4560. }
  4561. else if (strncmp(formatCmd.c_str(), "count=", 6) == 0)
  4562. {
  4563. formatCmd = formatFlags.Substring(1);
  4564. formatCmd = Trim(formatCmd);
  4565. String countExpr = formatCmd.Substring(6);
  4566. if (countExpr.empty())
  4567. break;
  4568. DbgEvaluationContext dbgEvaluationContext(this, dbgModule, countExpr, formatInfo);
  4569. DbgTypedValue countValue = dbgEvaluationContext.EvaluateInContext(contextTypedValue);
  4570. if ((countValue) && (countValue.mType->IsInteger()))
  4571. formatInfo->mOverrideCount = (int)countValue.GetInt64();
  4572. if (dbgEvaluationContext.HadError())
  4573. {
  4574. if (errorString != NULL)
  4575. *errorString = dbgEvaluationContext.GetErrorStr();
  4576. return false;
  4577. }
  4578. formatFlags = countExpr.Substring(dbgEvaluationContext.mExprNode->GetSrcEnd());
  4579. continue;
  4580. }
  4581. else if (strncmp(formatCmd.c_str(), "maxcount=", 9) == 0)
  4582. {
  4583. formatCmd = formatFlags.Substring(1);
  4584. formatCmd = Trim(formatCmd);
  4585. String countExpr = formatCmd.Substring(9);
  4586. if (countExpr.empty())
  4587. break;
  4588. DbgEvaluationContext dbgEvaluationContext(this, dbgModule, countExpr, formatInfo);
  4589. DbgTypedValue countValue = dbgEvaluationContext.EvaluateInContext(contextTypedValue);
  4590. if ((countValue) && (countValue.mType->IsInteger()))
  4591. formatInfo->mOverrideCount = (int)countValue.GetInt64();
  4592. if (dbgEvaluationContext.HadError())
  4593. {
  4594. if (errorString != NULL)
  4595. *errorString = dbgEvaluationContext.GetErrorStr();
  4596. return false;
  4597. }
  4598. formatFlags = countExpr.Substring(dbgEvaluationContext.mExprNode->GetSrcEnd());
  4599. continue;
  4600. }
  4601. else if (strncmp(formatCmd.c_str(), "arraysize=", 10) == 0)
  4602. {
  4603. formatCmd = formatFlags.Substring(1);
  4604. formatCmd = Trim(formatCmd);
  4605. String countExpr = formatCmd.Substring(10);
  4606. if (countExpr.empty())
  4607. break;
  4608. DbgEvaluationContext dbgEvaluationContext(this, dbgModule, countExpr, formatInfo);
  4609. DbgTypedValue countValue = dbgEvaluationContext.EvaluateInContext(contextTypedValue);
  4610. if ((countValue) && (countValue.mType->IsInteger()))
  4611. formatInfo->mArrayLength = (int)countValue.GetInt64();
  4612. if (dbgEvaluationContext.HadError())
  4613. {
  4614. if (errorString != NULL)
  4615. *errorString = dbgEvaluationContext.GetErrorStr();
  4616. return false;
  4617. }
  4618. formatFlags = countExpr.Substring(dbgEvaluationContext.mExprNode->GetSrcEnd());
  4619. continue;
  4620. }
  4621. else if (strncmp(formatCmd.c_str(), "assign=", 7) == 0)
  4622. {
  4623. formatCmd = formatFlags.Substring(1);
  4624. formatCmd = Trim(formatCmd);
  4625. String assignExpr = formatCmd.Substring(7);
  4626. if (assignExpr.empty())
  4627. break;
  4628. DbgEvaluationContext dbgEvaluationContext(this, dbgModule, assignExpr, formatInfo);
  4629. if (dbgEvaluationContext.HadError())
  4630. {
  4631. if (errorString != NULL)
  4632. *errorString = dbgEvaluationContext.GetErrorStr();
  4633. return false;
  4634. }
  4635. if (assignExprOffset != NULL)
  4636. {
  4637. //TODO: Keep track of the offset directly, this is a hack
  4638. *assignExprOffset = (int)formatInfoStr.IndexOf("assign=") + 7;
  4639. }
  4640. if (assignExprString != NULL)
  4641. *assignExprString = dbgEvaluationContext.mExprNode->ToString();
  4642. formatFlags = assignExpr.Substring(dbgEvaluationContext.mExprNode->GetSrcEnd());
  4643. continue;
  4644. }
  4645. else if (strncmp(formatCmd.c_str(), "refid=", 6) == 0)
  4646. {
  4647. formatInfo->mReferenceId = formatCmd.Substring(6);
  4648. if (formatInfo->mReferenceId[0] == '\"')
  4649. formatInfo->mReferenceId = formatInfo->mReferenceId.Substring(1, formatInfo->mReferenceId.length() - 2);
  4650. }
  4651. else if (strncmp(formatCmd.c_str(), "_=", 2) == 0)
  4652. {
  4653. formatInfo->mSubjectExpr = formatCmd.Substring(2);
  4654. if (formatInfo->mSubjectExpr[0] == '\"')
  4655. formatInfo->mSubjectExpr = formatInfo->mSubjectExpr.Substring(1, formatInfo->mSubjectExpr.length() - 2);
  4656. }
  4657. else if (strncmp(formatCmd.c_str(), "expectedType=", 13) == 0)
  4658. {
  4659. formatInfo->mExpectedType = formatCmd.Substring(13);
  4660. if (formatInfo->mExpectedType[0] == '\"')
  4661. formatInfo->mExpectedType = formatInfo->mExpectedType.Substring(1, formatInfo->mExpectedType.length() - 2);
  4662. }
  4663. else if (strncmp(formatCmd.c_str(), "namespaceSearch=", 16) == 0)
  4664. {
  4665. formatInfo->mNamespaceSearch = formatCmd.Substring(16);
  4666. if (formatInfo->mNamespaceSearch[0] == '\"')
  4667. formatInfo->mNamespaceSearch = formatInfo->mNamespaceSearch.Substring(1, formatInfo->mNamespaceSearch.length() - 2);
  4668. }
  4669. else if (formatCmd == "d")
  4670. {
  4671. formatInfo->mDisplayType = DwDisplayType_Decimal;
  4672. }
  4673. else if (formatCmd == "x")
  4674. {
  4675. formatInfo->mDisplayType = DwDisplayType_HexLower;
  4676. }
  4677. else if (formatCmd == "X")
  4678. {
  4679. formatInfo->mDisplayType = DwDisplayType_HexUpper;
  4680. }
  4681. else if (formatCmd == "s")
  4682. {
  4683. formatInfo->mHidePointers = true;
  4684. formatInfo->mDisplayType = DwDisplayType_Ascii;
  4685. }
  4686. else if (formatCmd == "s8")
  4687. {
  4688. formatInfo->mHidePointers = true;
  4689. formatInfo->mDisplayType = DwDisplayType_Utf8;
  4690. }
  4691. else if (formatCmd == "s16")
  4692. {
  4693. formatInfo->mHidePointers = true;
  4694. formatInfo->mDisplayType = DwDisplayType_Utf16;
  4695. }
  4696. else if (formatCmd == "s32")
  4697. {
  4698. formatInfo->mHidePointers = true;
  4699. formatInfo->mDisplayType = DwDisplayType_Utf32;
  4700. }
  4701. else if (formatCmd == "nd")
  4702. {
  4703. formatInfo->mIgnoreDerivedClassInfo = true;
  4704. }
  4705. else if (formatCmd == "na")
  4706. {
  4707. formatInfo->mHidePointers = true;
  4708. }
  4709. else if (formatCmd == "nm")
  4710. {
  4711. formatInfo->mNoMembers = true;
  4712. }
  4713. else if (formatCmd == "ne")
  4714. {
  4715. formatInfo->mNoEdit = true;
  4716. }
  4717. else if (formatCmd == "nv")
  4718. {
  4719. formatInfo->mNoVisualizers = true;
  4720. }
  4721. else if (formatCmd == "rawStr")
  4722. {
  4723. formatInfo->mRawString = true;
  4724. }
  4725. else if (((!formatCmd.IsEmpty()) && ((formatCmd[0] >= '0') && (formatCmd[0] <= '9'))) ||
  4726. (formatCmd.StartsWith("(")))
  4727. {
  4728. String countExpr = formatCmd;
  4729. if (countExpr.empty())
  4730. break;
  4731. DbgEvaluationContext dbgEvaluationContext(this, dbgModule, countExpr, formatInfo);
  4732. DbgTypedValue countValue = dbgEvaluationContext.EvaluateInContext(contextTypedValue);
  4733. if ((countValue) && (countValue.mType->IsInteger()))
  4734. formatInfo->mArrayLength = (int)countValue.GetInt64();
  4735. if (dbgEvaluationContext.HadError())
  4736. {
  4737. if (errorString != NULL)
  4738. *errorString = dbgEvaluationContext.GetErrorStr();
  4739. return false;
  4740. }
  4741. formatFlags = countExpr.Substring(dbgEvaluationContext.mExprNode->GetSrcEnd());
  4742. continue;
  4743. }
  4744. else
  4745. hadError = true;
  4746. if (hadError)
  4747. {
  4748. if (errorString != NULL)
  4749. *errorString = "Invalid format flags";
  4750. return false;
  4751. }
  4752. formatFlags = formatFlags.Substring(nextComma);
  4753. }
  4754. }
  4755. return true;
  4756. }
  4757. String WinDebugger::MaybeQuoteFormatInfoParam(const StringImpl& str)
  4758. {
  4759. bool needsQuote = false;
  4760. for (int i = 0; i < (int)str.length(); i++)
  4761. {
  4762. char c = str[i];
  4763. if (c == ',')
  4764. needsQuote = true;
  4765. }
  4766. if (!needsQuote)
  4767. return str;
  4768. String qStr = "\"";
  4769. qStr += str;
  4770. qStr += "\"";
  4771. return qStr;
  4772. }
  4773. DbgTypedValue WinDebugger::EvaluateInContext(DbgCompileUnit* dbgCompileUnit, const DbgTypedValue& contextTypedValue, const StringImpl& subExpr, DwFormatInfo* formatInfo, String* outReferenceId, String* outErrors)
  4774. {
  4775. DbgEvaluationContext dbgEvaluationContext(this, dbgCompileUnit->mDbgModule, subExpr, formatInfo, contextTypedValue);
  4776. dbgEvaluationContext.mDbgExprEvaluator->mDbgCompileUnit = dbgCompileUnit;
  4777. if (formatInfo != NULL)
  4778. {
  4779. dbgEvaluationContext.mDbgExprEvaluator->mLanguage = formatInfo->mLanguage;
  4780. dbgEvaluationContext.mDbgExprEvaluator->mSubjectExpr = formatInfo->mSubjectExpr;
  4781. }
  4782. dbgEvaluationContext.mDbgExprEvaluator->mReferenceId = outReferenceId;
  4783. auto result = dbgEvaluationContext.EvaluateInContext(contextTypedValue);
  4784. if ((formatInfo != NULL) && (dbgEvaluationContext.mDbgExprEvaluator->mCountResultOverride != -1))
  4785. formatInfo->mOverrideCount = dbgEvaluationContext.mDbgExprEvaluator->mCountResultOverride;
  4786. if (dbgEvaluationContext.mPassInstance->HasFailed())
  4787. {
  4788. if (outErrors != NULL)
  4789. {
  4790. int errIdx = 0;
  4791. for (auto err : dbgEvaluationContext.mPassInstance->mErrors)
  4792. {
  4793. if (errIdx > 0)
  4794. (*outErrors) += "\n";
  4795. (*outErrors) += err->mError;
  4796. errIdx++;
  4797. }
  4798. }
  4799. return DbgTypedValue();
  4800. }
  4801. return result;
  4802. }
  4803. void WinDebugger::DbgVisFailed(DebugVisualizerEntry* debugVis, const StringImpl& evalString, const StringImpl& errors)
  4804. {
  4805. bool onlyMemError = errors.StartsWith("Failed to read") && !errors.Contains('\n');
  4806. if ((!debugVis->mShowedError) && (!onlyMemError))
  4807. {
  4808. debugVis->mShowedError = true;
  4809. String errStr = StrFormat("DbgVis '%s' failed while evaluating condition '%s'\n", debugVis->mName.c_str(), evalString.c_str());
  4810. String spacedErrors = errors;
  4811. spacedErrors.Insert(0, " ");
  4812. spacedErrors.Replace("\n", "\n ");
  4813. errStr += spacedErrors;
  4814. OutputMessage(errStr);
  4815. }
  4816. }
  4817. bool WinDebugger::EvalCondition(DebugVisualizerEntry* debugVis, DbgCompileUnit* dbgCompileUnit, DbgTypedValue typedVal, DwFormatInfo& formatInfo, const StringImpl& condition, const Array<String>& dbgVisWildcardCaptures, String& errorStr)
  4818. {
  4819. DwFormatInfo displayStrFormatInfo = formatInfo;
  4820. displayStrFormatInfo.mHidePointers = false;
  4821. displayStrFormatInfo.mRawString = false;
  4822. String errors;
  4823. const String conditionStr = mDebugManager->mDebugVisualizers->DoStringReplace(condition, dbgVisWildcardCaptures);
  4824. DbgTypedValue evalResult = EvaluateInContext(dbgCompileUnit, typedVal, conditionStr, &displayStrFormatInfo, NULL, &errors);
  4825. if ((!evalResult) || (!evalResult.mType->IsBoolean()))
  4826. {
  4827. if (formatInfo.mRawString)
  4828. return false;
  4829. errorStr += "<DbgVis Failed>";
  4830. DbgVisFailed(debugVis, conditionStr, errors);
  4831. return false;
  4832. }
  4833. return evalResult.mBool;
  4834. }
  4835. String WinDebugger::GetArrayItems(DbgCompileUnit* dbgCompileUnit, DebugVisualizerEntry* debugVis, DbgType* valueType, DbgTypedValue& curNode, int& count, String* outContinuationData)
  4836. {
  4837. DbgEvaluationContext conditionEvaluationContext(this, dbgCompileUnit, debugVis->mCondition);
  4838. String addrs;
  4839. bool checkLeft = true;
  4840. int usedCount = 0;
  4841. while (usedCount < count)
  4842. {
  4843. DbgTypedValue condVal = conditionEvaluationContext.EvaluateInContext(curNode);
  4844. if (!condVal)
  4845. break;
  4846. if (condVal.mBool)
  4847. {
  4848. auto val = curNode;
  4849. if (valueType == NULL)
  4850. {
  4851. String typeAddr = val.mType->ToStringRaw();
  4852. // RPad
  4853. typeAddr.Append(' ', sizeof(addr_target) * 2 - typeAddr.length());
  4854. addrs += typeAddr;
  4855. }
  4856. String addr = EncodeDataPtr(val.mPtr, false);
  4857. addrs += addr;
  4858. usedCount++;
  4859. }
  4860. curNode.mPtr += curNode.mType->mTypeParam->GetStride();
  4861. }
  4862. count = usedCount;
  4863. if (outContinuationData != NULL)
  4864. {
  4865. *outContinuationData += EncodeDataPtr(debugVis, false) + EncodeDataPtr(valueType, false) +
  4866. EncodeDataPtr(curNode.mType, false) + EncodeDataPtr(curNode.mPtr, false);
  4867. }
  4868. return addrs;
  4869. }
  4870. String WinDebugger::GetLinkedListItems(DbgCompileUnit* dbgCompileUnit, DebugVisualizerEntry* debugVis, addr_target endNodePtr, DbgType* valueType, DbgTypedValue& curNode, int& count, String* outContinuationData)
  4871. {
  4872. DbgEvaluationContext nextEvaluationContext(this, dbgCompileUnit, debugVis->mNextPointer);
  4873. DbgEvaluationContext valueEvaluationContext(this, dbgCompileUnit, debugVis->mValuePointer);
  4874. String addrs;
  4875. bool checkLeft = true;
  4876. int mapIdx;
  4877. for (mapIdx = 0; mapIdx < count; mapIdx++)
  4878. {
  4879. if (curNode.mPtr == endNodePtr)
  4880. break;
  4881. DbgTypedValue val = valueEvaluationContext.EvaluateInContext(curNode);
  4882. if (!val)
  4883. break;
  4884. if (val.mPtr == 0)
  4885. break;
  4886. if (valueType == NULL)
  4887. {
  4888. String typeAddr = val.mType->ToStringRaw();
  4889. // RPad
  4890. typeAddr.Append(' ', sizeof(addr_target)*2 - typeAddr.length());
  4891. addrs += typeAddr;
  4892. }
  4893. String addr = EncodeDataPtr(val.mPtr, false);
  4894. addrs += addr;
  4895. curNode = nextEvaluationContext.EvaluateInContext(curNode);
  4896. }
  4897. count = mapIdx;
  4898. if (outContinuationData != NULL)
  4899. {
  4900. *outContinuationData += EncodeDataPtr(debugVis, false) + EncodeDataPtr(endNodePtr, false) + EncodeDataPtr(valueType, false) +
  4901. EncodeDataPtr(curNode.mType, false) + EncodeDataPtr(curNode.mPtr, false);
  4902. }
  4903. return addrs;
  4904. }
  4905. String WinDebugger::GetDictionaryItems(DbgCompileUnit* dbgCompileUnit, DebugVisualizerEntry* debugVis, DbgTypedValue dictValue, int bucketIdx, int nodeIdx, int& count, String* outContinuationData)
  4906. {
  4907. //DbgEvaluationContext bucketsEvaluationContext(this, dbgModule, debugVis->mBuckets);
  4908. DbgEvaluationContext nextEvaluationContext(this, dbgCompileUnit->mDbgModule, debugVis->mNextPointer);
  4909. DbgTypedValue bucketsPtr = EvaluateInContext(dbgCompileUnit, dictValue, debugVis->mBuckets);
  4910. DbgTypedValue entriesPtr = EvaluateInContext(dbgCompileUnit, dictValue, debugVis->mEntries);
  4911. if ((!bucketsPtr) || (!entriesPtr))
  4912. {
  4913. count = -1;
  4914. return "";
  4915. }
  4916. int entrySize = entriesPtr.mType->mTypeParam->GetByteCount();
  4917. String addrs;
  4918. bool checkLeft = true;
  4919. int encodeCount = 0;
  4920. while (encodeCount < count)
  4921. {
  4922. if (nodeIdx != -1)
  4923. {
  4924. DbgTypedValue entryValue;
  4925. entryValue.mSrcAddress = entriesPtr.mPtr + (nodeIdx * entrySize);
  4926. entryValue.mType = entriesPtr.mType->mTypeParam;
  4927. addrs += EncodeDataPtr(entryValue.mSrcAddress, false);
  4928. DbgTypedValue nextValue = nextEvaluationContext.EvaluateInContext(entryValue);
  4929. if ((!nextValue) || (!nextValue.mType->IsInteger()))
  4930. {
  4931. break;
  4932. }
  4933. nodeIdx = (int)nextValue.GetInt64();
  4934. encodeCount++;
  4935. }
  4936. else
  4937. {
  4938. nodeIdx = ReadMemory<int>(bucketsPtr.mPtr + bucketIdx * sizeof(int32));
  4939. bucketIdx++;
  4940. }
  4941. }
  4942. count = encodeCount;
  4943. //count = mapIdx;
  4944. if (outContinuationData != NULL)
  4945. {
  4946. *outContinuationData += EncodeDataPtr(debugVis, false) + EncodeDataPtr(dictValue.mType, false) + EncodeDataPtr(dictValue.mSrcAddress, false) +
  4947. EncodeDataPtr((addr_target)bucketIdx, false) + EncodeDataPtr((addr_target)nodeIdx, false);
  4948. }
  4949. return addrs;
  4950. }
  4951. String WinDebugger::GetTreeItems(DbgCompileUnit* dbgCompileUnit, DebugVisualizerEntry* debugVis, Array<addr_target>& parentList, DbgType*& valueType, DbgTypedValue& curNode, int count, String* outContinuationData)
  4952. {
  4953. DbgEvaluationContext leftEvaluationContext(this, dbgCompileUnit, debugVis->mLeftPointer);
  4954. DbgEvaluationContext rightEvaluationContext(this, dbgCompileUnit, debugVis->mRightPointer);
  4955. DbgEvaluationContext valueEvaluationContext(this, dbgCompileUnit, debugVis->mValuePointer);
  4956. DbgEvaluationContext conditionEvaluationContext(this, dbgCompileUnit, debugVis->mCondition);
  4957. String addrs;
  4958. bool checkLeft = true;
  4959. if ((curNode.mPtr & 2) != 0) // Flag from continuation
  4960. {
  4961. checkLeft = false;
  4962. curNode.mPtr &= (addr_target)~2;
  4963. }
  4964. HashSet<intptr> seenAddrs;
  4965. for (int mapIdx = 0; mapIdx < count; mapIdx++)
  4966. {
  4967. DbgTypedValue readNode;
  4968. while (true)
  4969. {
  4970. bool checkNode = (curNode.mPtr & 1) == 0;
  4971. readNode = curNode;
  4972. readNode.mPtr &= (addr_target)~1;
  4973. if (checkLeft)
  4974. {
  4975. DbgTypedValue leftValue = leftEvaluationContext.EvaluateInContext(readNode);
  4976. bool isEmpty = leftValue.mPtr == NULL;
  4977. if ((leftValue) && (conditionEvaluationContext.HasExpression()))
  4978. {
  4979. auto condValue = conditionEvaluationContext.EvaluateInContext(leftValue);
  4980. if (condValue)
  4981. isEmpty = !condValue.mBool;
  4982. }
  4983. if (isEmpty)
  4984. {
  4985. checkLeft = false;
  4986. break; // Handle node
  4987. }
  4988. parentList.push_back(curNode.mPtr);
  4989. curNode = leftValue;
  4990. }
  4991. else if (checkNode)
  4992. {
  4993. break; // Handle node
  4994. }
  4995. else
  4996. {
  4997. DbgTypedValue rightValue = rightEvaluationContext.EvaluateInContext(readNode);
  4998. bool isEmpty = rightValue.mPtr == NULL;
  4999. if ((rightValue) && (conditionEvaluationContext.HasExpression()))
  5000. {
  5001. auto condValue = conditionEvaluationContext.EvaluateInContext(rightValue);
  5002. if (condValue)
  5003. isEmpty = !condValue.mBool;
  5004. }
  5005. if (!isEmpty)
  5006. {
  5007. curNode = rightValue;
  5008. checkLeft = true;
  5009. }
  5010. else
  5011. {
  5012. if (parentList.size() == 0)
  5013. {
  5014. // Failed
  5015. break;
  5016. }
  5017. curNode.mPtr = parentList.back();
  5018. parentList.pop_back();
  5019. continue; // Don't check against seenAddrs
  5020. }
  5021. }
  5022. if (!seenAddrs.Add(curNode.mPtr))
  5023. {
  5024. // Failed!
  5025. return "";
  5026. }
  5027. }
  5028. DbgTypedValue val = valueEvaluationContext.EvaluateInContext(readNode);
  5029. if (valueType == NULL)
  5030. valueType = val.mType;
  5031. String addr = EncodeDataPtr(val.mPtr, false);
  5032. addrs += addr;
  5033. curNode.mPtr |= 1; // Node handled
  5034. }
  5035. if (!checkLeft)
  5036. curNode.mPtr |= 2;
  5037. if (outContinuationData != NULL)
  5038. {
  5039. *outContinuationData += EncodeDataPtr(debugVis, false) + EncodeDataPtr(valueType, false) + EncodeDataPtr(curNode.mType, false) + EncodeDataPtr(curNode.mPtr, false);
  5040. for (auto parent : parentList)
  5041. *outContinuationData += EncodeDataPtr(parent, false);
  5042. }
  5043. return addrs;
  5044. }
  5045. String WinDebugger::GetCollectionContinuation(const StringImpl& continuationData, int callStackIdx, int count)
  5046. {
  5047. DbgCompileUnit* dbgCompileUnit = GetCallStackCompileUnit(callStackIdx);;
  5048. if (!IsPaused())
  5049. return "";
  5050. const char* dataPtr = continuationData.c_str();
  5051. DebugVisualizerEntry* debugVis = (DebugVisualizerEntry*)DecodeLocalDataPtr(dataPtr);
  5052. if (debugVis->mCollectionType == DebugVisualizerEntry::CollectionType_TreeItems)
  5053. {
  5054. DbgType* valueType = (DbgType*)DecodeLocalDataPtr(dataPtr);
  5055. DbgTypedValue curNode;
  5056. curNode.mType = (DbgType*)DecodeLocalDataPtr(dataPtr);
  5057. curNode.mPtr = DecodeTargetDataPtr(dataPtr);
  5058. Array<addr_target> parentList;
  5059. String newContinuationData;
  5060. while (*dataPtr != 0)
  5061. parentList.push_back(DecodeTargetDataPtr(dataPtr));
  5062. String retVal = GetTreeItems(dbgCompileUnit, debugVis, parentList, valueType, curNode, count, &newContinuationData);
  5063. retVal += "\n" + newContinuationData;
  5064. return retVal;
  5065. }
  5066. else if (debugVis->mCollectionType == DebugVisualizerEntry::CollectionType_LinkedList)
  5067. {
  5068. addr_target endNodePtr = DecodeTargetDataPtr(dataPtr);
  5069. DbgType* valueType = (DbgType*) DecodeLocalDataPtr(dataPtr);
  5070. DbgTypedValue curNode;
  5071. curNode.mType = (DbgType*)DecodeLocalDataPtr(dataPtr);
  5072. curNode.mPtr = DecodeTargetDataPtr(dataPtr);
  5073. String newContinuationData;
  5074. if (count < 0)
  5075. count = 3;
  5076. String retVal = GetLinkedListItems(dbgCompileUnit, debugVis, endNodePtr, valueType, curNode, count, &newContinuationData);
  5077. retVal += "\n" + newContinuationData;
  5078. return retVal;
  5079. }
  5080. else if (debugVis->mCollectionType == DebugVisualizerEntry::CollectionType_Array)
  5081. {
  5082. DbgType* valueType = (DbgType*)DecodeLocalDataPtr(dataPtr);
  5083. DbgTypedValue curNode;
  5084. curNode.mType = (DbgType*)DecodeLocalDataPtr(dataPtr);
  5085. curNode.mPtr = DecodeTargetDataPtr(dataPtr);
  5086. String newContinuationData;
  5087. if (count < 0)
  5088. count = 3;
  5089. String retVal = GetArrayItems(dbgCompileUnit, debugVis, valueType, curNode, count, &newContinuationData);
  5090. retVal += "\n" + newContinuationData;
  5091. return retVal;
  5092. }
  5093. else if (debugVis->mCollectionType == DebugVisualizerEntry::CollectionType_Dictionary)
  5094. {
  5095. DbgTypedValue dictValue;
  5096. dictValue.mType = (DbgType*)DecodeLocalDataPtr(dataPtr);
  5097. dictValue.mSrcAddress = DecodeTargetDataPtr(dataPtr);
  5098. int bucketIdx = (int)DecodeTargetDataPtr(dataPtr);
  5099. int nodeIdx = (int)DecodeTargetDataPtr(dataPtr);
  5100. String newContinuationData;
  5101. String retVal = GetDictionaryItems(dbgCompileUnit, debugVis, dictValue, bucketIdx, nodeIdx, count, &newContinuationData);
  5102. retVal += "\n" + newContinuationData;
  5103. return retVal;
  5104. }
  5105. return "";
  5106. }
  5107. template <typename T>
  5108. static String IntTypeToString(T val, const StringImpl& name, DwDisplayInfo* displayInfo, DwFormatInfo& formatInfo)
  5109. {
  5110. auto intDisplayType = displayInfo->mIntDisplayType;
  5111. if (formatInfo.mDisplayType == DwDisplayType_Decimal)
  5112. intDisplayType = DwIntDisplayType_Decimal;
  5113. else if (formatInfo.mDisplayType == DwDisplayType_HexUpper)
  5114. intDisplayType = DwIntDisplayType_HexadecimalUpper;
  5115. else if (formatInfo.mDisplayType == DwDisplayType_HexLower)
  5116. intDisplayType = DwIntDisplayType_HexadecimalLower;
  5117. if (intDisplayType == DwIntDisplayType_Binary)
  5118. {
  5119. String binary;
  5120. for (int i = 0; i < sizeof(T) * 8; i++)
  5121. {
  5122. if ((i != 0) && (i % 4 == 0))
  5123. binary = "'" + binary;
  5124. if ((i != 0) && (i % 16 == 0))
  5125. binary = "'" + binary;
  5126. binary = ((val & ((T)1 << i)) ? "1" : "0") + binary;
  5127. }
  5128. return StrFormat("0b'%s\n%s", binary.c_str(), name.c_str());
  5129. }
  5130. if (intDisplayType == DwIntDisplayType_Octal)
  5131. {
  5132. String format;
  5133. if (sizeof(T) == 8)
  5134. {
  5135. format = StrFormat("0o%%lo\n%s", name.c_str());
  5136. }
  5137. else
  5138. format = StrFormat("0o%%0%do\n%s", sizeof(val) * 2, name.c_str());
  5139. return StrFormat(format.c_str(), (std::make_unsigned<T>::type)(val));
  5140. }
  5141. if (intDisplayType == DwIntDisplayType_HexadecimalUpper)
  5142. {
  5143. String format;
  5144. if (sizeof(T) == 8)
  5145. {
  5146. format = StrFormat("0x%%l@\n%s", name.c_str());
  5147. }
  5148. else
  5149. format = StrFormat("0x%%0%dX\n%s", sizeof(val) * 2, name.c_str());
  5150. return StrFormat(format.c_str(), (std::make_unsigned<T>::type)(val));
  5151. }
  5152. //TODO: Implement HexadecimalLower
  5153. if (intDisplayType == DwIntDisplayType_HexadecimalLower)
  5154. {
  5155. String format;
  5156. if (sizeof(T) == 8)
  5157. {
  5158. format = StrFormat("0x%%l@\n%s", name.c_str());
  5159. }
  5160. else
  5161. format = StrFormat("0x%%0%dX\n%s", sizeof(val) * 2, name.c_str());
  5162. return StrFormat(format.c_str(), (std::make_unsigned<T>::type)(val));
  5163. }
  5164. if (std::is_unsigned<T>::value)
  5165. {
  5166. if (sizeof(T) == 8)
  5167. {
  5168. if (val > 0x7FFFFFFFF)
  5169. return StrFormat("%llu\n%s\n:editVal\t%lluUL", val, name.c_str(), val);
  5170. else
  5171. return StrFormat("%llu\n%s", val, name.c_str());
  5172. }
  5173. else
  5174. return StrFormat("%u\n%s", val, name.c_str());
  5175. }
  5176. else
  5177. {
  5178. if (sizeof(T) == 8)
  5179. {
  5180. if ((val > 0x7FFFFFFFF) || (val < -0x80000000LL))
  5181. return StrFormat("%lld\n%s\n:editVal\t%lldL", val, name.c_str(), val);
  5182. else
  5183. return StrFormat("%lld\n%s", val, name.c_str(), val);
  5184. }
  5185. else
  5186. return StrFormat("%d\n%s", val, name.c_str());
  5187. }
  5188. }
  5189. DwDisplayInfo* WinDebugger::GetDisplayInfo(const StringImpl& referenceId)
  5190. {
  5191. DwDisplayInfo* displayInfo = &mDebugManager->mDefaultDisplayInfo;
  5192. if (!referenceId.empty())
  5193. {
  5194. mDebugManager->mDisplayInfos.TryGetValue(referenceId, &displayInfo);
  5195. }
  5196. return displayInfo;
  5197. }
  5198. static String WrapWithModifiers(const StringImpl& origName, DbgType* dbgType, DbgLanguage language)
  5199. {
  5200. if (language == DbgLanguage_Unknown)
  5201. language = dbgType->GetLanguage();
  5202. String name = origName;
  5203. while (true)
  5204. {
  5205. if (dbgType->mTypeCode == DbgType_Const)
  5206. {
  5207. if (language == DbgLanguage_Beef)
  5208. name = "readonly " + name;
  5209. else
  5210. name = "const " + name;
  5211. dbgType = dbgType->mTypeParam;
  5212. }
  5213. else if (dbgType->mTypeCode == DbgType_Volatile)
  5214. {
  5215. name = "volatile " + name;
  5216. dbgType = dbgType->mTypeParam;
  5217. }
  5218. else if (dbgType->mTypeCode == DbgType_TypeDef)
  5219. {
  5220. dbgType = dbgType->mTypeParam;
  5221. }
  5222. else if (dbgType->mTypeCode == DbgType_Ref)
  5223. {
  5224. if (language == DbgLanguage_Beef)
  5225. name = "ref " + name;
  5226. else
  5227. name = name + "&";
  5228. dbgType = dbgType->mTypeParam;
  5229. }
  5230. else if (dbgType->mTypeCode == DbgType_Bitfield)
  5231. {
  5232. return dbgType->ToString(language);
  5233. }
  5234. else
  5235. return name;
  5236. }
  5237. }
  5238. DebugVisualizerEntry* WinDebugger::FindVisualizerForType(DbgType* dbgType, Array<String>* wildcardCaptures)
  5239. {
  5240. auto entry = mDebugManager->mDebugVisualizers->FindEntryForType(dbgType->ToString(DbgLanguage_Unknown, true), dbgType->mCompileUnit->mDbgModule->mDbgFlavor, wildcardCaptures);
  5241. if (entry == NULL)
  5242. {
  5243. dbgType = dbgType->GetPrimaryType();
  5244. dbgType->PopulateType();
  5245. for (auto baseTypeEntry : dbgType->mBaseTypes)
  5246. {
  5247. entry = FindVisualizerForType(baseTypeEntry->mBaseType, wildcardCaptures);
  5248. if (entry != NULL)
  5249. break;
  5250. }
  5251. }
  5252. return entry;
  5253. }
  5254. #define GET_FROM(ptr, T) *((T*)(ptr += sizeof(T)) - 1)
  5255. String WinDebugger::ReadString(DbgTypeCode charType, intptr addr, bool isLocalAddr, int maxLength, DwFormatInfo& formatInfo)
  5256. {
  5257. int origMaxLength = maxLength;
  5258. if (addr == 0)
  5259. return "";
  5260. BP_ZONE("WinDebugger::ReadString");
  5261. String retVal = "\"";
  5262. bool wasTerminated = false;
  5263. String valString;
  5264. int maxShowSize = 255;
  5265. if (maxLength == -1)
  5266. maxLength = formatInfo.mOverrideCount;
  5267. else if (formatInfo.mOverrideCount != -1)
  5268. maxLength = BF_MIN(formatInfo.mOverrideCount, maxLength);
  5269. if (formatInfo.mMaxCount != -1)
  5270. maxLength = BF_MIN(formatInfo.mMaxCount, maxLength);
  5271. if (maxLength == -1)
  5272. maxLength = 8 * 1024 * 1024; // Is 8MB crazy?
  5273. if (!formatInfo.mRawString)
  5274. maxLength = BF_MIN(maxLength, maxShowSize);
  5275. //EnableMemCache();
  5276. bool readFailed = false;
  5277. intptr strPtr = addr;
  5278. int charLen = 1;
  5279. if ((charType == DbgType_SChar16) || (charType == DbgType_UChar16))
  5280. charLen = 2;
  5281. else if ((charType == DbgType_SChar32) || (charType == DbgType_UChar32))
  5282. charLen = 4;
  5283. bool isUTF8 = formatInfo.mDisplayType == DwDisplayType_Utf8;
  5284. int readSize = BF_MIN(1024, maxLength * charLen);
  5285. uint8 buf[1024];
  5286. uint8* bufPtr = NULL;
  5287. uint8* bufEnd = NULL;
  5288. bool hasHighAscii = false;
  5289. int i;
  5290. for (i = 0; i < maxLength; i++)
  5291. {
  5292. if (bufPtr >= bufEnd)
  5293. {
  5294. while (true)
  5295. {
  5296. if (readSize < charLen)
  5297. {
  5298. readFailed = true;
  5299. break;
  5300. }
  5301. if (ReadMemory(strPtr, readSize, buf, isLocalAddr))
  5302. break;
  5303. readSize /= 2;
  5304. }
  5305. if (readFailed)
  5306. break;
  5307. bufPtr = buf;
  5308. bufEnd = buf + readSize;
  5309. }
  5310. switch (charLen)
  5311. {
  5312. case 1:
  5313. {
  5314. char c = GET_FROM(bufPtr, char);
  5315. if (c != 0)
  5316. {
  5317. if ((uint8)c >= 0x80)
  5318. hasHighAscii = true;
  5319. valString.Append(c);
  5320. }
  5321. else
  5322. wasTerminated = true;
  5323. }
  5324. break;
  5325. case 2:
  5326. {
  5327. uint16 c16 = GET_FROM(bufPtr, uint16);
  5328. if (c16 != 0)
  5329. {
  5330. char str[8];
  5331. u8_toutf8(str, 8, c16);
  5332. valString += str;
  5333. }
  5334. else
  5335. wasTerminated = true;
  5336. }
  5337. break;
  5338. case 4:
  5339. {
  5340. uint32 c32 = GET_FROM(bufPtr, uint32);
  5341. if (c32 != 0)
  5342. {
  5343. char str[8];
  5344. u8_toutf8(str, 8, c32);
  5345. valString += str;
  5346. }
  5347. else
  5348. wasTerminated = true;
  5349. }
  5350. break;
  5351. }
  5352. if ((wasTerminated) && (formatInfo.mOverrideCount != -1))
  5353. {
  5354. valString += '\x00';
  5355. wasTerminated = false;
  5356. }
  5357. if ((wasTerminated) || (readFailed))
  5358. {
  5359. break;
  5360. }
  5361. strPtr += charLen;
  5362. }
  5363. //DisableMemCache();
  5364. if (formatInfo.mOverrideCount != -1)
  5365. {
  5366. if (i == formatInfo.mOverrideCount)
  5367. wasTerminated = true;
  5368. }
  5369. if (strPtr == addr + origMaxLength)
  5370. wasTerminated = true;
  5371. if (valString.length() == formatInfo.mOverrideCount)
  5372. wasTerminated = true;
  5373. // if (formatInfo.mDisplayType == DwDisplayType_Ascii)
  5374. // {
  5375. // // Our encoding for retVal is already assumed to be UTF8, so the special case here actually Ascii
  5376. // valString = UTF8Encode(ToWString(valString));
  5377. // }
  5378. if (formatInfo.mRawString)
  5379. {
  5380. if ((formatInfo.mDisplayType == DwDisplayType_Utf8) || (!hasHighAscii))
  5381. return valString;
  5382. String utf8Str;
  5383. for (int i = 0; i < (int)valString.length(); i++)
  5384. {
  5385. char c = valString[i];
  5386. if ((uint8)c >= 0x80)
  5387. {
  5388. utf8Str += (char)(0xC0 | (((uint8)c & 0xFF) >> 6));
  5389. utf8Str += (char)(0x80 | ((uint8)c & 0x3F));
  5390. }
  5391. else
  5392. utf8Str += c;
  5393. }
  5394. return utf8Str;
  5395. }
  5396. if ((readFailed) && (valString.IsEmpty()))
  5397. return "< Failed to read string >";
  5398. retVal += SlashString(valString, true, true, formatInfo.mLanguage == DbgLanguage_Beef);
  5399. // We could go over 'maxShowSize' if we have a lot of slashed chars. An uninitialized string can be filled with '\xcc' chars
  5400. if ((!formatInfo.mRawString) && ((int)retVal.length() > maxShowSize))
  5401. {
  5402. retVal = retVal.Substring(0, maxShowSize);
  5403. wasTerminated = false;
  5404. }
  5405. if (wasTerminated)
  5406. retVal += "\"";
  5407. else
  5408. retVal += "...";
  5409. return retVal;
  5410. }
  5411. void WinDebugger::ProcessEvalString(DbgCompileUnit* dbgCompileUnit, DbgTypedValue useTypedValue, String& evalStr, String& displayString, DwFormatInfo& formatInfo, DebugVisualizerEntry* debugVis, bool limitLength)
  5412. {
  5413. for (int i = 0; i < (int)evalStr.length(); i++)
  5414. {
  5415. char c = evalStr[i];
  5416. char nextC = 0;
  5417. if (i < (int)evalStr.length() - 1)
  5418. nextC = evalStr[i + 1];
  5419. if ((c == '{') && (nextC != '{'))
  5420. {
  5421. // Evaluate
  5422. int endIdx = i;
  5423. for (; endIdx < (int)evalStr.length(); endIdx++)
  5424. {
  5425. //TODO: Do better parsing - this paren could be inside a string, for example
  5426. if (evalStr[endIdx] == '}')
  5427. break;
  5428. }
  5429. DwFormatInfo displayStrFormatInfo = formatInfo;
  5430. displayStrFormatInfo.mTotalSummaryLength = formatInfo.mTotalSummaryLength + (int)displayString.length();
  5431. displayStrFormatInfo.mHidePointers = false;
  5432. if ((limitLength) && (displayStrFormatInfo.mTotalSummaryLength > 255))
  5433. {
  5434. displayString += "...";
  5435. }
  5436. else
  5437. {
  5438. String evalString = evalStr.Substring(i + 1, endIdx - i - 1);
  5439. String errors;
  5440. DbgTypedValue evalResult = EvaluateInContext(dbgCompileUnit, useTypedValue, evalString, &displayStrFormatInfo, NULL, &errors);
  5441. if (evalResult)
  5442. {
  5443. if (displayStrFormatInfo.mNoEdit)
  5444. formatInfo.mNoEdit = true;
  5445. String result = DbgTypedValueToString(evalResult, evalString, displayStrFormatInfo, NULL);
  5446. if ((formatInfo.mRawString) && (limitLength))
  5447. {
  5448. displayString = result;
  5449. return;
  5450. }
  5451. int crPos = result.IndexOf('\n');
  5452. if (crPos != -1)
  5453. displayString += result.Substring(0, crPos);
  5454. else
  5455. displayString += result;
  5456. }
  5457. else if (debugVis != NULL)
  5458. {
  5459. displayString += "<DbgVis Failed>";
  5460. DbgVisFailed(debugVis, evalString, errors);
  5461. }
  5462. else
  5463. {
  5464. displayString += "<Eval Failed>";
  5465. }
  5466. }
  5467. i = endIdx;
  5468. continue;
  5469. }
  5470. else if ((c == '{') && (nextC == '{'))
  5471. {
  5472. // Skip next paren
  5473. i++;
  5474. }
  5475. else if ((c == '}') && (nextC == '}'))
  5476. {
  5477. // Skip next paren
  5478. i++;
  5479. }
  5480. displayString += c;
  5481. }
  5482. }
  5483. static bool IsNormalChar(uint32 c)
  5484. {
  5485. return (c < 0x80);
  5486. }
  5487. String WinDebugger::DbgTypedValueToString(const DbgTypedValue& origTypedValue, const StringImpl& expr, DwFormatInfo& formatInfo, DbgExprEvaluator* optEvaluator, bool fullPrecision)
  5488. {
  5489. BP_ZONE("WinDebugger::DbgTypedValueToString");
  5490. DbgTypedValue typedValue = origTypedValue;
  5491. auto dbgCompileUnit = typedValue.mType->mCompileUnit;
  5492. auto dbgModule = typedValue.mType->GetDbgModule();
  5493. auto language = origTypedValue.mType->GetLanguage();
  5494. if (language == DbgLanguage_Unknown)
  5495. language = formatInfo.mLanguage;
  5496. formatInfo.mLanguage = language;
  5497. bool isBeef = language == DbgLanguage_Beef;
  5498. char str[32];
  5499. bool readFailed = false;
  5500. bool isCompositeType = false;
  5501. bool isSizedArray = false;
  5502. bool isEnum = false;
  5503. int64 enumVal = 0;
  5504. String result;
  5505. DwDisplayInfo* displayInfo = GetDisplayInfo(formatInfo.mReferenceId);
  5506. DbgType* origValueType = typedValue.mType;
  5507. bool origHadRef = false;
  5508. DbgType* dwValueType = typedValue.mType->RemoveModifiers(&origHadRef);
  5509. // if (origValueType->mTypeCode == DbgType_Bitfield)
  5510. // {
  5511. // auto dbgBitfieldType = (DbgBitfieldType*)origValueType;
  5512. //
  5513. // typedValue.mUInt64 = typedValue.mUInt64 >> dbgBitfieldType->mPosition;
  5514. //
  5515. // uint64 mask = ((uint64)1<<dbgBitfieldType->mLength) - 1;
  5516. // typedValue.mUInt64 &= mask;
  5517. //
  5518. // if ((dwValueType->IsSigned()) && ((typedValue.mUInt64 & (1LL << (dbgBitfieldType->mLength - 1))) != 0))
  5519. // {
  5520. // // Sign extend
  5521. // typedValue.mUInt64 |= ~mask;
  5522. // }
  5523. // }
  5524. if (dwValueType == NULL)
  5525. dwValueType = dbgModule->GetPrimitiveType(DbgType_Void, language);
  5526. if (dwValueType->mTypeCode == DbgType_TypeDef)
  5527. {
  5528. DbgTypedValue realTypedVal = typedValue;
  5529. realTypedVal.mType = dwValueType->mTypeParam;
  5530. return DbgTypedValueToString(realTypedVal, expr, formatInfo, optEvaluator);
  5531. }
  5532. if (formatInfo.mRawString)
  5533. {
  5534. if ((dwValueType->mTypeCode != DbgType_Struct) && (dwValueType->mTypeCode != DbgType_Class) && (dwValueType->mTypeCode != DbgType_Ptr) && (dwValueType->mTypeCode != DbgType_SizedArray))
  5535. return "";
  5536. }
  5537. auto _ShowArraySummary = [&](String& retVal, addr_target ptrVal, int arraySize, DbgType* innerType)
  5538. {
  5539. String displayString;
  5540. displayString += "{";
  5541. for (int idx = 0; idx < arraySize; idx++)
  5542. {
  5543. if (formatInfo.mTotalSummaryLength + retVal.length() + displayString.length() > 255)
  5544. {
  5545. displayString += "...";
  5546. break;
  5547. }
  5548. if ((idx != 0) && (!displayString.EndsWith('{')))
  5549. displayString += ", ";
  5550. DwFormatInfo displayStrFormatInfo = formatInfo;
  5551. displayStrFormatInfo.mExpandItemDepth = 1;
  5552. displayStrFormatInfo.mTotalSummaryLength = formatInfo.mTotalSummaryLength + retVal.length() + displayString.length();
  5553. displayStrFormatInfo.mHidePointers = false;
  5554. displayStrFormatInfo.mArrayLength = -1;
  5555. // Why did we have this "na" on here? It made "void*[3]" type things show up as "{,,}"
  5556. //String evalStr = "((" + innerType->ToStringRaw(language) + "*)" + EncodeDataPtr(ptrVal, true) + StrFormat(")[%d], na", idx);
  5557. String evalStr = "((" + innerType->ToStringRaw(language) + "*)" + EncodeDataPtr(ptrVal, true) + StrFormat(")[%d]", idx);
  5558. DbgTypedValue evalResult = EvaluateInContext(dbgCompileUnit, typedValue, evalStr, &displayStrFormatInfo);
  5559. String result;
  5560. if (evalResult)
  5561. {
  5562. result = DbgTypedValueToString(evalResult, evalStr, displayStrFormatInfo, NULL);
  5563. int crPos = result.IndexOf('\n');
  5564. if (crPos != -1)
  5565. result.RemoveToEnd(crPos);
  5566. }
  5567. else
  5568. result = "???";
  5569. displayString += result;
  5570. }
  5571. displayString += "}";
  5572. retVal += displayString;
  5573. };
  5574. if (formatInfo.mArrayLength != -1)
  5575. {
  5576. if (formatInfo.mRawString)
  5577. return "";
  5578. if (dwValueType->IsPointer())
  5579. {
  5580. String retVal;
  5581. addr_target ptrVal = (addr_target)typedValue.mPtr;
  5582. if ((!typedValue.mIsLiteral) && (!formatInfo.mHidePointers))
  5583. {
  5584. retVal = EncodeDataPtr(ptrVal, true) + " ";
  5585. retVal += dwValueType->mTypeParam->ToString(language);
  5586. retVal += StrFormat("[%d] ", formatInfo.mArrayLength);
  5587. }
  5588. else
  5589. {
  5590. // Show first item
  5591. // String evalString = "*((" + typedValue.mType->ToStringRaw(language) + ")" + EncodeDataPtr(ptrVal, true) + "), nm";
  5592. // DwFormatInfo emptyFormatInfo;
  5593. // DbgTypedValue evalResult = EvaluateInContext(dbgModule, typedValue, evalString, &emptyFormatInfo);
  5594. // if (evalResult)
  5595. // {
  5596. // retVal += DbgTypedValueToString(evalResult, evalString, emptyFormatInfo, NULL);
  5597. // }
  5598. }
  5599. _ShowArraySummary(retVal, ptrVal, formatInfo.mArrayLength, dwValueType->mTypeParam);
  5600. String idxStr = "[{0}]";
  5601. DbgType* innerType = dwValueType->mTypeParam;
  5602. retVal += "\n" + dwValueType->ToString(language);
  5603. String evalStr = "*((" + typedValue.mType->ToStringRaw(language) + ")" + EncodeDataPtr(ptrVal, true) + " + {0})";
  5604. retVal += "\n:repeat" + StrFormat("\t%d\t%d\t%d", 0, (int)BF_MAX(formatInfo.mArrayLength, 0), 10000) +
  5605. "\t" + idxStr + "\t" + evalStr;
  5606. return retVal;
  5607. }
  5608. else
  5609. {
  5610. DwFormatInfo newFormatInfo = formatInfo;
  5611. newFormatInfo.mArrayLength = -1;
  5612. String retVal = DbgTypedValueToString(typedValue, expr, newFormatInfo, optEvaluator);
  5613. int crPos = (int)retVal.IndexOf('\n');
  5614. if (crPos != -1)
  5615. retVal = "!Array length flag not valid with this type" + retVal.Substring(crPos);
  5616. return retVal;
  5617. }
  5618. }
  5619. switch (dwValueType->mTypeCode)
  5620. {
  5621. case DbgType_Void:
  5622. return "\nvoid";
  5623. case DbgType_Bool:
  5624. {
  5625. if (typedValue.mUInt8 == 0)
  5626. return "false\n" + WrapWithModifiers("bool", origValueType, language);
  5627. else if (typedValue.mUInt8 == 1)
  5628. return "true\n" + WrapWithModifiers("bool", origValueType, language);
  5629. else
  5630. return StrFormat("true (%d)\n", typedValue.mUInt8) + WrapWithModifiers("bool", origValueType, language);
  5631. }
  5632. break;
  5633. case DbgType_UChar:
  5634. if (language != DbgLanguage_Beef)
  5635. return IntTypeToString<int8>(typedValue.mUInt8, WrapWithModifiers("uint8_t", origValueType, language), displayInfo, formatInfo);
  5636. case DbgType_SChar:
  5637. {
  5638. if (typedValue.mInt8 != 0)
  5639. {
  5640. char str[2] = {(char)typedValue.mInt8};
  5641. result = SlashString(str, formatInfo.mDisplayType == DwDisplayType_Utf8, true);
  5642. if (!IsNormalChar(typedValue.mUInt8))
  5643. result = StrFormat("'%s' (0x%02X)\n", result.c_str(), typedValue.mUInt8);
  5644. else
  5645. result = StrFormat("'%s'\n", result.c_str());
  5646. }
  5647. else
  5648. result = "'\\0'\n";
  5649. return result + WrapWithModifiers("char", origValueType, language);
  5650. }
  5651. break;
  5652. case DbgType_UChar16:
  5653. if (language != DbgLanguage_Beef)
  5654. return IntTypeToString<int16>(typedValue.mUInt8, WrapWithModifiers("uint16_t", origValueType, language), displayInfo, formatInfo);
  5655. case DbgType_SChar16:
  5656. {
  5657. if (typedValue.mInt16 != 0)
  5658. {
  5659. u8_toutf8(str, 8, typedValue.mUInt32);
  5660. result = SlashString(str, true, true);
  5661. if (!IsNormalChar(typedValue.mUInt32))
  5662. result = StrFormat("'%s' (0x%02X)\n", result.c_str(), typedValue.mUInt16);
  5663. else
  5664. result = StrFormat("'%s'\n", result.c_str());
  5665. }
  5666. else
  5667. result = "'\\0'";
  5668. return result + WrapWithModifiers(isBeef ? "char16" : "int16_t", origValueType, language);
  5669. }
  5670. break;
  5671. case DbgType_UChar32:
  5672. case DbgType_SChar32:
  5673. {
  5674. if (typedValue.mInt32 != 0)
  5675. {
  5676. u8_toutf8(str, 8, typedValue.mUInt32);
  5677. result = SlashString(str, true, true);
  5678. if (!IsNormalChar(typedValue.mUInt32))
  5679. result = StrFormat("'%s' (0x%02X)\n", result.c_str(), typedValue.mUInt32);
  5680. else
  5681. result = StrFormat("'%s'\n", result.c_str());
  5682. }
  5683. else
  5684. result = "'\\0'";
  5685. return result + WrapWithModifiers(isBeef ? "char32" : "int32_t", origValueType, language);
  5686. }
  5687. break;
  5688. case DbgType_i8:
  5689. return IntTypeToString<int8>(typedValue.mInt8, WrapWithModifiers(isBeef ? "int8" : "int8_t", origValueType, language), displayInfo, formatInfo);
  5690. case DbgType_u8:
  5691. return IntTypeToString<uint8>(typedValue.mUInt8, WrapWithModifiers(isBeef ? "uint8" : "uint8_t", origValueType, language), displayInfo, formatInfo);
  5692. case DbgType_i16:
  5693. return IntTypeToString<int16>(typedValue.mInt16, WrapWithModifiers(isBeef ? "int16" : "int16_t", origValueType, language), displayInfo, formatInfo);
  5694. case DbgType_u16:
  5695. return IntTypeToString<uint16>(typedValue.mUInt16, WrapWithModifiers(isBeef ? "uint16" : "uint16_t", origValueType, language), displayInfo, formatInfo);
  5696. case DbgType_i32:
  5697. return IntTypeToString<int32>(typedValue.mInt32, WrapWithModifiers(isBeef ? "int32" : "int32_t", origValueType, language), displayInfo, formatInfo);
  5698. case DbgType_u32:
  5699. return IntTypeToString<uint32>(typedValue.mUInt32, WrapWithModifiers(isBeef ? "uint32" : "uint32_t", origValueType, language), displayInfo, formatInfo);
  5700. case DbgType_i64:
  5701. return IntTypeToString<int64>(typedValue.mInt64, WrapWithModifiers(isBeef ? "int64" : "int64_t", origValueType, language), displayInfo, formatInfo);
  5702. case DbgType_u64:
  5703. return IntTypeToString<uint64>(typedValue.mUInt64, WrapWithModifiers(isBeef ? "uint64" : "uint64_t", origValueType, language), displayInfo, formatInfo);
  5704. case DbgType_RegGroup:
  5705. {
  5706. if ((typedValue.mRegNum >= CPUReg_M128_XMMREG_FIRST) && (typedValue.mRegNum <= CPUReg_M128_XMMREG_LAST))
  5707. {
  5708. int callStackIdx = formatInfo.mCallStackIdx;
  5709. FixCallStackIdx(callStackIdx);
  5710. UpdateRegisterUsage(callStackIdx);
  5711. WdStackFrame* wdStackFrame = mCallStack[callStackIdx];
  5712. RegForm regForm = RegForm_Unknown;
  5713. if (typedValue.mRegNum < (int)wdStackFrame->mRegForms.size())
  5714. regForm = wdStackFrame->mRegForms[typedValue.mRegNum];
  5715. int xmmMajor = typedValue.mRegNum - CPUReg_M128_XMMREG_FIRST;
  5716. String headerStr;
  5717. String xmmType = "__m128";
  5718. int xmmCount = 4;
  5719. if ((regForm == RegForm_Double) || (regForm == RegForm_Double2) ||
  5720. (regForm == RegForm_Long) || (regForm == RegForm_Long2) ||
  5721. (regForm == RegForm_ULong) || (regForm == RegForm_ULong2))
  5722. xmmCount = 2;
  5723. //TODO: add byte, short, int, etc...
  5724. if (optEvaluator)
  5725. {
  5726. DwMmDisplayType mmDwMmDisplayType = displayInfo->mMmDisplayType;
  5727. if (mmDwMmDisplayType == DwMmDisplayType_Default)
  5728. {
  5729. if ((regForm == RegForm_Double) || (regForm == RegForm_Double2))
  5730. mmDwMmDisplayType = DwMmDisplayType_Double;
  5731. else if (regForm == RegForm_Int4)
  5732. mmDwMmDisplayType = DwMmDisplayType_Int;
  5733. }
  5734. //TODO: Add support for int types
  5735. if (mmDwMmDisplayType == DwMmDisplayType_Double)
  5736. {
  5737. xmmType = "__m128d";
  5738. xmmCount = 2;
  5739. double xmmRegVals[2];
  5740. CPURegisters* regs = optEvaluator->GetRegisters();
  5741. for (int xmmMinor = 0; xmmMinor < xmmCount; ++xmmMinor)
  5742. {
  5743. DbgTypedValue xmmReg = GetRegister(StrFormat("xmm%d_%d", xmmMajor, xmmMinor), language, regs, &wdStackFrame->mRegForms);
  5744. BF_ASSERT(xmmReg.mType->mTypeCode == DbgType_Double);
  5745. BF_ASSERT(xmmReg.mRegNum == CPUReg_XMMREG_FIRST + (xmmMajor * 4) + xmmMinor);
  5746. xmmRegVals[xmmMinor] = xmmReg.mDouble;
  5747. }
  5748. headerStr = StrFormat("(%f, %f)", xmmRegVals[0], xmmRegVals[1]);
  5749. }
  5750. else if (mmDwMmDisplayType == DwMmDisplayType_Int)
  5751. {
  5752. int xmmRegVals[4];
  5753. xmmCount = 4;
  5754. CPURegisters* regs = optEvaluator->GetRegisters();
  5755. for (int xmmMinor = 0; xmmMinor < xmmCount; ++xmmMinor)
  5756. {
  5757. DbgTypedValue xmmReg = GetRegister(StrFormat("xmm%d_%d", xmmMajor, xmmMinor), language, regs, &wdStackFrame->mRegForms);
  5758. BF_ASSERT(xmmReg.mType->mTypeCode == DbgType_i32);
  5759. BF_ASSERT(xmmReg.mRegNum == CPUReg_XMMREG_FIRST + (xmmMajor * 4) + xmmMinor);
  5760. xmmRegVals[xmmMinor] = xmmReg.mInt32;
  5761. }
  5762. headerStr = StrFormat("(%d, %d, %d, %d)", xmmRegVals[0], xmmRegVals[1], xmmRegVals[2], xmmRegVals[3]);
  5763. }
  5764. else // Float
  5765. {
  5766. float xmmRegVals[4];
  5767. xmmCount = 4;
  5768. CPURegisters* regs = optEvaluator->GetRegisters();
  5769. for (int xmmMinor = 0; xmmMinor < xmmCount; ++xmmMinor)
  5770. {
  5771. DbgTypedValue xmmReg = GetRegister(StrFormat("xmm%d_%d", xmmMajor, xmmMinor), language, regs, &wdStackFrame->mRegForms);
  5772. BF_ASSERT(xmmReg.mType->mTypeCode == DbgType_Single);
  5773. BF_ASSERT(xmmReg.mRegNum == CPUReg_XMMREG_FIRST + (xmmMajor * 4) + xmmMinor);
  5774. xmmRegVals[xmmMinor] = xmmReg.mSingle;
  5775. }
  5776. headerStr = StrFormat("(%f, %f, %f, %f)", xmmRegVals[0], xmmRegVals[1], xmmRegVals[2], xmmRegVals[3]);
  5777. }
  5778. }
  5779. else
  5780. {
  5781. headerStr = StrFormat("XMM%d", xmmMajor);
  5782. }
  5783. result = headerStr + "\n" + xmmType;
  5784. for (int i = 0; i < xmmCount; i++)
  5785. result += WrapWithModifiers(StrFormat("\n[%d]\t$xmm%d_%d", i, xmmMajor, i, language), origValueType, language);
  5786. return result;
  5787. }
  5788. else
  5789. {
  5790. switch (typedValue.mRegNum)
  5791. {
  5792. case CPUReg_CAT_ALLREGS:
  5793. {
  5794. return "ALLREGS\n__allregs\niregs\t$iregs\nflags\t$flags\nfpregs\t$fpregs\nmmregs\t$mmregs\nxmmregs\t$xmmregs";
  5795. }
  5796. break;
  5797. case CPUReg_CAT_IREGS:
  5798. {
  5799. #ifdef BF_DBG_32
  5800. String headerStr;
  5801. if (optEvaluator)
  5802. {
  5803. CPURegisters* regs = optEvaluator->GetRegisters();
  5804. headerStr = StrFormat("(eax=0x%08x, ebx=0x%08x, ecx=0x%08x, edx=0x%08x, esi=0x%08x, edi=0x%08x, esp=0x%08x, ebp=0x%08x, eip=0x%08x, efl=0x%08x)",
  5805. (uint32)regs->mIntRegs.eax, (uint32)regs->mIntRegs.ebx, (uint32)regs->mIntRegs.ecx, (uint32)regs->mIntRegs.edx,
  5806. (uint32)regs->mIntRegs.esi, (uint32)regs->mIntRegs.edi, (uint32)regs->mIntRegs.esp, (uint32)regs->mIntRegs.ebp,
  5807. (uint32)regs->mIntRegs.eip, (uint32)regs->mIntRegs.efl);
  5808. }
  5809. else
  5810. {
  5811. headerStr = "IREGS";
  5812. }
  5813. return StrFormat("%s\n__iregs\neax\t$eax\nebx\t$ebx\necx\t$ecx\nedx\t$edx\nesi\t$esi\nedi\t$edi\nesp\t$esp\nebp\t$ebp\neip\t$eip", headerStr.c_str());
  5814. #else
  5815. String headerStr;
  5816. if (optEvaluator)
  5817. {
  5818. CPURegisters* regs = optEvaluator->GetRegisters();
  5819. headerStr = StrFormat("(rax=0x%@, rbx=0x%@, rcx=0x%@, rdx=0x%@, rsi=0x%@, rdi=0x%@, rsp=0x%@, rbp=0x%@, eip=0x%@, r8=0x%@, r9=0x%@, r10=0x%@, r11=0x%@, r12=0x%@, r13=0x%@, r14=0x%@, r15=0x%@, efl=0x%08x)",
  5820. (uint64)regs->mIntRegs.rax, (uint64)regs->mIntRegs.rbx, (uint64)regs->mIntRegs.rcx, (uint64)regs->mIntRegs.rdx,
  5821. (uint64)regs->mIntRegs.rsi, (uint64)regs->mIntRegs.rdi, (uint64)regs->mIntRegs.rsp, (uint64)regs->mIntRegs.rbp,
  5822. (uint64)regs->mIntRegs.rip,
  5823. (uint64)regs->mIntRegs.r8, (uint64)regs->mIntRegs.r9, (uint64)regs->mIntRegs.r10, (uint64)regs->mIntRegs.r11,
  5824. (uint64)regs->mIntRegs.r12, (uint64)regs->mIntRegs.r13, (uint64)regs->mIntRegs.r14, (uint64)regs->mIntRegs.r15,
  5825. (uint32)regs->mIntRegs.efl);
  5826. }
  5827. else
  5828. {
  5829. headerStr = "IREGS";
  5830. }
  5831. return StrFormat("%s\n__iregs\neax\t$eax\nebx\t$ebx\necx\t$ecx\nedx\t$edx\nesi\t$esi\nedi\t$edi\nesp\t$esp\nebp\t$ebp\neip\t$eip\nr8\t$r8\nr9\t$r9\nr10\t$r10\nr11\t$r11\nr12\t$r12\nr13\t$r13\nr14\t$r14\nr15\t$r15", headerStr.c_str());
  5832. #endif
  5833. }
  5834. break;
  5835. case CPUReg_CAT_FPREGS:
  5836. {
  5837. String headerStr;
  5838. if (optEvaluator)
  5839. {
  5840. CPURegisters* regs = optEvaluator->GetRegisters();
  5841. headerStr = "(";
  5842. for (int i = 0; i < CPURegisters::kNumFpMmRegs; ++i)
  5843. {
  5844. if (i)
  5845. headerStr += ", ";
  5846. double val = ConvertFloat80ToDouble(regs->mFpMmRegsArray[i].fp.fp80);
  5847. headerStr += StrFormat("%f", val);
  5848. }
  5849. headerStr += ")";
  5850. }
  5851. else
  5852. {
  5853. headerStr = "FPREGS";
  5854. }
  5855. result = StrFormat("%s\n__fpregs", headerStr.c_str());
  5856. for (int i = 0; i < CPURegisters::kNumFpMmRegs; ++i)
  5857. result += StrFormat("\n[%d]\t$st%d", i, i);
  5858. return result;
  5859. }
  5860. break;
  5861. case CPUReg_CAT_MMREGS:
  5862. {
  5863. String headerStr;
  5864. if (optEvaluator)
  5865. {
  5866. CPURegisters* regs = optEvaluator->GetRegisters();
  5867. headerStr = "(";
  5868. for (int i = 0; i < CPURegisters::kNumFpMmRegs; ++i)
  5869. {
  5870. if (i)
  5871. headerStr += ", ";
  5872. uint64 val = regs->mFpMmRegsArray[i].mm;
  5873. headerStr += StrFormat("0x%016llx", val);
  5874. }
  5875. headerStr += ")";
  5876. }
  5877. else
  5878. {
  5879. headerStr = "MMREGS";
  5880. }
  5881. result = StrFormat("%s\n__mmregs", headerStr.c_str());
  5882. for (int i = 0; i < CPURegisters::kNumFpMmRegs; ++i)
  5883. result += StrFormat("\n[%d]\t$mm%d", i, i);
  5884. return result;
  5885. }
  5886. break;
  5887. case CPUReg_CAT_XMMREGS:
  5888. {
  5889. String headerStr = StrFormat("XMMREGS[%d]", CPURegisters::kNumXmmRegs); // these are too big to put a useful header for the entire category
  5890. result = StrFormat("%s\n__xmmregs", headerStr.c_str());
  5891. for (int i = 0; i < CPURegisters::kNumXmmRegs; ++i)
  5892. result += StrFormat("\n[%d]\t$xmm%d", i, i);
  5893. return result;
  5894. }
  5895. break;
  5896. case CPUReg_CAT_FLAGS:
  5897. {
  5898. String headerStr;
  5899. if (optEvaluator)
  5900. {
  5901. CPURegisters* regs = optEvaluator->GetRegisters();
  5902. #ifdef BF_DBG_32
  5903. #define FLAGVAR(abbr, name) int flag##abbr = ((regs->mIntRegs.efl & ((uint64)1 << CPURegisters::GetFlagBitForRegister(X86Reg_FLAG_##abbr##_##name))) != 0) ? 1 : 0
  5904. FLAGVAR(CF, CARRY);
  5905. FLAGVAR(PF, PARITY);
  5906. FLAGVAR(AF, ADJUST);
  5907. FLAGVAR(ZF, ZERO);
  5908. FLAGVAR(SF, SIGN);
  5909. FLAGVAR(IF, INTERRUPT);
  5910. FLAGVAR(DF, DIRECTION);
  5911. FLAGVAR(OF, OVERFLOW);
  5912. #undef FLAGVAR
  5913. #else
  5914. #define FLAGVAR(abbr, name) int flag##abbr = ((regs->mIntRegs.efl & ((uint64)1 << CPURegisters::GetFlagBitForRegister(X64Reg_FLAG_##abbr##_##name))) != 0) ? 1 : 0
  5915. FLAGVAR(CF, CARRY);
  5916. FLAGVAR(PF, PARITY);
  5917. FLAGVAR(AF, ADJUST);
  5918. FLAGVAR(ZF, ZERO);
  5919. FLAGVAR(SF, SIGN);
  5920. FLAGVAR(IF, INTERRUPT);
  5921. FLAGVAR(DF, DIRECTION);
  5922. FLAGVAR(OF, OVERFLOW);
  5923. #undef FLAGVAR
  5924. #endif
  5925. headerStr = StrFormat("(CF=%d, PF=%d, AF=%d, ZF=%d, SF=%d, IF=%d, DF=%d, OF=%d)",
  5926. flagCF, flagPF, flagAF, flagZF, flagSF, flagIF, flagDF, flagOF);
  5927. }
  5928. else
  5929. {
  5930. headerStr = "FLAGS";
  5931. }
  5932. return StrFormat("%s\n__flags\nCarry (CF)\t$flagcf\nParity (PF)\t$flagpf\nAdjust (AF)\t$flagaf\nZero (ZF)\t$flagzf\nSign (SF)\t$flagsf\nInterrupt (IF)\t$flagif\nDirection (DF)\t$flagdf\nOverflow (OF)\t$flagof",
  5933. headerStr.c_str());
  5934. }
  5935. break;
  5936. default:
  5937. BF_ASSERT(false && "unknown category register");
  5938. return "UNKNOWNCATEGORY\n__unknown\n";
  5939. }
  5940. }
  5941. }
  5942. break;
  5943. case DbgType_Single:
  5944. {
  5945. ExactMinimalFloatToStr(typedValue.mSingle, str);
  5946. return StrFormat("%s\n%s", str, WrapWithModifiers("float", origValueType, language).c_str());
  5947. }
  5948. case DbgType_Double:
  5949. ExactMinimalDoubleToStr(typedValue.mDouble, str);
  5950. return StrFormat("%s\n%s", str, WrapWithModifiers("double", origValueType, language).c_str());
  5951. case DbgType_Subroutine:
  5952. if (typedValue.mCharPtr != NULL)
  5953. return StrFormat("%s\nfunc", typedValue.mCharPtr);
  5954. else
  5955. return "\nfunc";
  5956. case DbgType_RawText:
  5957. return StrFormat("%s\nrawtext", typedValue.mCharPtr);
  5958. case DbgType_Ptr:
  5959. {
  5960. addr_target ptrVal = (addr_target)typedValue.mPtr;
  5961. String retVal;
  5962. DbgType* innerType = dwValueType->mTypeParam;
  5963. if (innerType == NULL)
  5964. return EncodeDataPtr(ptrVal, true) + "\nvoid*";
  5965. bool isChar = false;
  5966. DbgType* unmodInnerType = innerType->RemoveModifiers();
  5967. if (unmodInnerType != NULL)
  5968. {
  5969. if (language == DbgLanguage_Beef)
  5970. {
  5971. if ((unmodInnerType->mTypeCode == DbgType_UChar) ||
  5972. (unmodInnerType->mTypeCode == DbgType_UChar16) ||
  5973. (unmodInnerType->mTypeCode == DbgType_UChar32))
  5974. isChar = true;
  5975. }
  5976. else
  5977. {
  5978. if ((unmodInnerType->mTypeCode == DbgType_SChar) ||
  5979. (unmodInnerType->mTypeCode == DbgType_SChar16) ||
  5980. (unmodInnerType->mTypeCode == DbgType_SChar32))
  5981. isChar = true;
  5982. }
  5983. }
  5984. if ((isChar) && (formatInfo.mArrayLength == -1))
  5985. {
  5986. if ((!typedValue.mIsLiteral) && (!formatInfo.mHidePointers))
  5987. retVal = EncodeDataPtr(ptrVal, true);
  5988. String strResult = ReadString(unmodInnerType->mTypeCode, typedValue.mLocalIntPtr, typedValue.mIsLiteral, typedValue.mIsLiteral ? strlen(typedValue.mCharPtr) : -1, formatInfo);
  5989. if (formatInfo.mRawString)
  5990. return strResult;
  5991. if (!strResult.IsEmpty())
  5992. {
  5993. if (!retVal.IsEmpty())
  5994. retVal += " ";
  5995. retVal += strResult;
  5996. }
  5997. retVal += "\n" + origValueType->ToString(language);
  5998. return retVal;
  5999. }
  6000. else if ((unmodInnerType != NULL) &&
  6001. ((unmodInnerType->mTypeCode == DbgType_Class) || (unmodInnerType->mTypeCode == DbgType_Struct) || (unmodInnerType->mTypeCode == DbgType_Union)))
  6002. {
  6003. isCompositeType = true;
  6004. }
  6005. else if ((unmodInnerType != NULL) && (unmodInnerType->mTypeCode == DbgType_SizedArray))
  6006. {
  6007. isSizedArray = true;
  6008. }
  6009. else if (unmodInnerType->mTypeCode == DbgType_Subroutine)
  6010. {
  6011. if (formatInfo.mRawString)
  6012. return "";
  6013. addr_target funcPtr = (addr_target)typedValue.mPtr;
  6014. String retVal;
  6015. if ((!typedValue.mIsLiteral) && (!formatInfo.mHidePointers))
  6016. retVal = EncodeDataPtr(funcPtr, true);
  6017. String symbolName;
  6018. addr_target offset;
  6019. DbgModule* dwarf;
  6020. static String demangledName;
  6021. auto subProgram = mDebugTarget->FindSubProgram(funcPtr);
  6022. if (subProgram != NULL)
  6023. {
  6024. demangledName = subProgram->ToString();
  6025. }
  6026. else if (mDebugTarget->FindSymbolAt(funcPtr, &symbolName, &offset, &dwarf))
  6027. {
  6028. demangledName = BfDemangler::Demangle(symbolName, language);
  6029. if (offset != 0)
  6030. demangledName += StrFormat("+%d", offset);
  6031. }
  6032. else
  6033. {
  6034. auto dbgModule = mDebugTarget->FindDbgModuleForAddress(funcPtr);
  6035. if (dbgModule != NULL)
  6036. demangledName += dbgModule->mDisplayName + "!";
  6037. demangledName += StrFormat("0x%@", funcPtr);
  6038. }
  6039. retVal += " {";
  6040. retVal += demangledName;
  6041. retVal += "}";
  6042. retVal += "\n" + origValueType->ToString(language);
  6043. return retVal;
  6044. }
  6045. else if (unmodInnerType->mTypeCode == DbgType_Void)
  6046. {
  6047. if (formatInfo.mRawString)
  6048. return "";
  6049. addr_target ptr = (addr_target)typedValue.mPtr;
  6050. String symbolName;
  6051. addr_target offset;
  6052. DbgModule* dwarf;
  6053. String demangledName;
  6054. retVal += demangledName = StrFormat("0x%@", ptr);
  6055. if (mDebugTarget->FindSymbolAt(ptr, &symbolName, &offset, &dwarf))
  6056. {
  6057. if (offset == 0)
  6058. {
  6059. retVal += " {";
  6060. retVal += BfDemangler::Demangle(symbolName, language);
  6061. retVal += "}";
  6062. }
  6063. }
  6064. retVal += "\n" + origValueType->ToString(language);
  6065. return retVal;
  6066. }
  6067. else
  6068. {
  6069. if (formatInfo.mRawString)
  6070. return "";
  6071. addr_target ptrVal = (addr_target)typedValue.mPtr;
  6072. String retVal;
  6073. if ((!typedValue.mIsLiteral) && (!formatInfo.mHidePointers))
  6074. retVal = EncodeDataPtr(ptrVal, true);
  6075. if (ptrVal != 0)
  6076. {
  6077. DbgExprEvaluator dbgExprEvaluator(this, dbgModule, NULL, -1, -1);
  6078. DbgTypedValue innerTypedVal = dbgExprEvaluator.ReadTypedValue(innerType, typedValue.mPtr, DbgAddrType_Target);
  6079. if (innerTypedVal)
  6080. {
  6081. DwFormatInfo defaultFormatInfo;
  6082. defaultFormatInfo.mLanguage = formatInfo.mLanguage;
  6083. defaultFormatInfo.mTotalSummaryLength = formatInfo.mTotalSummaryLength + 2; // Take into accout the necessary {}'s
  6084. defaultFormatInfo.mExpandItemDepth++;
  6085. String innerStr = DbgTypedValueToString(innerTypedVal, "", defaultFormatInfo, &dbgExprEvaluator);
  6086. int crIdx = innerStr.IndexOf('\n');
  6087. if (crIdx != -1)
  6088. {
  6089. String innerDataStr = innerStr.Substring(0, crIdx);
  6090. if (!innerDataStr.empty())
  6091. {
  6092. if (!retVal.empty())
  6093. retVal += " ";
  6094. retVal += "{" + innerDataStr + "}";
  6095. }
  6096. }
  6097. else
  6098. {
  6099. retVal += "{ ??? }";
  6100. }
  6101. }
  6102. }
  6103. retVal += "\n" + origValueType->ToString(language);
  6104. innerType->PopulateType();
  6105. if ((ptrVal != 0) &&
  6106. ((!innerType->mMemberList.IsEmpty()) || (innerType->mSize > 0) || (innerType->mTypeParam != NULL)))
  6107. {
  6108. String ptrDataStr = StrFormat("(%s)", dwValueType->ToStringRaw(language).c_str()) + EncodeDataPtr(typedValue.mPtr, true);
  6109. retVal += "\n*\t";
  6110. // Why did we have this? It messed up a pointer to sized array
  6111. /*if (language == DbgLanguage_Beef)
  6112. retVal += "this";
  6113. else*/
  6114. retVal += "*this";
  6115. if (!formatInfo.mReferenceId.empty())
  6116. retVal += ", refid=" + MaybeQuoteFormatInfoParam(formatInfo.mReferenceId);
  6117. retVal += ", this=" + ptrDataStr;
  6118. }
  6119. return retVal;
  6120. }
  6121. break;
  6122. }
  6123. case DbgType_Union:
  6124. case DbgType_Class:
  6125. case DbgType_Struct:
  6126. isCompositeType = true;
  6127. break;
  6128. case DbgType_Enum:
  6129. enumVal = typedValue.GetInt64();
  6130. isEnum = true;
  6131. break;
  6132. case DbgType_SizedArray:
  6133. {
  6134. isSizedArray = true;
  6135. }
  6136. break;
  6137. default:
  6138. break;
  6139. }
  6140. if (isSizedArray)
  6141. {
  6142. String retVal;
  6143. addr_target ptrVal = 0;
  6144. DbgType* arrayType = dwValueType;
  6145. DbgType* innerType = dwValueType->mTypeParam;
  6146. if (dwValueType->mTypeCode == DbgType_SizedArray)
  6147. {
  6148. ptrVal = (addr_target)typedValue.mSrcAddress;
  6149. }
  6150. else
  6151. {
  6152. BF_ASSERT(dwValueType->mTypeCode == DbgType_Ptr);
  6153. arrayType = innerType;
  6154. innerType = arrayType->mTypeParam;
  6155. ptrVal = typedValue.mPtr;
  6156. if ((!typedValue.mIsLiteral) && (!formatInfo.mHidePointers))
  6157. retVal = EncodeDataPtr(ptrVal, true) + " ";
  6158. }
  6159. if (ptrVal == 0)
  6160. ptrVal = typedValue.mPtr;
  6161. int arraySize = 0;
  6162. int innerSize = innerType->GetStride();
  6163. if (innerSize > 0)
  6164. arraySize = arrayType->GetStride() / innerSize;
  6165. else
  6166. {
  6167. // Failure!
  6168. }
  6169. String idxStr = "[{0}]";
  6170. if (innerType->IsChar(language))
  6171. {
  6172. String strVal = ReadString(innerType->mTypeCode, typedValue.mSrcAddress, false, arraySize, formatInfo);
  6173. if (formatInfo.mRawString)
  6174. return strVal;
  6175. retVal += strVal;
  6176. }
  6177. else
  6178. {
  6179. if (formatInfo.mRawString)
  6180. return "";
  6181. _ShowArraySummary(retVal, ptrVal, arraySize, innerType);
  6182. }
  6183. retVal += "\n" + origValueType->ToString(language);
  6184. String referenceId = dwValueType->ToString(language);
  6185. String evalStr;
  6186. // Why did we have the "na"? Do we not want to show addresses for all members?
  6187. //evalStr = "((" + innerType->ToStringRaw(language) + "*)" + EncodeDataPtr(ptrVal, true) + ")[{0}], na, refid=" + referenceId + ".[]";
  6188. evalStr = "((" + innerType->ToStringRaw(language) + "*)" + EncodeDataPtr(ptrVal, true) + ")[{0}], refid=" + MaybeQuoteFormatInfoParam(referenceId + ".[]");
  6189. if (typedValue.mIsReadOnly)
  6190. evalStr += ", ne";
  6191. retVal += "\n:repeat" + StrFormat("\t%d\t%d\t%d", 0, (int)BF_MAX(arraySize, 0), 10000) +
  6192. "\t" + idxStr + "\t" + evalStr;
  6193. return retVal;
  6194. }
  6195. dwValueType->PopulateType();
  6196. if (isEnum)
  6197. {
  6198. String retVal;
  6199. int64 bitsLeft = enumVal;
  6200. int valueCount = 0;
  6201. String editVal;
  6202. dwValueType = dwValueType->GetPrimaryType();
  6203. dwValueType->PopulateType();
  6204. while ((bitsLeft != 0) || (valueCount == 0))
  6205. {
  6206. DbgVariable* bestMatch = NULL;
  6207. for (auto member : dwValueType->mMemberList)
  6208. {
  6209. if (member->mConstValue == bitsLeft)
  6210. {
  6211. bestMatch = member;
  6212. break;
  6213. }
  6214. }
  6215. if (bestMatch == NULL)
  6216. {
  6217. for (auto member : dwValueType->mMemberList)
  6218. {
  6219. if ((member->mConstValue != 0) &&
  6220. ((member->mConstValue & bitsLeft) == member->mConstValue))
  6221. {
  6222. bestMatch = member;
  6223. break;
  6224. }
  6225. }
  6226. }
  6227. if (bestMatch == NULL)
  6228. break;
  6229. if (valueCount > 0)
  6230. {
  6231. retVal += " | ";
  6232. if (language == DbgLanguage_C)
  6233. editVal += " | ";
  6234. }
  6235. if (language == DbgLanguage_Beef)
  6236. retVal += ".";
  6237. retVal += bestMatch->mName;
  6238. if (language == DbgLanguage_C)
  6239. {
  6240. if (dwValueType->mParent != NULL)
  6241. {
  6242. editVal += dwValueType->mParent->ToString(language);
  6243. editVal += "::";
  6244. }
  6245. editVal += bestMatch->mName;
  6246. }
  6247. valueCount++;
  6248. bitsLeft &= ~bestMatch->mConstValue;
  6249. }
  6250. if ((valueCount == 0) || (bitsLeft != 0))
  6251. {
  6252. if (valueCount > 0)
  6253. retVal += " | ";
  6254. retVal += StrFormat("%d", bitsLeft);
  6255. if (language == DbgLanguage_C)
  6256. {
  6257. if (valueCount > 0)
  6258. editVal += " | ";
  6259. editVal += StrFormat("%d", bitsLeft);
  6260. }
  6261. }
  6262. retVal += "\n" + origValueType->ToString();
  6263. if (language == DbgLanguage_C)
  6264. {
  6265. retVal += "\n:editVal\t";
  6266. retVal += editVal;
  6267. }
  6268. retVal += "\n:canEdit";
  6269. return retVal;
  6270. }
  6271. else if (isCompositeType)
  6272. {
  6273. addr_target ptrVal;
  6274. if (dwValueType->IsPointer())
  6275. ptrVal = (addr_target)typedValue.mPtr;
  6276. else
  6277. ptrVal = (addr_target)typedValue.mSrcAddress;
  6278. String retVal;
  6279. if ((!typedValue.mIsLiteral) && (dwValueType->IsPointer()) &&
  6280. ((!formatInfo.mHidePointers) || (ptrVal == 0)))
  6281. retVal = EncodeDataPtr(ptrVal, true);
  6282. DbgType* innerType = dwValueType;
  6283. bool wasPtr = false;
  6284. if (innerType->mTypeCode == DbgType_Ptr)
  6285. {
  6286. wasPtr = true;
  6287. innerType = dwValueType->mTypeParam;
  6288. innerType = innerType->RemoveModifiers();
  6289. }
  6290. innerType = innerType->GetPrimaryType();
  6291. addr_target dataPtr = wasPtr ? typedValue.mPtr : typedValue.mSrcAddress;
  6292. DbgType* actualType = NULL;
  6293. bool useActualRawType = false;
  6294. bool isBfObject = innerType->IsBfObject();
  6295. bool hasCPPVTable = false;
  6296. if (!isBfObject)
  6297. hasCPPVTable = innerType->HasCPPVTable();
  6298. int bfObjectFlags = 0;
  6299. addr_target classVDataPtr = 0;
  6300. bool isAppendBfObject = false;
  6301. bool isStackBfObject = false;
  6302. bool isDeletedBfObject = false;
  6303. bool isCompositeWithoutAddress = false;
  6304. if (innerType->IsBfPayloadEnum())
  6305. {
  6306. if (formatInfo.mRawString)
  6307. return "";
  6308. auto tagMember = innerType->mMemberList.mTail;
  6309. int tagIdx = 0;
  6310. if (dataPtr == -1)
  6311. {
  6312. DbgEvaluationContext dbgEvaluationContext(this, dbgModule, "(int)" + expr, &formatInfo);
  6313. auto dscValue = dbgEvaluationContext.EvaluateInContext(DbgTypedValue());
  6314. tagIdx = dscValue.mInt32;
  6315. }
  6316. else if (!ReadMemory((intptr)ptrVal + tagMember->mMemberOffset, tagMember->mType->mSize, (void*)&tagIdx))
  6317. {
  6318. return StrFormat("!Failed to read from 0x%@", ptrVal);
  6319. }
  6320. char findStr[16];
  6321. findStr[0] = '_';
  6322. itoa(tagIdx, findStr + 1, 10);
  6323. int len = strlen(findStr);
  6324. findStr[len] = '_';
  6325. len++;
  6326. if (!retVal.empty())
  6327. retVal += " ";
  6328. int startIdx = 0;
  6329. for (auto member : innerType->mMemberList)
  6330. {
  6331. if (strncmp(member->mName, findStr, len) == 0)
  6332. {
  6333. retVal += ".";
  6334. retVal += member->mName + len;
  6335. String tupleExpr;
  6336. DbgTypedValue tupleVal;
  6337. if (dataPtr == -1)
  6338. {
  6339. tupleVal.mSrcAddress = -1;
  6340. tupleVal.mType = member->mType;
  6341. //tupleExpr = "$" + expr + "$u";
  6342. tupleVal.mVariable = typedValue.mVariable;
  6343. tupleExpr = "(" + member->mType->ToStringRaw() + ")(" + expr + ")";
  6344. }
  6345. else
  6346. {
  6347. tupleVal.mType = member->mType;
  6348. tupleVal.mSrcAddress = ptrVal;
  6349. }
  6350. DwFormatInfo displayStrFormatInfo = formatInfo;
  6351. displayStrFormatInfo.mTotalSummaryLength = formatInfo.mTotalSummaryLength + (int)retVal.length();
  6352. displayStrFormatInfo.mExpandItemDepth++;
  6353. displayStrFormatInfo.mHidePointers = false;
  6354. retVal += DbgTypedValueToString(tupleVal, tupleExpr, displayStrFormatInfo, NULL);
  6355. int idx = (int)retVal.IndexOf('\n');
  6356. if (idx != -1)
  6357. {
  6358. String typeName = innerType->ToString(DbgLanguage_Unknown, true);
  6359. typeName += " ";
  6360. retVal.Insert(idx + 1, typeName);
  6361. }
  6362. return retVal;
  6363. }
  6364. }
  6365. }
  6366. if (isBfObject)
  6367. {
  6368. classVDataPtr = ReadMemory<addr_target>(ptrVal);
  6369. mDebugTarget->GetCompilerSettings();
  6370. if (mDebugTarget->mBfObjectHasFlags)
  6371. {
  6372. bfObjectFlags = ((int)classVDataPtr) & 0xFF;
  6373. //TODO: Only do this in debug?
  6374. if (bfObjectFlags & BfObjectFlag_Deleted)
  6375. isDeletedBfObject = true;
  6376. if (bfObjectFlags & BfObjectFlag_AppendAlloc)
  6377. isAppendBfObject = true;
  6378. if (bfObjectFlags & BfObjectFlag_StackAlloc)
  6379. isStackBfObject = true;
  6380. classVDataPtr &= ~0xFF;
  6381. }
  6382. }
  6383. if (!formatInfo.mIgnoreDerivedClassInfo)
  6384. {
  6385. if (isBfObject)
  6386. {
  6387. dbgModule->ParseSymbolData();
  6388. String symbolName;
  6389. addr_target symOffset;
  6390. if ((mDebugTarget->FindSymbolAt(classVDataPtr, &symbolName, &symOffset)) && (symOffset < 0x100))
  6391. {
  6392. String mangledClassName;
  6393. const char* symEnd = "sBfClassVData";
  6394. int symEndLen = strlen(symEnd);
  6395. if (((int)symbolName.length() > symEndLen) && (strstr(symbolName.c_str(), symEnd) != NULL))
  6396. mangledClassName = symbolName;
  6397. // If we have flags then we may be pointing past the _typeData, actually. We could fix this by masking out
  6398. // the flags area, but we need to be sure we are running a build that supports flags
  6399. symEnd = "sBfTypeData";
  6400. symEndLen = strlen(symEnd);
  6401. if (((int) symbolName.length() > symEndLen) && (strstr(symbolName.c_str(), symEnd) != NULL))
  6402. mangledClassName = symbolName;
  6403. if (mangledClassName.length() > 0)
  6404. {
  6405. String className = BfDemangler::Demangle(mangledClassName, innerType->GetLanguage(), BfDemangler::Flag_RawDemangle);
  6406. for (int i = 0; i < className.length() - 3; i++)
  6407. {
  6408. if ((className[i] == 'b') &&
  6409. (className[i + 1] == 'f') &&
  6410. (className[i + 2] == '.'))
  6411. {
  6412. bool matches;
  6413. if (i == 0)
  6414. matches = true;
  6415. else
  6416. {
  6417. char prevC = className[i - 1];
  6418. if ((prevC == ' ') ||
  6419. (prevC == ',') ||
  6420. (prevC == '<'))
  6421. {
  6422. matches = true;
  6423. }
  6424. }
  6425. if (matches)
  6426. className.Remove(i, 3);
  6427. }
  6428. }
  6429. // if (className.StartsWith("bf."))
  6430. // className.Remove(0, 3);
  6431. // else if (className.StartsWith("Box<bf."))
  6432. // className.Remove(4, 3);
  6433. int lastDot = (int)className.LastIndexOf('.');
  6434. if (lastDot > 0)
  6435. className = className.Substring(0, lastDot);
  6436. const char* arrPrefix = "System.Array1<";
  6437. if (strncmp(className.c_str(), arrPrefix, strlen(arrPrefix)) == 0)
  6438. {
  6439. className = className.Substring(strlen(arrPrefix), className.length() - strlen(arrPrefix) - 1);
  6440. className += "[]";
  6441. }
  6442. auto typeEntry = dbgModule->GetLinkedModule()->mTypeMap.Find(className.c_str(), DbgLanguage_BeefUnfixed);
  6443. if (typeEntry != NULL)
  6444. {
  6445. actualType = typeEntry->mValue;
  6446. if (!actualType->IsBfObject())
  6447. {
  6448. if (actualType->mTypeCode == DbgType_Ptr)
  6449. {
  6450. actualType = actualType->mTypeParam;
  6451. }
  6452. }
  6453. }
  6454. }
  6455. }
  6456. }
  6457. else if (hasCPPVTable)
  6458. {
  6459. dbgModule->ParseSymbolData();
  6460. addr_target classVDataPtr = ReadMemory<addr_target>(ptrVal);
  6461. String symbolName;
  6462. addr_target offset = 0;
  6463. if (mDebugTarget->FindSymbolAt(classVDataPtr, &symbolName, &offset, NULL))
  6464. {
  6465. // On GNU, vtable indices can "go negative" for things like RTTI and virtual inheritance, so
  6466. // we can't rely on an exact vtable address lookup
  6467. if (offset < 0x200)
  6468. {
  6469. DbgLanguage lang = innerType->GetLanguage();
  6470. const char* symStart = (innerType->mCompileUnit->mDbgModule->mDbgFlavor == DbgFlavor_GNU) ? "_ZTV" : "??_7";
  6471. if (strncmp(symbolName.c_str(), symStart, strlen(symStart)) == 0)
  6472. {
  6473. //String mangledClassName = symbolName.Substring(1);
  6474. String className = BfDemangler::Demangle(symbolName, lang);
  6475. int vtableNameIdx = (int)className.IndexOf("::`vftable'");
  6476. if (vtableNameIdx != -1)
  6477. className = className.Substring(0, vtableNameIdx);
  6478. auto typeEntry = dbgModule->mTypeMap.Find(className.c_str(), DbgLanguage_C);
  6479. if (typeEntry != NULL)
  6480. {
  6481. actualType = typeEntry->mValue;
  6482. if ((int)className.IndexOf('<') != -1)
  6483. useActualRawType = true;
  6484. int thisOffset = 0;
  6485. if (!DbgExprEvaluator::TypeIsSubTypeOf(actualType, innerType, &thisOffset))
  6486. {
  6487. // This catches virtual inheritance cases where we can't downcast
  6488. actualType = NULL;
  6489. }
  6490. }
  6491. }
  6492. }
  6493. }
  6494. }
  6495. }
  6496. DbgType* displayType = origValueType;
  6497. String displayString;
  6498. bool wantsCustomExpandedItems = false;
  6499. DebugVisualizerEntry* debugVis = NULL;
  6500. Array<String> dbgVisWildcardCaptures;
  6501. DbgType* dwUseType = (actualType != NULL) ? actualType : innerType;
  6502. //auto ptrDataType = dwValueType;
  6503. //TODO: Changed this from the above to account for COFF types where 'this' is always a fwd reference, does this cause any issues?
  6504. auto ptrDataType = innerType;
  6505. String ptrDataStr;
  6506. if (/*(!innerType->IsBfObject()) &&*/ (!ptrDataType->IsPointer()))
  6507. {
  6508. if ((dataPtr != 0) || (ptrDataType->GetByteCount() > sizeof(addr_target)))
  6509. {
  6510. bool wantsRefThis = ptrDataType->WantsRefThis();
  6511. ptrDataType = ptrDataType->GetDbgModule()->GetPointerType(ptrDataType);
  6512. if (wantsRefThis)
  6513. ptrDataStr += "*";
  6514. }
  6515. else
  6516. {
  6517. // Data is inline - must be int-sized or less
  6518. isCompositeWithoutAddress = true;
  6519. dataPtr = typedValue.mPtr;
  6520. }
  6521. }
  6522. String ptrDataTypeStr = ptrDataType->ToStringRaw();
  6523. ptrDataStr += StrFormat("(%s)", ptrDataTypeStr.c_str()) + EncodeDataPtr(dataPtr, true);
  6524. DbgType* dwUsePtrType = dwUseType;
  6525. String ptrUseDataStr;
  6526. if (!dwUsePtrType->IsPointer())
  6527. {
  6528. bool wantsRefThis = dwUsePtrType->WantsRefThis();
  6529. dwUsePtrType = dwUsePtrType->GetDbgModule()->GetPointerType(dwUsePtrType);
  6530. if (wantsRefThis)
  6531. ptrUseDataStr += "*";
  6532. }
  6533. String ptrUseDataTypeStr = dwUsePtrType->ToStringRaw();
  6534. ptrUseDataStr += StrFormat("(%s)", ptrUseDataTypeStr.c_str()) + EncodeDataPtr(dataPtr, true);
  6535. if ((origTypedValue.mSrcAddress == -1) && (origTypedValue.mVariable != NULL))
  6536. {
  6537. ptrDataStr = origTypedValue.mVariable->mName;
  6538. if (!origTypedValue.mType->RemoveModifiers()->Equals(origTypedValue.mVariable->mType->RemoveModifiers()))
  6539. {
  6540. //ptrDataStr = StrFormat("(%s)%s", origTypedValue.mType->ToString().c_str(), origTypedValue.mVariable->mName);
  6541. ptrDataStr = expr;
  6542. }
  6543. ptrUseDataStr = ptrDataStr;
  6544. }
  6545. if ((ptrVal == 0) && (dwValueType->IsTypedPrimitive()))
  6546. {
  6547. DbgTypedValue rawVal;
  6548. rawVal.mInt64 = origTypedValue.mInt64;
  6549. rawVal.mType = dwValueType->GetRootBaseType();
  6550. ptrDataStr = "(" + dwUseType->ToStringRaw() + ")";
  6551. ptrDataStr += DbgTypedValueToString(rawVal, expr, formatInfo, optEvaluator, fullPrecision);
  6552. int editValIdx = ptrDataStr.IndexOf(":editVal");
  6553. if (editValIdx != -1)
  6554. ptrDataStr.Remove(0, editValIdx + 9);
  6555. int crPos = (int)ptrDataStr.IndexOf('\n');
  6556. if (crPos != -1)
  6557. ptrDataStr.RemoveToEnd(crPos);
  6558. ptrUseDataStr = ptrDataStr;
  6559. if ((origTypedValue.mRegNum != -1) && (!expr.IsEmpty()) && (!formatInfo.mExplicitThis))
  6560. {
  6561. // There's no address, use direct local identifier
  6562. ptrDataStr = expr;
  6563. ptrUseDataStr = expr;
  6564. }
  6565. }
  6566. else if ((ptrVal == 0) && (dwValueType->IsCompositeType()))
  6567. {
  6568. }
  6569. bool isNull = wasPtr && (dataPtr == 0);
  6570. bool isBadSrc = !wasPtr && (dataPtr == 0);
  6571. DbgTypedValue useTypedValue = typedValue;
  6572. if ((origHadRef) || ((typedValue.mType->HasPointer()) && (!dwUseType->HasPointer())))
  6573. {
  6574. useTypedValue.mSrcAddress = useTypedValue.mPtr;
  6575. useTypedValue.mPtr = 0;
  6576. if (dwUseType->IsTypedPrimitive())
  6577. {
  6578. int byteCount = dwUseType->GetByteCount();
  6579. if (byteCount <= sizeof(intptr))
  6580. {
  6581. ReadMemory(useTypedValue.mSrcAddress, byteCount, &useTypedValue.mPtr);
  6582. }
  6583. }
  6584. }
  6585. useTypedValue.mType = dwUseType;
  6586. if ((!formatInfo.mNoVisualizers) && (!isNull) && (!isBadSrc))
  6587. {
  6588. if (language == DbgLanguage_Beef)
  6589. dwUseType->FixName();
  6590. debugVis = FindVisualizerForType(dwUseType, &dbgVisWildcardCaptures);
  6591. // for (auto& wildcardCapture : dbgVisWildcardCaptures)
  6592. // {
  6593. // if (wildcardCapture.StartsWith("`"))
  6594. // {
  6595. // dwUseType->PopulateType();
  6596. // auto entry = dbgModule->mTypeMap.Find(wildcardCapture.c_str(), language);
  6597. // if (entry != NULL)
  6598. // {
  6599. // //wildcardCapture = entry->mValue->ToStringRaw(language);
  6600. // }
  6601. // }
  6602. // }
  6603. }
  6604. bool hadCustomDisplayString = false;
  6605. if (debugVis != NULL)
  6606. {
  6607. auto& displayStringList = formatInfo.mRawString ? debugVis->mStringViews : debugVis->mDisplayStrings;
  6608. for (auto displayEntry : displayStringList)
  6609. {
  6610. if (!displayEntry->mCondition.empty())
  6611. {
  6612. if (!EvalCondition(debugVis, dbgCompileUnit, useTypedValue, formatInfo, displayEntry->mCondition, dbgVisWildcardCaptures, displayString))
  6613. continue;
  6614. }
  6615. hadCustomDisplayString = true;
  6616. String displayStr = mDebugManager->mDebugVisualizers->DoStringReplace(displayEntry->mString, dbgVisWildcardCaptures);
  6617. if (displayString.length() > 0)
  6618. displayString += " ";
  6619. ProcessEvalString(dbgCompileUnit, useTypedValue, displayStr, displayString, formatInfo, debugVis, true);
  6620. if (formatInfo.mRawString)
  6621. return displayString;
  6622. break;
  6623. }
  6624. if ((!debugVis->mExpandItems.empty()) || (debugVis->mCollectionType != DebugVisualizerEntry::CollectionType_None))
  6625. {
  6626. wantsCustomExpandedItems = true;
  6627. }
  6628. }
  6629. if (formatInfo.mRawString)
  6630. return "";
  6631. bool isTuple = (dwUseType->mName != NULL) && (dwUseType->mName[0] == '(') && (language == DbgLanguage_Beef);
  6632. if (isBadSrc)
  6633. {
  6634. displayString += "<null parent>";
  6635. }
  6636. else if ((!isNull) && (!formatInfo.mNoVisualizers) && (!hadCustomDisplayString))
  6637. {
  6638. // Create our own custom display
  6639. String firstRet;
  6640. String bigRet = isTuple ? "(" : "{ ";
  6641. int memberIdx = 0;
  6642. DbgType* summaryType = dwUseType;
  6643. bool summaryDone = false;
  6644. bool truncatedMemberList = false;
  6645. DbgTypedValue summaryTypedValue = useTypedValue;
  6646. String summaryDataStr = ptrDataStr;
  6647. String splatStr;
  6648. if (dataPtr == -1)
  6649. splatStr = expr;
  6650. while (summaryType != NULL)
  6651. {
  6652. summaryType->PopulateType();
  6653. if (summaryType->IsPrimitiveType())
  6654. {
  6655. if (formatInfo.mTotalSummaryLength + (int)displayString.length() > 255)
  6656. {
  6657. truncatedMemberList = true;
  6658. summaryDone = true;
  6659. bigRet += "...";
  6660. }
  6661. else
  6662. {
  6663. DwFormatInfo displayStrFormatInfo = formatInfo;
  6664. displayStrFormatInfo.mExpandItemDepth = 1;
  6665. displayStrFormatInfo.mTotalSummaryLength += (int)displayString.length();
  6666. displayStrFormatInfo.mHidePointers = false;
  6667. auto primType = dwUseType->GetDbgModule()->GetPrimitiveType(summaryType->mTypeCode, dwUseType->GetLanguage());
  6668. String result;
  6669. if ((dataPtr != 0) && (dataPtr != -1))
  6670. {
  6671. String evalString = "(" + primType->ToString() + ")" + ptrDataStr;
  6672. DbgTypedValue evalResult = EvaluateInContext(dbgCompileUnit, origTypedValue, evalString, &displayStrFormatInfo);
  6673. if (evalResult)
  6674. result = DbgTypedValueToString(evalResult, evalString, displayStrFormatInfo, NULL);
  6675. }
  6676. else
  6677. {
  6678. DbgTypedValue evalResult = origTypedValue;
  6679. evalResult.mType = primType;
  6680. String evalString = "(" + primType->ToString() + ")" + expr;
  6681. result = DbgTypedValueToString(evalResult, evalString, displayStrFormatInfo, NULL);
  6682. }
  6683. if (formatInfo.mRawString)
  6684. return result;
  6685. int crPos = result.IndexOf('\n');
  6686. if (crPos != -1)
  6687. result.RemoveToEnd(crPos);
  6688. if (memberIdx == 0)
  6689. firstRet = result;
  6690. bigRet += result;
  6691. memberIdx++;
  6692. }
  6693. }
  6694. for (auto member : summaryType->mMemberList)
  6695. {
  6696. if (!member->mIsStatic)
  6697. {
  6698. if (formatInfo.mTotalSummaryLength + retVal.length() + bigRet.length() > 255)
  6699. {
  6700. truncatedMemberList = true;
  6701. summaryDone = true;
  6702. bigRet += "...";
  6703. break;
  6704. }
  6705. if (member->mName != NULL)
  6706. {
  6707. if (!isdigit(*member->mName))
  6708. {
  6709. if (memberIdx != 0)
  6710. bigRet += isTuple ? ", " : " ";
  6711. if ((!isTuple) || (member->mName[0] != '_'))
  6712. {
  6713. bigRet += String(member->mName);
  6714. bigRet += isTuple ? ":" : "=";
  6715. }
  6716. }
  6717. else
  6718. {
  6719. if (memberIdx != 0)
  6720. bigRet += ", ";
  6721. }
  6722. DwFormatInfo displayStrFormatInfo = formatInfo;
  6723. displayStrFormatInfo.mExpandItemDepth = 1;
  6724. displayStrFormatInfo.mHidePointers = false;
  6725. displayStrFormatInfo.mTotalSummaryLength = formatInfo.mTotalSummaryLength + retVal.length() + bigRet.length();
  6726. String evalString;
  6727. if (dataPtr != -1)
  6728. {
  6729. if ((member->mName[0] >= '0') && (member->mName[0] <= '9'))
  6730. evalString += "this.";
  6731. evalString += String(member->mName); // +", this=" + summaryDataStr;
  6732. }
  6733. else
  6734. {
  6735. evalString = "(";
  6736. evalString += splatStr;
  6737. evalString += ").";
  6738. evalString += member->mName;
  6739. }
  6740. String referenceId;
  6741. String result;
  6742. if (!member->mType->IsValuelessType())
  6743. {
  6744. DbgTypedValue evalResult = EvaluateInContext(dbgCompileUnit, summaryTypedValue, evalString, &displayStrFormatInfo, &referenceId);
  6745. if (evalResult)
  6746. {
  6747. displayStrFormatInfo.mReferenceId = referenceId;
  6748. result = DbgTypedValueToString(evalResult, evalString, displayStrFormatInfo, NULL);
  6749. int crPos = result.IndexOf('\n');
  6750. if (crPos != -1)
  6751. result.RemoveToEnd(crPos);
  6752. }
  6753. else
  6754. result = "???";
  6755. }
  6756. if (formatInfo.mRawString)
  6757. return result;
  6758. if (memberIdx == 0)
  6759. firstRet = result;
  6760. bigRet += result;
  6761. //formatInfo.mEmbeddedDisplayCount = displayStrFormatInfo.mEmbeddedDisplayCount;
  6762. memberIdx++;
  6763. }
  6764. else
  6765. {
  6766. //TODO: Handle C++ unions?
  6767. }
  6768. }
  6769. }
  6770. if (truncatedMemberList)
  6771. break;
  6772. // Find first base class with members
  6773. DbgType* nextSummaryType = NULL;
  6774. for (auto checkBase : summaryType->mBaseTypes)
  6775. {
  6776. auto checkBaseType = checkBase->mBaseType;
  6777. checkBaseType = checkBaseType->GetPrimaryType();
  6778. checkBaseType->PopulateType();
  6779. if ((checkBaseType->GetByteCount() > 0) || (checkBaseType->IsPrimitiveType()))
  6780. {
  6781. if (!splatStr.empty())
  6782. {
  6783. splatStr = "(" + checkBaseType->ToString() + ")" + splatStr;
  6784. }
  6785. else
  6786. {
  6787. summaryTypedValue.mType = checkBaseType;
  6788. }
  6789. nextSummaryType = checkBaseType;
  6790. break;
  6791. }
  6792. }
  6793. summaryType = nextSummaryType;
  6794. if (summaryType == NULL)
  6795. break;
  6796. // Don't add the Object members
  6797. if ((summaryType->GetBaseType() == NULL) && (summaryType->IsBfObject()))
  6798. break;
  6799. // If we don't have many members then find a base class with some members to show
  6800. if ((memberIdx != 0) && (displayString.length() >= 255))
  6801. {
  6802. truncatedMemberList = true;
  6803. bigRet += "...";
  6804. break;
  6805. }
  6806. }
  6807. bigRet += isTuple ? ")" : " }";
  6808. if (displayString.length() > 0)
  6809. displayString += " ";
  6810. if ((memberIdx == 1) && (!truncatedMemberList) && (firstRet.IndexOf('{') == -1) && (!isTuple))
  6811. displayString += "{ " + firstRet + " }";
  6812. else
  6813. displayString += bigRet;
  6814. }
  6815. DbgType* memberListType = actualType;
  6816. bool memberListForceCast = false;
  6817. if (actualType != NULL)
  6818. {
  6819. String valTypeName = displayType->ToString();
  6820. String actualTypeName = actualType->ToString(DbgLanguage_Unknown, true);
  6821. String actualUseTypeName = actualTypeName;
  6822. if ((int)actualTypeName.IndexOf('^') != -1)
  6823. useActualRawType = true;
  6824. if (useActualRawType)
  6825. actualUseTypeName = actualType->ToStringRaw();
  6826. if (displayString.empty())
  6827. {
  6828. // Nothing to display
  6829. }
  6830. else
  6831. {
  6832. if (!retVal.empty())
  6833. retVal += " ";
  6834. retVal += displayString;
  6835. }
  6836. retVal += "\n" + valTypeName;
  6837. if ((innerType->IsBaseBfObject()) || (innerType->IsInterface()))
  6838. {
  6839. if (actualType != innerType)
  6840. {
  6841. retVal += " {" + actualTypeName + "}";
  6842. memberListForceCast = true;
  6843. }
  6844. }
  6845. else
  6846. {
  6847. if (actualType != innerType)
  6848. {
  6849. retVal += " {" + actualTypeName + "}";
  6850. retVal += "\n";
  6851. if (!wantsCustomExpandedItems)
  6852. {
  6853. retVal += "[" + actualTypeName + "]\t((" + actualUseTypeName;
  6854. if (!actualType->IsBfObject())
  6855. retVal += "*";
  6856. retVal += ")this), nd, na, nv, this=" + ptrDataStr;
  6857. memberListType = innerType;
  6858. }
  6859. }
  6860. }
  6861. }
  6862. else
  6863. {
  6864. if ((formatInfo.mHidePointers) && (formatInfo.mIgnoreDerivedClassInfo))
  6865. {
  6866. displayType = innerType;
  6867. if (displayString.empty())
  6868. retVal += displayType->ToString(DbgLanguage_Unknown, true);
  6869. }
  6870. if (!displayString.empty())
  6871. {
  6872. if (!retVal.empty())
  6873. retVal += " ";
  6874. retVal += displayString;
  6875. }
  6876. else
  6877. {
  6878. if (formatInfo.mRawString)
  6879. return "";
  6880. }
  6881. retVal += "\n" + displayType->ToString(DbgLanguage_Unknown, true);
  6882. memberListType = innerType;
  6883. }
  6884. if ((isBfObject) && (mDebugTarget->mBfObjectHasFlags) && (!formatInfo.mNoVisualizers) && (!formatInfo.mRawString))
  6885. {
  6886. int stackTraceLen = 1;
  6887. addr_target stackTraceAddr = ptrVal + sizeof(addr_target);
  6888. if ((bfObjectFlags & BfObjectFlag_AllocInfo) != 0)
  6889. {
  6890. addr_target objectSize = ReadMemory<addr_target>(ptrVal + sizeof(addr_target));
  6891. addr_target largeAllocInfo = ReadMemory<addr_target>(ptrVal + objectSize);
  6892. stackTraceLen = largeAllocInfo & 0xFFFF;
  6893. stackTraceAddr = ptrVal + objectSize + sizeof(addr_target);
  6894. }
  6895. else if ((bfObjectFlags & BfObjectFlag_AllocInfo_Short) != 0)
  6896. {
  6897. addr_target dbgAllocInfo = ReadMemory<addr_target>(ptrVal + sizeof(addr_target));
  6898. stackTraceLen = dbgAllocInfo & 0xFF;
  6899. stackTraceAddr = ptrVal + (dbgAllocInfo >> 16);
  6900. }
  6901. if (stackTraceLen == 1)
  6902. {
  6903. retVal += StrFormat("\n[AllocStackTrace]\t*(System.CallStackAddr*)%s, nm", EncodeDataPtr(stackTraceAddr, true).c_str());
  6904. }
  6905. else if (stackTraceLen > 0)
  6906. {
  6907. retVal += StrFormat("\n[AllocStackTrace]\t(System.CallStackAddr*)%s, %d, na", EncodeDataPtr(stackTraceAddr, true).c_str(), stackTraceLen);
  6908. }
  6909. }
  6910. retVal += StrFormat("\n:language\t%d", language);
  6911. if (formatInfo.mNoMembers)
  6912. {
  6913. //
  6914. }
  6915. else if (wantsCustomExpandedItems)
  6916. {
  6917. HandleCustomExpandedItems(retVal, dbgCompileUnit, debugVis, dwUseType, dwValueType, ptrUseDataStr, ptrDataStr, useTypedValue, dbgVisWildcardCaptures, formatInfo);
  6918. }
  6919. else if ((!isNull) && (!isBadSrc))
  6920. {
  6921. if (dataPtr == -1)
  6922. {
  6923. //String splatName = ((origTypedValue.mSrcAddress == -1) && (origTypedValue.mVariable != NULL)) ? origTypedValue.mVariable->mName : expr;
  6924. String splatName = expr;
  6925. retVal += "\n" + GetMemberList(memberListType, splatName, wasPtr, false, false, true, origTypedValue.mIsReadOnly);
  6926. }
  6927. else
  6928. {
  6929. retVal += "\n" + GetMemberList(memberListType, ptrDataStr, wasPtr, false, memberListForceCast, isCompositeWithoutAddress, origTypedValue.mIsReadOnly);
  6930. }
  6931. }
  6932. if (formatInfo.mExpandItemDepth > 0)
  6933. return retVal;
  6934. if (isAppendBfObject)
  6935. retVal += "\n:appendAlloc";
  6936. if (isStackBfObject)
  6937. retVal += "\n:stack";
  6938. if (isDeletedBfObject)
  6939. retVal += "\n:deleted";
  6940. if ((debugVis != NULL) && (!debugVis->mAction.empty()))
  6941. {
  6942. String rawActionStr = mDebugManager->mDebugVisualizers->DoStringReplace(debugVis->mAction, dbgVisWildcardCaptures);
  6943. String actionStr;
  6944. ProcessEvalString(dbgCompileUnit, useTypedValue, rawActionStr, actionStr, formatInfo, debugVis, true);
  6945. retVal += "\n:action\t" + actionStr;
  6946. }
  6947. if ((!typedValue.mIsLiteral) && (dwValueType->IsPointer()))
  6948. {
  6949. retVal += "\n:editVal\t" + EncodeDataPtr(ptrVal, true);
  6950. }
  6951. return retVal;
  6952. }
  6953. return "Unknown Type\n" + origValueType->ToString();
  6954. }
  6955. void WinDebugger::HandleCustomExpandedItems(String& retVal, DbgCompileUnit* dbgCompileUnit, DebugVisualizerEntry* debugVis, DbgType* dwUseType, DbgType* dwValueType, String& ptrUseDataStr, String& ptrDataStr, DbgTypedValue useTypedValue, Array<String>& dbgVisWildcardCaptures, DwFormatInfo& formatInfo)
  6956. {
  6957. auto debugVisualizers = mDebugManager->mDebugVisualizers;
  6958. auto dbgModule = dbgCompileUnit->mDbgModule;
  6959. if (formatInfo.mExpandItemDepth > 10) // Avoid crashing on circular ExpandItems
  6960. return;
  6961. auto language = formatInfo.mLanguage;
  6962. bool isReadOnly = false;
  6963. if (useTypedValue.mIsReadOnly)
  6964. isReadOnly = true;
  6965. for (auto entry : debugVis->mExpandItems)
  6966. {
  6967. if (!entry->mCondition.empty())
  6968. {
  6969. String error;
  6970. if (!EvalCondition(debugVis, dbgCompileUnit, useTypedValue, formatInfo, entry->mCondition, dbgVisWildcardCaptures, error))
  6971. {
  6972. if (!error.empty())
  6973. retVal += "\n" + entry->mName + "\t@!<DbgVis Failed>@!";
  6974. continue;
  6975. }
  6976. }
  6977. String replacedStr = debugVisualizers->DoStringReplace(entry->mValue, dbgVisWildcardCaptures);
  6978. retVal += "\n" + entry->mName + "\t" + replacedStr + ", this=(" + ptrUseDataStr + ")";
  6979. }
  6980. String referenceId = dwUseType->ToString();
  6981. if (debugVis->mCollectionType == DebugVisualizerEntry::CollectionType_ExpandedItem)
  6982. {
  6983. DbgTypedValue itemValue = EvaluateInContext(dbgCompileUnit, useTypedValue, debugVisualizers->DoStringReplace(debugVis->mValuePointer, dbgVisWildcardCaptures), &formatInfo);
  6984. if (itemValue)
  6985. {
  6986. DwFormatInfo itemFormatInfo = formatInfo;
  6987. itemFormatInfo.mExpandItemDepth++;
  6988. String itemRetVal = DbgTypedValueToString(itemValue, "", itemFormatInfo, NULL);
  6989. int crIdx = (int)itemRetVal.IndexOf('\n');
  6990. if (crIdx != -1)
  6991. {
  6992. crIdx = (int)itemRetVal.IndexOf('\n', crIdx + 1);
  6993. if (crIdx != -1)
  6994. retVal += itemRetVal.Substring(crIdx);
  6995. }
  6996. }
  6997. }
  6998. else if (debugVis->mCollectionType == DebugVisualizerEntry::CollectionType_Array)
  6999. {
  7000. DbgTypedValue sizeValue = EvaluateInContext(dbgCompileUnit, useTypedValue, debugVisualizers->DoStringReplace(debugVis->mSize, dbgVisWildcardCaptures), &formatInfo);
  7001. Array<int> lowerDimSizes;
  7002. for (auto lowerDim : debugVis->mLowerDimSizes)
  7003. {
  7004. DbgTypedValue lowerDimValue = EvaluateInContext(dbgCompileUnit, useTypedValue, debugVisualizers->DoStringReplace(lowerDim, dbgVisWildcardCaptures), &formatInfo);
  7005. int dimSize = 0;
  7006. if ((lowerDimValue) && (lowerDimValue.mType->IsInteger()))
  7007. dimSize = (int)lowerDimValue.GetInt64();
  7008. dimSize = BF_MAX(dimSize, 1);
  7009. lowerDimSizes.push_back(dimSize);
  7010. }
  7011. if ((sizeValue) && (sizeValue.mType->IsInteger()) && (sizeValue.GetInt64() > 0))
  7012. {
  7013. if (!debugVis->mCondition.IsEmpty())
  7014. {
  7015. int size = (int)sizeValue.GetInt64();
  7016. DbgTypedValue headPointer = EvaluateInContext(dbgCompileUnit, useTypedValue, debugVisualizers->DoStringReplace(debugVis->mValuePointer, dbgVisWildcardCaptures), &formatInfo);
  7017. DbgTypedValue curNode = headPointer;
  7018. Array<addr_target> parentList;
  7019. String continuationData;
  7020. int totalSize = 2;
  7021. auto valueType = headPointer.mType;
  7022. String addrs = GetArrayItems(dbgCompileUnit, debugVis, valueType, headPointer, totalSize, &continuationData);
  7023. String firstAddr;
  7024. String secondAddr;
  7025. bool hasSecondAddr = valueType == NULL;
  7026. if (addrs.length() > 0)
  7027. {
  7028. const char* addrsPtr = addrs.c_str();
  7029. firstAddr = addrs.Substring(0, sizeof(addr_target) * 2);
  7030. if (hasSecondAddr)
  7031. secondAddr = addrs.Substring(sizeof(addr_target) * 2, sizeof(addr_target) * 2);
  7032. }
  7033. String evalStr;
  7034. if (valueType != NULL)
  7035. {
  7036. evalStr = "(" + valueType->ToStringRaw();
  7037. if (!valueType->IsPointer())
  7038. evalStr += "*";
  7039. evalStr += ")0x{1}";
  7040. }
  7041. else
  7042. {
  7043. evalStr += "({1})0x{2}";
  7044. }
  7045. if (!debugVis->mShowElementAddrs)
  7046. evalStr.Insert(0, "*");
  7047. if (addrs.length() > 0)
  7048. {
  7049. evalStr += ", refid=\"" + referenceId + ".[]\"";
  7050. if (isReadOnly)
  7051. evalStr += ", ne";
  7052. retVal += "\n:repeat" + StrFormat("\t%d\t%d\t%d", 0, BF_MAX(size, 0), 10000) +
  7053. "\t[{0}]\t" + evalStr + "\t" + firstAddr;
  7054. if (hasSecondAddr)
  7055. retVal += "\t" + secondAddr;
  7056. if (size != 0)
  7057. {
  7058. retVal += "\n:addrs\t" + addrs;
  7059. if (valueType == NULL)
  7060. retVal += "\n:addrsEntrySize\t2";
  7061. if (continuationData.length() > 0)
  7062. retVal += "\n:continuation\t" + continuationData;
  7063. }
  7064. }
  7065. }
  7066. else if (lowerDimSizes.size() == 1)
  7067. {
  7068. int dimSize1 = lowerDimSizes[0];
  7069. String evalStr = "(" + debugVisualizers->DoStringReplace(debugVis->mValuePointer, dbgVisWildcardCaptures) +
  7070. StrFormat(" + {0} * %d), arraysize=%d, na, this=", dimSize1, dimSize1) + ptrUseDataStr;
  7071. evalStr += ", refid=\"" + referenceId + ".[]\"";
  7072. if (isReadOnly)
  7073. evalStr += ", ne";
  7074. retVal += "\n:repeat" + StrFormat("\t%d\t%d\t%d", 0, (int)sizeValue.GetInt64() / dimSize1, 50000) +
  7075. "\t[{0}]\t" + evalStr;
  7076. }
  7077. else if (lowerDimSizes.size() == 2)
  7078. {
  7079. int dimSize1 = lowerDimSizes[0];
  7080. int dimSize2 = lowerDimSizes[1];
  7081. DbgTypedValue headPointer = EvaluateInContext(dbgCompileUnit, useTypedValue, debugVisualizers->DoStringReplace(debugVis->mValuePointer, dbgVisWildcardCaptures), &formatInfo);
  7082. if ((headPointer.mType != NULL) && (headPointer.mType->IsPointer()))
  7083. {
  7084. String evalStr = StrFormat("((%s[%d]*)", headPointer.mType->mTypeParam->ToStringRaw(language).c_str(), dimSize2) + debugVisualizers->DoStringReplace(debugVis->mValuePointer, dbgVisWildcardCaptures) +
  7085. StrFormat(" + {0} * %d), arraysize=%d, na, this=", dimSize1, dimSize1) + ptrUseDataStr;
  7086. evalStr += ", refid=\"" + referenceId + ".[]\"";
  7087. if (isReadOnly)
  7088. evalStr += ", ne";
  7089. retVal += "\n:repeat" + StrFormat("\t%d\t%d\t%d", 0, (int)sizeValue.GetInt64() / dimSize1 / dimSize2, 50000) +
  7090. "\t[{0}]\t" + evalStr;
  7091. }
  7092. }
  7093. else if (lowerDimSizes.size() == 3)
  7094. {
  7095. int dimSize1 = lowerDimSizes[0];
  7096. int dimSize2 = lowerDimSizes[1];
  7097. int dimSize3 = lowerDimSizes[2];
  7098. DbgTypedValue headPointer = EvaluateInContext(dbgCompileUnit, useTypedValue, debugVisualizers->DoStringReplace(debugVis->mValuePointer, dbgVisWildcardCaptures), &formatInfo);
  7099. if ((headPointer.mType != NULL) && (headPointer.mType->IsPointer()))
  7100. {
  7101. String evalStr = StrFormat("((%s[%d][%d]*)", headPointer.mType->mTypeParam->ToStringRaw(language).c_str(), dimSize2, dimSize3) + debugVisualizers->DoStringReplace(debugVis->mValuePointer, dbgVisWildcardCaptures) +
  7102. StrFormat(" + {0} * %d), arraysize=%d, na, this=", dimSize1, dimSize1) + ptrUseDataStr;
  7103. evalStr += ", refid=\"" + referenceId + ".[]\"";
  7104. if (isReadOnly)
  7105. evalStr += ", ne";
  7106. retVal += "\n:repeat" + StrFormat("\t%d\t%d\t%d", 0, (int)sizeValue.GetInt64() / dimSize1 / dimSize2 / dimSize3, 50000) +
  7107. "\t[{0}]\t" + evalStr;
  7108. }
  7109. }
  7110. else
  7111. {
  7112. String evalStr = "*(" + debugVisualizers->DoStringReplace(debugVis->mValuePointer, dbgVisWildcardCaptures) + " + {0}), this=" + ptrUseDataStr;
  7113. evalStr += ", refid=\"" + referenceId + ".[]\"";
  7114. if (isReadOnly)
  7115. evalStr += ", ne";
  7116. retVal += "\n:repeat" + StrFormat("\t%d\t%d\t%d", 0, (int)sizeValue.GetInt64(), 50000) +
  7117. "\t[{0}]\t" + evalStr;
  7118. }
  7119. }
  7120. }
  7121. else if (debugVis->mCollectionType == DebugVisualizerEntry::CollectionType_IndexItems)
  7122. {
  7123. DbgTypedValue sizeValue = EvaluateInContext(dbgCompileUnit, useTypedValue, debugVisualizers->DoStringReplace(debugVis->mSize, dbgVisWildcardCaptures), &formatInfo);
  7124. if ((sizeValue) && (sizeValue.mType->IsInteger()) && (sizeValue.GetInt64() > 0))
  7125. {
  7126. String evalStr = debugVis->mValuePointer + ", this=" + ptrUseDataStr;
  7127. evalStr.Replace("$i", "{0}");
  7128. evalStr += ", refid=\"" + referenceId + ".[]\"";
  7129. if (isReadOnly)
  7130. evalStr += ", ne";
  7131. retVal += "\n:repeat" + StrFormat("\t%d\t%d\t%d", 0, (int)sizeValue.GetInt64(), 50000) +
  7132. "\t[{0}]\t" + evalStr;
  7133. }
  7134. }
  7135. else if (debugVis->mCollectionType == DebugVisualizerEntry::CollectionType_LinkedList)
  7136. {
  7137. DbgType* valueType = NULL;
  7138. if (!debugVis->mValueType.empty())
  7139. {
  7140. valueType = dbgModule->FindType(debugVisualizers->DoStringReplace(debugVis->mValueType, dbgVisWildcardCaptures), dwValueType);
  7141. if (valueType != NULL)
  7142. valueType = valueType->ResolveTypeDef();
  7143. }
  7144. DbgTypedValue headPointer = EvaluateInContext(dbgCompileUnit, useTypedValue, debugVisualizers->DoStringReplace(debugVis->mHeadPointer, dbgVisWildcardCaptures), &formatInfo);
  7145. if (headPointer)
  7146. {
  7147. DbgTypedValue endPointer;
  7148. if (!debugVis->mEndPointer.empty())
  7149. endPointer = EvaluateInContext(dbgCompileUnit, useTypedValue, debugVisualizers->DoStringReplace(debugVis->mEndPointer, dbgVisWildcardCaptures), &formatInfo);
  7150. DbgTypedValue nextPointer = EvaluateInContext(dbgCompileUnit, headPointer, debugVisualizers->DoStringReplace(debugVis->mNextPointer, dbgVisWildcardCaptures), &formatInfo);
  7151. int size = -1;
  7152. if (!debugVis->mSize.empty())
  7153. {
  7154. auto sizeValue = EvaluateInContext(dbgCompileUnit, useTypedValue, debugVisualizers->DoStringReplace(debugVis->mSize, dbgVisWildcardCaptures), &formatInfo);
  7155. if (sizeValue)
  7156. size = (int)sizeValue.GetInt64();
  7157. }
  7158. DbgTypedValue curNode = headPointer;
  7159. Array<addr_target> parentList;
  7160. String continuationData;
  7161. int totalSize = 2;
  7162. String addrs = GetLinkedListItems(dbgCompileUnit, debugVis, endPointer.mPtr, valueType, curNode, totalSize, &continuationData);
  7163. String firstAddr;
  7164. String secondAddr;
  7165. bool hasSecondAddr = valueType == NULL;
  7166. if (addrs.length() > 0)
  7167. {
  7168. const char* addrsPtr = addrs.c_str();
  7169. firstAddr = addrs.Substring(0, sizeof(addr_target)*2);
  7170. if (hasSecondAddr)
  7171. secondAddr = addrs.Substring(sizeof(addr_target)*2, sizeof(addr_target)*2);
  7172. }
  7173. String evalStr;
  7174. if (valueType != NULL)
  7175. {
  7176. evalStr = "(" + valueType->ToStringRaw();
  7177. if (!valueType->IsPointer())
  7178. evalStr += "*";
  7179. evalStr += ")0x{1}";
  7180. }
  7181. else
  7182. {
  7183. evalStr += "({1})0x{2}";
  7184. }
  7185. if (!debugVis->mShowElementAddrs)
  7186. evalStr.Insert(0, "*");
  7187. if (addrs.length() > 0)
  7188. {
  7189. evalStr += ", refid=\"" + referenceId + ".[]\"";
  7190. if (isReadOnly)
  7191. evalStr += ", ne";
  7192. retVal += "\n:repeat" + StrFormat("\t%d\t%d\t%d", 0, size, 10000) +
  7193. "\t[{0}]\t" + evalStr + "\t" + firstAddr;
  7194. if (hasSecondAddr)
  7195. retVal += "\t" + secondAddr;
  7196. if (size != 0)
  7197. {
  7198. retVal += "\n:addrs\t" + addrs;
  7199. if (valueType == NULL)
  7200. retVal += "\n:addrsEntrySize\t2";
  7201. if (continuationData.length() > 0)
  7202. retVal += "\n:continuation\t" + continuationData;
  7203. }
  7204. }
  7205. }
  7206. }
  7207. else if (debugVis->mCollectionType == DebugVisualizerEntry::CollectionType_TreeItems)
  7208. {
  7209. DbgType* valueType = NULL;
  7210. if (!debugVis->mValueType.empty())
  7211. {
  7212. valueType = dbgModule->FindType(debugVisualizers->DoStringReplace(debugVis->mValueType, dbgVisWildcardCaptures), dwValueType);
  7213. if (valueType != NULL)
  7214. valueType = valueType->ResolveTypeDef();
  7215. }
  7216. DbgTypedValue sizeValue = EvaluateInContext(dbgCompileUnit, useTypedValue, debugVisualizers->DoStringReplace(debugVis->mSize, dbgVisWildcardCaptures), &formatInfo);
  7217. DbgTypedValue headPointer = EvaluateInContext(dbgCompileUnit, useTypedValue, debugVisualizers->DoStringReplace(debugVis->mHeadPointer, dbgVisWildcardCaptures), &formatInfo);
  7218. if (sizeValue)
  7219. sizeValue.mType = sizeValue.mType->RemoveModifiers();
  7220. if ((sizeValue) && (headPointer) && (sizeValue.mType->IsInteger()) && (sizeValue.GetInt64() > 0))
  7221. {
  7222. DbgTypedValue curNode = headPointer;
  7223. Array<addr_target> parentList;
  7224. String continuationData;
  7225. int getItemCount = (int)BF_MIN(sizeValue.GetInt64(), 32LL);
  7226. String addrs = GetTreeItems(dbgCompileUnit, debugVis, parentList, valueType, curNode, getItemCount, &continuationData);
  7227. addr_target firstAddr = 0;
  7228. addr_target secondAddr = 0;
  7229. bool hasSecondAddr = valueType == NULL;
  7230. if (addrs.length() > 0)
  7231. {
  7232. const char* addrsPtr = addrs.c_str();
  7233. firstAddr = DecodeTargetDataPtr(addrsPtr);
  7234. if (hasSecondAddr)
  7235. secondAddr = DecodeTargetDataPtr(addrsPtr);
  7236. }
  7237. String evalStr;
  7238. if (valueType != NULL)
  7239. {
  7240. evalStr = "*(" + valueType->ToStringRaw();
  7241. if (!valueType->IsPointer())
  7242. evalStr += "*";
  7243. evalStr += ")0x{1}";
  7244. }
  7245. else
  7246. {
  7247. evalStr += "*(_T_{1}*)0x{2}";
  7248. }
  7249. int size = (int)sizeValue.GetInt64();
  7250. if (addrs.length() == 0)
  7251. {
  7252. evalStr = ""; // Failed
  7253. }
  7254. evalStr += ", refid=\"" + referenceId + ".[]\"";
  7255. if (isReadOnly)
  7256. evalStr += ", ne";
  7257. retVal += "\n:repeat" + StrFormat("\t%d\t%d\t%d", 0, size, 10000) +
  7258. "\t[{0}]\t" + evalStr + "\t" + EncodeDataPtr(firstAddr, false);
  7259. if (hasSecondAddr)
  7260. retVal += "\t" + EncodeDataPtr(secondAddr, false);
  7261. if (addrs.length() > 0)
  7262. {
  7263. retVal += "\n:addrs\t" + addrs;
  7264. if (continuationData.length() > 0)
  7265. retVal += "\n:continuation\t" + continuationData;
  7266. }
  7267. }
  7268. }
  7269. else if (debugVis->mCollectionType == DebugVisualizerEntry::CollectionType_Dictionary)
  7270. {
  7271. DbgTypedValue sizeValue = EvaluateInContext(dbgCompileUnit, useTypedValue, debugVisualizers->DoStringReplace(debugVis->mSize, dbgVisWildcardCaptures), &formatInfo);
  7272. DbgTypedValue entriesPtrValue = EvaluateInContext(dbgCompileUnit, useTypedValue, debugVisualizers->DoStringReplace(debugVis->mEntries, dbgVisWildcardCaptures), &formatInfo);
  7273. if (sizeValue)
  7274. sizeValue.mType = sizeValue.mType->RemoveModifiers();
  7275. if ((sizeValue) && (entriesPtrValue) && (sizeValue.mType->IsInteger()) && (sizeValue.GetInt64() > 0))
  7276. {
  7277. String continuationData;
  7278. DbgType* valueType = entriesPtrValue.mType;
  7279. int getItemCount = (int)std::min(sizeValue.GetInt64(), 2LL);
  7280. DbgType* useTypedValType = useTypedValue.mType;
  7281. addr_target useTypedValPtr = useTypedValue.mPtr;
  7282. addr_target useTypedValAddr = useTypedValue.mSrcAddress;
  7283. String addrs = GetDictionaryItems(dbgCompileUnit, debugVis, useTypedValue, 0, -1, getItemCount, &continuationData);
  7284. addr_target firstAddr = 0;
  7285. if (addrs.length() > 0)
  7286. {
  7287. const char* addrsPtr = addrs.c_str();
  7288. firstAddr = DecodeTargetDataPtr(addrsPtr);
  7289. }
  7290. String evalStr = "((" + valueType->ToStringRaw() + ")0x{1}), na";
  7291. evalStr += ", refid=\"" + referenceId + ".[]\"";
  7292. if (isReadOnly)
  7293. evalStr += ", ne";
  7294. retVal += "\n:repeat" + StrFormat("\t%d\t%d\t%d", 0, (int)sizeValue.GetInt64(), 10000) +
  7295. "\t[{0}]\t" + evalStr + "\t" + EncodeDataPtr(firstAddr, false);
  7296. if (addrs.length() > 0)
  7297. {
  7298. retVal += "\n:addrs\t" + addrs;
  7299. if (continuationData.length() > 0)
  7300. retVal += "\n:continuation\t" + continuationData;
  7301. }
  7302. }
  7303. }
  7304. if (formatInfo.mExpandItemDepth == 0)
  7305. {
  7306. //retVal += "\n[Raw View]\tthis, this=" + ptrDataStr + ", nv";
  7307. retVal += "\n[Raw View]\t" + ptrDataStr + ", nv";
  7308. }
  7309. }
  7310. bool WinDebugger::IsPaused()
  7311. {
  7312. return (mRunState == RunState_Paused) || (mRunState == RunState_Breakpoint) || (mRunState == RunState_Exception) || (mRunState == RunState_DebugEval_Done);
  7313. }
  7314. DbgTypedValue WinDebugger::GetRegister(const StringImpl& regName, DbgLanguage language, CPURegisters* registers, Array<RegForm>* regForms)
  7315. {
  7316. int regNum = -1;
  7317. String lwrRegName(regName);
  7318. _strlwr((char*)lwrRegName.c_str());
  7319. // int regs
  7320. #ifdef BF_DBG_32
  7321. DbgTypeCode regType = DbgType_i32;
  7322. if (lwrRegName == "eax")
  7323. regNum = X86Reg_EAX;
  7324. else if (lwrRegName == "ecx")
  7325. regNum = X86Reg_ECX;
  7326. else if (lwrRegName == "edx")
  7327. regNum = X86Reg_EDX;
  7328. else if (lwrRegName == "ebx")
  7329. regNum = X86Reg_EBX;
  7330. else if (lwrRegName == "esp")
  7331. regNum = X86Reg_ESP;
  7332. else if (lwrRegName == "ebp")
  7333. regNum = X86Reg_EBP;
  7334. else if (lwrRegName == "esi")
  7335. regNum = X86Reg_ESI;
  7336. else if (lwrRegName == "edi")
  7337. regNum = X86Reg_EDI;
  7338. else if (lwrRegName == "eip")
  7339. regNum = X86Reg_EIP;
  7340. else if (lwrRegName == "efl")
  7341. regNum = X86Reg_EFL;
  7342. #else
  7343. DbgTypeCode regType = DbgType_i64;
  7344. if (lwrRegName == "rax")
  7345. regNum = X64Reg_RAX;
  7346. else if (lwrRegName == "rcx")
  7347. regNum = X64Reg_RCX;
  7348. else if (lwrRegName == "rdx")
  7349. regNum = X64Reg_RDX;
  7350. else if (lwrRegName == "rbx")
  7351. regNum = X64Reg_RBX;
  7352. else if (lwrRegName == "rsp")
  7353. regNum = X64Reg_RSP;
  7354. else if (lwrRegName == "rbp")
  7355. regNum = X64Reg_RBP;
  7356. else if (lwrRegName == "rsi")
  7357. regNum = X64Reg_RSI;
  7358. else if (lwrRegName == "rdi")
  7359. regNum = X64Reg_RDI;
  7360. else if (lwrRegName == "rip")
  7361. regNum = X64Reg_RIP;
  7362. else if (lwrRegName == "r8")
  7363. regNum = X64Reg_R8;
  7364. else if (lwrRegName == "r9")
  7365. regNum = X64Reg_R9;
  7366. else if (lwrRegName == "r10")
  7367. regNum = X64Reg_R10;
  7368. else if (lwrRegName == "r11")
  7369. regNum = X64Reg_R11;
  7370. else if (lwrRegName == "r12")
  7371. regNum = X64Reg_R12;
  7372. else if (lwrRegName == "r13")
  7373. regNum = X64Reg_R13;
  7374. else if (lwrRegName == "r14")
  7375. regNum = X64Reg_R14;
  7376. else if (lwrRegName == "r15")
  7377. regNum = X64Reg_R15;
  7378. else
  7379. {
  7380. regType = DbgType_i32;
  7381. if (lwrRegName == "eax")
  7382. regNum = X64Reg_RAX;
  7383. else if (lwrRegName == "ecx")
  7384. regNum = X64Reg_RCX;
  7385. else if (lwrRegName == "edx")
  7386. regNum = X64Reg_RDX;
  7387. else if (lwrRegName == "ebx")
  7388. regNum = X64Reg_RBX;
  7389. else if (lwrRegName == "efl")
  7390. regNum = X64Reg_EFL;
  7391. else if (lwrRegName == "esi")
  7392. regNum = X64Reg_RSI;
  7393. else if (lwrRegName == "edi")
  7394. regNum = X64Reg_RDI;
  7395. else if (lwrRegName == "r8d")
  7396. regNum = X64Reg_R8;
  7397. else if (lwrRegName == "r9d")
  7398. regNum = X64Reg_R9;
  7399. else if (lwrRegName == "r10d")
  7400. regNum = X64Reg_R10;
  7401. else if (lwrRegName == "r11d")
  7402. regNum = X64Reg_R11;
  7403. else if (lwrRegName == "r12d")
  7404. regNum = X64Reg_R12;
  7405. else if (lwrRegName == "r13d")
  7406. regNum = X64Reg_R13;
  7407. else if (lwrRegName == "r14d")
  7408. regNum = X64Reg_R14;
  7409. else if (lwrRegName == "r15d")
  7410. regNum = X64Reg_R15;
  7411. else
  7412. {
  7413. regType = DbgType_i16;
  7414. if (lwrRegName == "ax")
  7415. regNum = X64Reg_RAX;
  7416. else if (lwrRegName == "cx")
  7417. regNum = X64Reg_RCX;
  7418. else if (lwrRegName == "dx")
  7419. regNum = X64Reg_RDX;
  7420. else if (lwrRegName == "bx")
  7421. regNum = X64Reg_RBX;
  7422. else if (lwrRegName == "si")
  7423. regNum = X64Reg_RSI;
  7424. else if (lwrRegName == "di")
  7425. regNum = X64Reg_RDI;
  7426. else if (lwrRegName == "r8w")
  7427. regNum = X64Reg_R8;
  7428. else if (lwrRegName == "r9w")
  7429. regNum = X64Reg_R9;
  7430. else if (lwrRegName == "r10w")
  7431. regNum = X64Reg_R10;
  7432. else if (lwrRegName == "r11w")
  7433. regNum = X64Reg_R11;
  7434. else if (lwrRegName == "r12w")
  7435. regNum = X64Reg_R12;
  7436. else if (lwrRegName == "r13w")
  7437. regNum = X64Reg_R13;
  7438. else if (lwrRegName == "r14w")
  7439. regNum = X64Reg_R14;
  7440. else if (lwrRegName == "r15w")
  7441. regNum = X64Reg_R15;
  7442. else
  7443. {
  7444. regType = DbgType_i8;
  7445. if (lwrRegName == "al")
  7446. regNum = X64Reg_RAX;
  7447. else if (lwrRegName == "cl")
  7448. regNum = X64Reg_RCX;
  7449. else if (lwrRegName == "dl")
  7450. regNum = X64Reg_RDX;
  7451. else if (lwrRegName == "bl")
  7452. regNum = X64Reg_RBX;
  7453. else if (lwrRegName == "sil")
  7454. regNum = X64Reg_RSI;
  7455. else if (lwrRegName == "dil")
  7456. regNum = X64Reg_RDI;
  7457. else if (lwrRegName == "r8b")
  7458. regNum = X64Reg_R8;
  7459. else if (lwrRegName == "r9b")
  7460. regNum = X64Reg_R9;
  7461. else if (lwrRegName == "r10b")
  7462. regNum = X64Reg_R10;
  7463. else if (lwrRegName == "r11b")
  7464. regNum = X64Reg_R11;
  7465. else if (lwrRegName == "r12b")
  7466. regNum = X64Reg_R12;
  7467. else if (lwrRegName == "r13b")
  7468. regNum = X64Reg_R13;
  7469. else if (lwrRegName == "r14b")
  7470. regNum = X64Reg_R14;
  7471. else if (lwrRegName == "r15b")
  7472. regNum = X64Reg_R15;
  7473. }
  7474. }
  7475. }
  7476. #endif
  7477. auto dbgModule = mDebugTarget->GetMainDbgModule();
  7478. if (regNum != -1)
  7479. {
  7480. DbgTypedValue typedVal;
  7481. typedVal.mType = dbgModule->GetPrimitiveType(regType, language);
  7482. typedVal.mInt64 = registers->mIntRegsArray[regNum];
  7483. typedVal.mRegNum = regNum;
  7484. return typedVal;
  7485. }
  7486. // st regs
  7487. if ((lwrRegName.length() == 3) && (lwrRegName[0] == 's') && (lwrRegName[1] == 't') && (lwrRegName[2] >= '0') && (lwrRegName[2] <= '7'))
  7488. {
  7489. regNum = CPUReg_FPSTREG_FIRST + (lwrRegName[2] - '0');
  7490. }
  7491. if (regNum != -1)
  7492. {
  7493. DbgTypedValue typedVal;
  7494. typedVal.mType = dbgModule->GetPrimitiveType(DbgType_Double, language);
  7495. typedVal.mDouble = ConvertFloat80ToDouble(registers->mFpMmRegsArray[regNum - CPUReg_FPSTREG_FIRST].fp.fp80);
  7496. typedVal.mRegNum = regNum;
  7497. return typedVal;
  7498. }
  7499. // mm regs
  7500. if ((lwrRegName.length() == 3) && (lwrRegName[0] == 'm') && (lwrRegName[1] == 'm') && (lwrRegName[2] >= '0') && (lwrRegName[2] <= '7'))
  7501. {
  7502. regNum = CPUReg_MMREG_FIRST + (lwrRegName[2] - '0');
  7503. }
  7504. if (regNum != -1)
  7505. {
  7506. DbgTypedValue typedVal;
  7507. typedVal.mType = dbgModule->GetPrimitiveType(DbgType_i64, language);
  7508. typedVal.mInt64 = registers->mFpMmRegsArray[regNum - CPUReg_MMREG_FIRST].mm;
  7509. typedVal.mRegNum = regNum;
  7510. return typedVal;
  7511. }
  7512. // xmm regs
  7513. #ifdef BF_DBG_32
  7514. if ((lwrRegName.length() == 6) && (lwrRegName[0] == 'x') && (lwrRegName[1] == 'm') && (lwrRegName[2] == 'm') && (lwrRegName[3] >= '0') && (lwrRegName[3] <= '7') &&
  7515. (lwrRegName[4] == '_') && (lwrRegName[5] >= '0') && (lwrRegName[5] <= '3'))
  7516. {
  7517. regNum = CPUReg_XMMREG_FIRST + ((lwrRegName[3] - '0') * 4) + (lwrRegName[5] - '0');
  7518. }
  7519. #else
  7520. if ((lwrRegName.length() == 6) && (lwrRegName[0] == 'x') && (lwrRegName[1] == 'm') && (lwrRegName[2] == 'm') && (lwrRegName[3] >= '0') && (lwrRegName[3] <= '9') &&
  7521. (lwrRegName[4] == '_') && (lwrRegName[5] >= '0') && (lwrRegName[5] <= '3'))
  7522. {
  7523. regNum = CPUReg_XMMREG_FIRST + ((lwrRegName[3] - '0') * 4) + (lwrRegName[5] - '0');
  7524. }
  7525. if ((lwrRegName.length() == 7) && (lwrRegName[0] == 'x') && (lwrRegName[1] == 'm') && (lwrRegName[2] == 'm') && (lwrRegName[3] == '1') && (lwrRegName[4] >= '0') && (lwrRegName[4] <= '9') &&
  7526. (lwrRegName[5] == '_') && (lwrRegName[6] >= '0') && (lwrRegName[6] <= '3'))
  7527. {
  7528. regNum = CPUReg_XMMREG_FIRST + ((10 + (lwrRegName[4] - '0')) * 4) + (lwrRegName[6] - '0');
  7529. }
  7530. #endif
  7531. if (regNum != -1)
  7532. {
  7533. int xmmMajor = (regNum - CPUReg_XMMREG_FIRST) >> 2;
  7534. int xmmMinor = (regNum - CPUReg_XMMREG_FIRST) & 3;
  7535. DwMmDisplayType mmDisplayType = GetDisplayInfo(StrFormat("$XMM%d", xmmMajor))->mMmDisplayType;
  7536. RegForm regForm = RegForm_Unknown;
  7537. if (regForms != NULL)
  7538. {
  7539. int regFormIdx = CPUReg_M128_XMMREG_FIRST + xmmMajor;
  7540. if (regFormIdx < (int)regForms->size())
  7541. regForm = (*regForms)[regFormIdx];
  7542. }
  7543. if (mmDisplayType == DwMmDisplayType_Default)
  7544. {
  7545. if ((regForm == RegForm_Double) || (regForm == RegForm_Double2))
  7546. mmDisplayType = DwMmDisplayType_Double;
  7547. else if (regForm == RegForm_Int4)
  7548. mmDisplayType = DwMmDisplayType_Int;
  7549. }
  7550. //TODO: Add int types
  7551. if (mmDisplayType == DwMmDisplayType_Double)
  7552. {
  7553. DbgTypedValue typedVal;
  7554. typedVal.mType = dbgModule->GetPrimitiveType(DbgType_Double, language);
  7555. typedVal.mDouble = registers->mXmmDRegsArray[xmmMajor].d[xmmMinor];
  7556. typedVal.mRegNum = regNum;
  7557. return typedVal;
  7558. }
  7559. if (mmDisplayType == DwMmDisplayType_Int)
  7560. {
  7561. DbgTypedValue typedVal;
  7562. typedVal.mType = dbgModule->GetPrimitiveType(DbgType_i32, language);
  7563. typedVal.mInt32 = registers->mXmmIRegsARray[xmmMajor].i[xmmMinor];
  7564. typedVal.mRegNum = regNum;
  7565. return typedVal;
  7566. }
  7567. DbgTypedValue typedVal;
  7568. typedVal.mType = dbgModule->GetPrimitiveType(DbgType_Single, language);
  7569. typedVal.mSingle = registers->mXmmRegsArray[xmmMajor].f[xmmMinor];
  7570. typedVal.mRegNum = regNum;
  7571. return typedVal;
  7572. }
  7573. #ifdef BF_DBG_32
  7574. if ((lwrRegName.length() == 4) && (lwrRegName[0] == 'x') && (lwrRegName[1] == 'm') && (lwrRegName[2] == 'm') && (lwrRegName[3] >= '0') && (lwrRegName[3] <= '7'))
  7575. {
  7576. regNum = CPUReg_M128_XMMREG_FIRST + (lwrRegName[3] - '0');
  7577. }
  7578. #else
  7579. if ((lwrRegName.length() == 4) && (lwrRegName[0] == 'x') && (lwrRegName[1] == 'm') && (lwrRegName[2] == 'm') && (lwrRegName[3] >= '0') && (lwrRegName[3] <= '9'))
  7580. {
  7581. regNum = CPUReg_M128_XMMREG_FIRST + (lwrRegName[3] - '0');
  7582. }
  7583. if ((lwrRegName.length() == 5) && (lwrRegName[0] == 'x') && (lwrRegName[1] == 'm') && (lwrRegName[2] == 'm') && (lwrRegName[3] == '1') && (lwrRegName[4] >= '0') && (lwrRegName[4] <= '5'))
  7584. {
  7585. regNum = CPUReg_M128_XMMREG_FIRST + 10 + (lwrRegName[4] - '0');
  7586. }
  7587. #endif
  7588. if (regNum != -1)
  7589. {
  7590. DbgTypedValue typedVal;
  7591. typedVal.mType = dbgModule->GetPrimitiveType(DbgType_RegGroup, language);
  7592. typedVal.mSingle = 0.0f; // ignored at a higher level (but if it's used as an rvalue in the meantime, it'll resolve to zero)
  7593. typedVal.mRegNum = regNum;
  7594. return typedVal;
  7595. }
  7596. // flags
  7597. if ((lwrRegName.length() == 6) && (lwrRegName[0] == 'f') && (lwrRegName[1] == 'l') && (lwrRegName[2] == 'a') && (lwrRegName[3] == 'g') && (lwrRegName[5] == 'f'))
  7598. {
  7599. switch(lwrRegName[4])
  7600. {
  7601. case 'c': regNum = CPUReg_FLAG_CF_CARRY; break;
  7602. case 'p': regNum = CPUReg_FLAG_PF_PARITY; break;
  7603. case 'a': regNum = CPUReg_FLAG_AF_ADJUST; break;
  7604. case 'z': regNum = CPUReg_FLAG_ZF_ZERO; break;
  7605. case 's': regNum = CPUReg_FLAG_SF_SIGN; break;
  7606. case 'i': regNum = CPUReg_FLAG_IF_INTERRUPT; break;
  7607. case 'd': regNum = CPUReg_FLAG_DF_DIRECTION; break;
  7608. case 'o': regNum = CPUReg_FLAG_OF_OVERFLOW; break;
  7609. default: break;
  7610. }
  7611. }
  7612. if (regNum != -1)
  7613. {
  7614. int flagBit = CPURegisters::GetFlagBitForRegister(regNum);
  7615. BF_ASSERT(flagBit >= 0);
  7616. DbgTypedValue typedVal;
  7617. typedVal.mType = dbgModule->GetPrimitiveType(DbgType_Bool, language);
  7618. typedVal.mBool = (registers->mIntRegs.efl & ((uint64)1 << flagBit)) != 0;
  7619. typedVal.mRegNum = regNum;
  7620. return typedVal;
  7621. }
  7622. // categories
  7623. if (lwrRegName == "allregs")
  7624. regNum = CPUReg_CAT_ALLREGS;
  7625. else if (lwrRegName == "iregs")
  7626. regNum = CPUReg_CAT_IREGS;
  7627. else if (lwrRegName == "fpregs")
  7628. regNum = CPUReg_CAT_FPREGS;
  7629. else if (lwrRegName == "mmregs")
  7630. regNum = CPUReg_CAT_MMREGS;
  7631. else if (lwrRegName == "xmmregs")
  7632. regNum = CPUReg_CAT_XMMREGS;
  7633. else if (lwrRegName == "flags")
  7634. regNum = CPUReg_CAT_FLAGS;
  7635. if (regNum != -1)
  7636. {
  7637. DbgTypedValue typedVal;
  7638. typedVal.mType = dbgModule->GetPrimitiveType(DbgType_RegGroup, language);
  7639. typedVal.mSingle = 0.0f; // ignored at a higher level (but if it's used as an rvalue in the meantime, it'll resolve to zero)
  7640. typedVal.mRegNum = regNum;
  7641. return typedVal;
  7642. }
  7643. return DbgTypedValue();
  7644. }
  7645. DbgModule* WinDebugger::GetCallStackDbgModule(int callStackIdx)
  7646. {
  7647. if ((mRunState == RunState_NotStarted) || (!IsPaused()))
  7648. return mEmptyDebugTarget->GetMainDbgModule();
  7649. if (callStackIdx == -1)
  7650. return mDebugTarget->GetMainDbgModule();
  7651. FixCallStackIdx(callStackIdx);
  7652. if (callStackIdx >= mCallStack.size())
  7653. return mDebugTarget->GetMainDbgModule();
  7654. UpdateCallStackMethod(callStackIdx);
  7655. auto subProgram = mCallStack[callStackIdx]->mSubProgram;
  7656. if (subProgram != NULL)
  7657. return subProgram->mCompileUnit->mDbgModule;
  7658. auto dbgModule = mDebugTarget->FindDbgModuleForAddress(mCallStack[callStackIdx]->mRegisters.GetPC());
  7659. if (dbgModule != NULL)
  7660. return dbgModule;
  7661. return mDebugTarget->GetMainDbgModule();
  7662. }
  7663. DbgSubprogram* WinDebugger::GetCallStackSubprogram(int callStackIdx)
  7664. {
  7665. if ((IsInRunState()) || (mRunState == RunState_NotStarted) || (callStackIdx == -1))
  7666. return NULL;
  7667. if (callStackIdx >= (int)mCallStack.size())
  7668. UpdateCallStack();
  7669. if (mCallStack.IsEmpty())
  7670. return NULL;
  7671. if (callStackIdx >= (int)mCallStack.size())
  7672. callStackIdx = 0;
  7673. UpdateCallStackMethod(callStackIdx);
  7674. auto subProgram = mCallStack[callStackIdx]->mSubProgram;
  7675. return subProgram;
  7676. }
  7677. DbgCompileUnit* WinDebugger::GetCallStackCompileUnit(int callStackIdx)
  7678. {
  7679. if ((IsInRunState()) || (mRunState == RunState_NotStarted) || (callStackIdx == -1))
  7680. return NULL;
  7681. if (callStackIdx >= (int)mCallStack.size())
  7682. UpdateCallStack();
  7683. if (mCallStack.IsEmpty())
  7684. return NULL;
  7685. if (callStackIdx >= (int)mCallStack.size())
  7686. callStackIdx = 0;
  7687. UpdateCallStackMethod(callStackIdx);
  7688. auto subProgram = mCallStack[callStackIdx]->mSubProgram;
  7689. if (subProgram == NULL)
  7690. return NULL;
  7691. return subProgram->mCompileUnit;
  7692. }
  7693. String WinDebugger::EvaluateContinue(DbgPendingExpr* pendingExpr, BfPassInstance& bfPassInstance)
  7694. {
  7695. DbgModule* dbgModule = NULL;
  7696. DbgCompileUnit* dbgCompileUnit = NULL;
  7697. if (pendingExpr->mThreadId == -1)
  7698. {
  7699. if ((pendingExpr->mFormatInfo.mLanguage == DbgLanguage_Beef) && (mDebugTarget != NULL) && (mDebugTarget->mTargetBinary != NULL))
  7700. dbgModule = mDebugTarget->mTargetBinary;
  7701. else
  7702. dbgModule = mEmptyDebugTarget->GetMainDbgModule();
  7703. }
  7704. else
  7705. {
  7706. dbgModule = GetCallStackDbgModule(pendingExpr->mCallStackIdx);
  7707. if (!dbgModule->mDebugTarget->mIsEmpty)
  7708. dbgCompileUnit = GetCallStackCompileUnit(pendingExpr->mCallStackIdx);
  7709. }
  7710. if (!pendingExpr->mException.empty())
  7711. {
  7712. RestoreAllRegisters();
  7713. return "!" + pendingExpr->mException;
  7714. }
  7715. DwAutoComplete autoComplete;
  7716. if (bfPassInstance.HasFailed())
  7717. {
  7718. // Don't allow pending calls if we've already failed in the calling Evaluate()
  7719. pendingExpr->mExpressionFlags = (DwEvalExpressionFlags)(pendingExpr->mExpressionFlags & ~DwEvalExpressionFlag_AllowCalls);
  7720. }
  7721. DbgExprEvaluator dbgExprEvaluator(this, dbgModule, &bfPassInstance, pendingExpr->mCallStackIdx, pendingExpr->mCursorPos);
  7722. dbgExprEvaluator.mLanguage = pendingExpr->mFormatInfo.mLanguage;
  7723. dbgExprEvaluator.mReferenceId = &pendingExpr->mReferenceId;
  7724. dbgExprEvaluator.mExpressionFlags = pendingExpr->mExpressionFlags;
  7725. dbgExprEvaluator.mExplicitThis = pendingExpr->mFormatInfo.mExplicitThis;
  7726. dbgExprEvaluator.mSubjectExpr = pendingExpr->mFormatInfo.mSubjectExpr;
  7727. dbgExprEvaluator.mNamespaceSearchStr = pendingExpr->mFormatInfo.mNamespaceSearch;
  7728. dbgExprEvaluator.mExpectingTypeName = pendingExpr->mFormatInfo.mExpectedType;
  7729. dbgExprEvaluator.mCallResults = &pendingExpr->mCallResults;
  7730. if ((pendingExpr->mExpressionFlags & DwEvalExpressionFlag_ValidateOnly) != 0)
  7731. {
  7732. dbgExprEvaluator.mValidateOnly = true;
  7733. }
  7734. if (pendingExpr->mCursorPos != -1)
  7735. {
  7736. dbgExprEvaluator.mAutoComplete = &autoComplete;
  7737. }
  7738. dbgExprEvaluator.mDbgCompileUnit = dbgCompileUnit;
  7739. DbgTypedValue exprResult;
  7740. if (pendingExpr->mExplitType != NULL)
  7741. {
  7742. exprResult.mHasNoValue = true;
  7743. exprResult.mType = pendingExpr->mExplitType;
  7744. }
  7745. else if (pendingExpr->mExprNode != NULL)
  7746. {
  7747. exprResult = dbgExprEvaluator.Resolve(pendingExpr->mExprNode);
  7748. }
  7749. if (dbgExprEvaluator.mCreatedPendingCall)
  7750. {
  7751. BF_ASSERT(mRunState == RunState_DebugEval);
  7752. //ContinueDebugEvent();
  7753. return "!pending";
  7754. }
  7755. if (dbgExprEvaluator.mCountResultOverride != -1)
  7756. pendingExpr->mFormatInfo.mOverrideCount = dbgExprEvaluator.mCountResultOverride;
  7757. String val;
  7758. if (bfPassInstance.HasFailed())
  7759. {
  7760. BfLogDbgExpr("Evaluate Failed: %s\n", bfPassInstance.mErrors[0]->mError.c_str());
  7761. val = StrFormat("!%d\t%d\t%s", bfPassInstance.mErrors[0]->GetSrcStart(), bfPassInstance.mErrors[0]->GetSrcLength(), bfPassInstance.mErrors[0]->mError.c_str());
  7762. }
  7763. else if (dbgExprEvaluator.mBlockedSideEffects)
  7764. {
  7765. BfLogDbgExpr("Evaluate blocked side effects\n");
  7766. val = "!sideeffects";
  7767. }
  7768. else if (!exprResult)
  7769. {
  7770. if (exprResult.mType != NULL)
  7771. {
  7772. BfLogDbgExpr("Evaluate success\n");
  7773. String typeName = exprResult.mType->ToString();
  7774. DbgType* rawType = exprResult.mType;
  7775. if (rawType->IsBfObjectPtr())
  7776. rawType = rawType->mTypeParam;
  7777. String typeNameRaw = rawType->ToStringRaw();
  7778. val = typeName + "\n" + typeName;
  7779. val += "\n" + GetMemberList(exprResult.mType, typeNameRaw, false, true, false, false, exprResult.mIsReadOnly);
  7780. if (exprResult.mType->mTypeCode == DbgType_Namespace)
  7781. {
  7782. val += "\n:type\tnamespace";
  7783. }
  7784. else
  7785. {
  7786. auto type = exprResult.mType;
  7787. if (type->IsPointer())
  7788. type = type->mTypeParam;
  7789. if (type->IsBfObject())
  7790. val += "\n:type\tclass";
  7791. else
  7792. val += "\n:type\tvaluetype";
  7793. }
  7794. if (!pendingExpr->mReferenceId.empty())
  7795. val += "\n:referenceId\t" + pendingExpr->mReferenceId;
  7796. }
  7797. else
  7798. val = "!";
  7799. }
  7800. else if ((pendingExpr->mExpressionFlags & (DwEvalExpressionFlag_MemoryAddress)) != 0)
  7801. {
  7802. DbgType* resultType = exprResult.mType->RemoveModifiers();
  7803. if ((resultType->IsInteger()) || (resultType->IsPointerOrRef()))
  7804. {
  7805. val = EncodeDataPtr(exprResult.mPtr, false) + "\n" + StrFormat("%d", 0);
  7806. }
  7807. else
  7808. {
  7809. if (exprResult.mSrcAddress != 0)
  7810. val = StrFormat("!Type '%s' is invalid. A pointer or address value is expected. Try using the '&' address-of operator.", exprResult.mType->ToString().c_str());
  7811. else
  7812. val = StrFormat("!Type '%s' is invalid. A pointer or address value is expected. An explicit cast may be required.", exprResult.mType->ToString().c_str());
  7813. }
  7814. }
  7815. else if ((pendingExpr->mExpressionFlags & (DwEvalExpressionFlag_MemoryWatch)) != 0)
  7816. {
  7817. DbgType* resultType = exprResult.mType->RemoveModifiers();
  7818. bool isMemoryWatch = (pendingExpr->mExpressionFlags & DwEvalExpressionFlag_MemoryWatch) != 0;
  7819. if (!resultType->IsPointerOrRef())
  7820. {
  7821. if (exprResult.mSrcAddress != 0)
  7822. val = StrFormat("!Type '%s' is invalid. A sized pointer type is expected. Try using the '&' address-of operator.", exprResult.mType->ToString().c_str());
  7823. else
  7824. val = StrFormat("!Type '%s' is invalid. A sized pointer type is expected. An explicit cast may be required.", exprResult.mType->ToString().c_str());
  7825. }
  7826. else
  7827. {
  7828. auto innerType = resultType->mTypeParam;
  7829. int byteCount = innerType->GetByteCount();
  7830. if (pendingExpr->mFormatInfo.mArrayLength != -1)
  7831. byteCount *= pendingExpr->mFormatInfo.mArrayLength;
  7832. if (byteCount == 0)
  7833. {
  7834. val = StrFormat("!Type '%s' is invalid. A sized pointer type is expected, try casting to a non-void pointer type.", exprResult.mType->ToString().c_str());
  7835. }
  7836. #ifdef BF_DBG_32
  7837. else if ((isMemoryWatch) && (!IsMemoryBreakpointSizeValid(exprResult.mPtr, byteCount)))
  7838. {
  7839. if (innerType->mSize > 16)
  7840. val = StrFormat("!Element size is %d bytes. A maximum of 16 bytes can be watched. Try casting to an appropriately-sized pointer or watching an individual member.", byteCount);
  7841. else if (!IsMemoryBreakpointSizeValid(0, byteCount))
  7842. val = StrFormat("!Element size is %d bytes, which is not a supported size for a memory watch. Try casting to an appropriately-sized pointer.", byteCount);
  7843. else
  7844. val = StrFormat("!Element size is %d bytes, which is not a supported size for a memory watch at non-aligned address %@. Try casting to an appropriately-sized pointer.", byteCount, exprResult.mPtr);
  7845. }
  7846. #else
  7847. else if ((isMemoryWatch) && (!IsMemoryBreakpointSizeValid(exprResult.mPtr, byteCount)))
  7848. {
  7849. if (innerType->mSize > 32)
  7850. val = StrFormat("!Element size is %d bytes. A maximum of 32 bytes can be watched. Try casting to an appropriately-sized pointer or watching an individual member.", byteCount);
  7851. else if (!IsMemoryBreakpointSizeValid(0, byteCount))
  7852. val = StrFormat("!Element size is %d bytes, which is not a supported size for a memory watch. Try casting to an appropriately-sized pointer.", byteCount);
  7853. else
  7854. val = StrFormat("!Element size is %d bytes, which is not a supported size for a memory watch at non-aligned address %@. Try casting to an appropriately-sized pointer.", byteCount, exprResult.mPtr);
  7855. }
  7856. #endif
  7857. else
  7858. {
  7859. auto language = dbgExprEvaluator.GetLanguage();
  7860. val = EncodeDataPtr(exprResult.mPtr, false) + "\n" + StrFormat("%d", byteCount) + "\n" + StrFormat("%d\t", language) + innerType->ToStringRaw(language);
  7861. }
  7862. }
  7863. }
  7864. else
  7865. {
  7866. if (pendingExpr->mFormatInfo.mNoEdit)
  7867. exprResult.mIsReadOnly = true;
  7868. if (!pendingExpr->mReferenceId.empty())
  7869. pendingExpr->mFormatInfo.mReferenceId = pendingExpr->mReferenceId;
  7870. val = DbgTypedValueToString(exprResult, pendingExpr->mExprNode->ToString(), pendingExpr->mFormatInfo, &dbgExprEvaluator, (pendingExpr->mExpressionFlags & DwEvalExpressionFlag_FullPrecision) != 0);
  7871. if ((!val.empty()) && (val[0] == '!'))
  7872. return val;
  7873. if (pendingExpr->mFormatInfo.mRawString)
  7874. return val;
  7875. if (exprResult.mIsLiteral)
  7876. val += "\n:literal";
  7877. if (bfPassInstance.HasMessages())
  7878. {
  7879. for (auto error : bfPassInstance.mErrors)
  7880. {
  7881. if (error->mIsWarning)
  7882. {
  7883. val += "\n:warn\t";
  7884. val += error->mError;
  7885. }
  7886. }
  7887. }
  7888. if (!pendingExpr->mFormatInfo.mReferenceId.empty())
  7889. val += "\n:referenceId\t" + pendingExpr->mFormatInfo.mReferenceId;
  7890. if ((exprResult.mSrcAddress != 0) && (HasMemoryBreakpoint(exprResult.mSrcAddress, exprResult.mType->GetByteCount())))
  7891. val += StrFormat("\n:break\t%@", exprResult.mSrcAddress);
  7892. auto checkType = exprResult.mType->RemoveModifiers();
  7893. if (checkType->IsBfObjectPtr())
  7894. val += "\n:type\tobject";
  7895. else if ((checkType->IsPointer()) || (checkType->mTypeCode == DbgType_Subroutine))
  7896. val += "\n:type\tpointer";
  7897. else if (checkType->IsInteger())
  7898. val += "\n:type\tint";
  7899. else if ((exprResult.mRegNum >= X64Reg_M128_XMM0) && (exprResult.mRegNum <= X64Reg_M128_XMM15))
  7900. val += "\n:type\tmm128";
  7901. if (dbgExprEvaluator.mHadSideEffects)
  7902. val += "\n:sideeffects";
  7903. auto underlyingType = exprResult.mType->RemoveModifiers();
  7904. bool canEdit = true;
  7905. if (pendingExpr->mFormatInfo.mLanguage == DbgLanguage_Beef)
  7906. {
  7907. if (exprResult.mType->IsConst())
  7908. canEdit = false;
  7909. }
  7910. if (pendingExpr->mFormatInfo.mNoEdit)
  7911. canEdit = false;
  7912. if (exprResult.mIsReadOnly)
  7913. canEdit = false;
  7914. if (val[0] == '!')
  7915. {
  7916. // Already has an error embedded, can't edit
  7917. }
  7918. else if ((exprResult.mSrcAddress != 0) && (underlyingType->mTypeCode >= DbgType_i8) && (underlyingType->mTypeCode <= DbgType_Ptr) &&
  7919. (underlyingType->mTypeCode != DbgType_Class) && (underlyingType->mTypeCode != DbgType_Struct))
  7920. {
  7921. if (canEdit)
  7922. val += "\n:canEdit";
  7923. if (exprResult.mType->mTypeCode == DbgType_Ptr)
  7924. {
  7925. val += "\n:editVal\t" + EncodeDataPtr(exprResult.mPtr, true);
  7926. }
  7927. }
  7928. else if ((underlyingType->IsStruct()) && (exprResult.mSrcAddress != 0) && (underlyingType->IsTypedPrimitive()))
  7929. {
  7930. auto primType = underlyingType->GetRootBaseType();
  7931. DbgTypedValue primVal = dbgExprEvaluator.ReadTypedValue(primType, exprResult.mSrcAddress, DbgAddrType_Target);
  7932. String primResult = DbgTypedValueToString(primVal, "", pendingExpr->mFormatInfo, NULL);
  7933. int crPos = (int)primResult.IndexOf('\n');
  7934. if (crPos != -1)
  7935. primResult.RemoveToEnd(crPos);
  7936. if (canEdit)
  7937. val += "\n:canEdit";
  7938. val += "\n:editVal\t" + primResult;
  7939. }
  7940. else if (exprResult.mRegNum >= 0)
  7941. {
  7942. bool isPseudoReg = ( ((exprResult.mRegNum >= X86Reg_M128_XMMREG_FIRST) && (exprResult.mRegNum <= X86Reg_M128_XMMREG_LAST))
  7943. || ((exprResult.mRegNum >= X86Reg_CAT_FIRST) && (exprResult.mRegNum <= X86Reg_CAT_LAST)) );
  7944. if (!isPseudoReg)
  7945. {
  7946. if (canEdit)
  7947. val += "\n:canEdit";
  7948. }
  7949. }
  7950. }
  7951. if (pendingExpr->mFormatInfo.mRawString)
  7952. return "";
  7953. if (pendingExpr->mCursorPos != -1)
  7954. val += GetAutocompleteOutput(autoComplete);
  7955. return val;
  7956. }
  7957. String WinDebugger::EvaluateContinue()
  7958. {
  7959. BP_ZONE("WinDebugger::EvaluateContinue");
  7960. AutoCrit autoCrit(mDebugManager->mCritSect);
  7961. if (mDebugPendingExpr == NULL)
  7962. return "!Evaluation canceled";
  7963. if (!IsPaused())
  7964. return "!Not paused";
  7965. if (mRunState == RunState_DebugEval_Done)
  7966. mRunState = RunState_Paused;
  7967. BfPassInstance bfPassInstance(mBfSystem);
  7968. String result = EvaluateContinue(mDebugPendingExpr, bfPassInstance);
  7969. if (result != "!pending")
  7970. {
  7971. BfLogDbg("EvaluateContinue finishing pending expr in thread %d\n", mDebugEvalThreadInfo.mThreadId);
  7972. CleanupDebugEval();
  7973. }
  7974. return result;
  7975. }
  7976. void WinDebugger::EvaluateContinueKeep()
  7977. {
  7978. if (mDebugPendingExpr != NULL)
  7979. mDebugPendingExpr->mIdleTicks = 0;
  7980. }
  7981. String WinDebugger::Evaluate(const StringImpl& expr, DwFormatInfo formatInfo, int callStackIdx, int cursorPos, int language, DwEvalExpressionFlags expressionFlags)
  7982. {
  7983. BP_ZONE_F("WinDebugger::Evaluate %s", BP_DYN_STR(expr.c_str()));
  7984. AutoCrit autoCrit(mDebugManager->mCritSect);
  7985. if ((expressionFlags & DwEvalExpressionFlag_Symbol) != 0)
  7986. {
  7987. DwAutoComplete autoComplete;
  7988. String retVal;
  7989. retVal += GetAutocompleteOutput(autoComplete);
  7990. return retVal;
  7991. }
  7992. UpdateCallStackMethod(callStackIdx);
  7993. BfLogDbgExpr("Evaluate %s in thread %d\n", expr.c_str(), (mActiveThread != NULL) ? mActiveThread->mThreadId : 0);
  7994. if (language != -1)
  7995. formatInfo.mLanguage = (DbgLanguage)language;
  7996. auto activeThread = mActiveThread;
  7997. if ((!IsPaused()) && (mRunState != RunState_NotStarted) && (mRunState != RunState_DebugEval))
  7998. {
  7999. activeThread = NULL;
  8000. callStackIdx = -1;
  8001. }
  8002. if (mDebugPendingExpr != NULL)
  8003. {
  8004. // We already have a pending call
  8005. expressionFlags = (DwEvalExpressionFlags)(expressionFlags & ~DwEvalExpressionFlag_AllowCalls);
  8006. }
  8007. auto dbgModule = GetCallStackDbgModule(callStackIdx);
  8008. auto dbgSubprogram = GetCallStackSubprogram(callStackIdx);
  8009. DbgCompileUnit* dbgCompileUnit = NULL;
  8010. if (dbgSubprogram != NULL)
  8011. dbgCompileUnit = dbgSubprogram->mCompileUnit;
  8012. auto terminatedExpr = expr + ";";
  8013. if ((expr.length() > 0) && (expr[0] == '!'))
  8014. {
  8015. if (expr.StartsWith("!step "))
  8016. {
  8017. expressionFlags = (DwEvalExpressionFlags)(expressionFlags | DwEvalExpressionFlag_StepIntoCalls);
  8018. for (int i = 0; i < 5; i++)
  8019. terminatedExpr[i] = ' ';
  8020. }
  8021. else
  8022. {
  8023. String cmd = expr;
  8024. int commaPos = (int)cmd.IndexOf(',');
  8025. if (commaPos != -1)
  8026. cmd.RemoveToEnd(commaPos);
  8027. if (cmd == "!info")
  8028. {
  8029. OutputMessage(StrFormat("Module: %s\n", dbgModule->mDisplayName.c_str()));
  8030. if (dbgSubprogram == NULL)
  8031. {
  8032. //
  8033. }
  8034. else if (dbgSubprogram->mLinkName != NULL)
  8035. {
  8036. OutputMessage(StrFormat("Link Name: %s\n", dbgSubprogram->mLinkName));
  8037. }
  8038. else
  8039. {
  8040. String outSymbol;
  8041. if (mDebugTarget->FindSymbolAt(dbgSubprogram->mBlock.mLowPC, &outSymbol))
  8042. {
  8043. OutputMessage(StrFormat("Link Name: %s\n", outSymbol.c_str()));
  8044. }
  8045. }
  8046. return "";
  8047. }
  8048. else if (cmd == "!dbg")
  8049. {
  8050. mDbgBreak = true;
  8051. return "";
  8052. }
  8053. }
  8054. }
  8055. bool valIsAddr = false;
  8056. BfParser* parser = new BfParser(mBfSystem);
  8057. parser->mCompatMode = true;
  8058. BfPassInstance bfPassInstance(mBfSystem);
  8059. if ((terminatedExpr.length() > 2) && (terminatedExpr[0] == '@'))
  8060. {
  8061. if (terminatedExpr[1] == '!') // Return string as error
  8062. {
  8063. int errorEnd = (int)terminatedExpr.IndexOf("@!", 2);
  8064. if (errorEnd != -1)
  8065. return terminatedExpr.Substring(1, errorEnd - 1);
  8066. else
  8067. return terminatedExpr.Substring(1);
  8068. }
  8069. else if (terminatedExpr[1] == '>') // Return string as text
  8070. {
  8071. int errorEnd = (int)terminatedExpr.IndexOf("@>", 2);
  8072. if (errorEnd != -1)
  8073. return terminatedExpr.Substring(2, errorEnd - 1);
  8074. else
  8075. return terminatedExpr.Substring(2);
  8076. }
  8077. else // Look for "@:" or "@Beef:" style
  8078. {
  8079. int colonIdx = terminatedExpr.IndexOf(':');
  8080. if (colonIdx > 0)
  8081. {
  8082. bool isValid = true;
  8083. DbgLanguage language = DbgLanguage_Unknown;
  8084. String lang = terminatedExpr.Substring(1, colonIdx - 1);
  8085. lang = ToUpper(lang);
  8086. if ((lang == "") || (lang == "BEEF"))
  8087. {
  8088. language = DbgLanguage_Beef;
  8089. }
  8090. else if (lang == "C")
  8091. {
  8092. language = DbgLanguage_C;
  8093. }
  8094. if (language != DbgLanguage_Unknown)
  8095. {
  8096. for (int i = 0; i < colonIdx + 1; i++)
  8097. terminatedExpr[i] = ' ';
  8098. DbgLanguage curLanguage = DbgLanguage_Unknown;
  8099. if (dbgSubprogram != NULL)
  8100. curLanguage = dbgSubprogram->GetLanguage();
  8101. if (language != curLanguage)
  8102. {
  8103. dbgModule = mDebugTarget->mTargetBinary;
  8104. dbgSubprogram = NULL;
  8105. formatInfo.mLanguage = language;
  8106. callStackIdx = -1;
  8107. }
  8108. }
  8109. }
  8110. }
  8111. }
  8112. parser->SetSource(terminatedExpr.c_str(), terminatedExpr.length());
  8113. parser->Parse(&bfPassInstance);
  8114. BfReducer bfReducer;
  8115. bfReducer.mAlloc = parser->mAlloc;
  8116. bfReducer.mSystem = mBfSystem;
  8117. bfReducer.mPassInstance = &bfPassInstance;
  8118. bfReducer.mVisitorPos = BfReducer::BfVisitorPos(parser->mRootNode);
  8119. bfReducer.mVisitorPos.MoveNext();
  8120. bfReducer.mCompatMode = parser->mCompatMode;
  8121. bfReducer.mSource = parser;
  8122. auto exprNode = bfReducer.CreateExpression(parser->mRootNode->mChildArr.GetAs<BfAstNode*>(0));
  8123. parser->Close();
  8124. formatInfo.mCallStackIdx = callStackIdx;
  8125. if ((formatInfo.mLanguage == DbgLanguage_Unknown) && (dbgSubprogram != NULL))
  8126. formatInfo.mLanguage = dbgSubprogram->GetLanguage();
  8127. DbgPendingExpr* pendingExpr = new DbgPendingExpr();
  8128. if (activeThread != NULL)
  8129. pendingExpr->mThreadId = activeThread->mThreadId;
  8130. pendingExpr->mParser = parser;
  8131. pendingExpr->mCallStackIdx = callStackIdx;
  8132. pendingExpr->mCursorPos = cursorPos;
  8133. pendingExpr->mExpressionFlags = expressionFlags;
  8134. pendingExpr->mExprNode = exprNode;
  8135. DbgType* explicitType = NULL;
  8136. String formatFlags;
  8137. String assignExpr;
  8138. int assignExprOffset = -1;
  8139. if ((exprNode != NULL) && (exprNode->GetSrcEnd() < (int)expr.length()))
  8140. {
  8141. int formatOffset = exprNode->GetSrcEnd();
  8142. while (formatOffset < (int)expr.length())
  8143. {
  8144. char c = expr[formatOffset];
  8145. if (c == ' ')
  8146. formatOffset++;
  8147. else
  8148. break;
  8149. }
  8150. formatFlags = Trim(expr.Substring(formatOffset));
  8151. bool isComplexType = false;
  8152. for (char c : formatFlags)
  8153. if (c == '>')
  8154. isComplexType = true;
  8155. if (isComplexType)
  8156. {
  8157. explicitType = dbgModule->FindType(expr);
  8158. }
  8159. if ((explicitType == NULL) && (formatFlags.length() > 0))
  8160. {
  8161. String errorString = "Invalid expression";
  8162. if (!ParseFormatInfo(dbgModule, formatFlags, &formatInfo, &bfPassInstance, &assignExprOffset, &assignExpr, &errorString))
  8163. {
  8164. if (formatInfo.mRawString)
  8165. return "";
  8166. bfPassInstance.FailAt(errorString, parser->mSourceData, exprNode->GetSrcEnd(), (int) expr.length() - exprNode->GetSrcEnd());
  8167. formatFlags = "";
  8168. }
  8169. if (assignExprOffset != -1)
  8170. assignExprOffset += formatOffset;
  8171. }
  8172. }
  8173. if (assignExpr.length() > 0)
  8174. {
  8175. String newEvalStr = exprNode->ToString() + " = ";
  8176. int errorOffset = (int)newEvalStr.length();
  8177. newEvalStr += assignExpr;
  8178. String result = Evaluate(newEvalStr, formatInfo, callStackIdx, cursorPos, language, expressionFlags);
  8179. if (result[0] == '!')
  8180. {
  8181. int tabPos = (int)result.IndexOf('\t');
  8182. if (tabPos > 0)
  8183. {
  8184. int errorStart = atoi(result.Substring(1, tabPos - 1).c_str());
  8185. if (errorStart >= errorOffset)
  8186. {
  8187. result = StrFormat("!%d", errorStart - errorOffset + assignExprOffset) + result.Substring(tabPos);
  8188. }
  8189. }
  8190. }
  8191. return result;
  8192. }
  8193. pendingExpr->mExplitType = explicitType;
  8194. pendingExpr->mFormatInfo = formatInfo;
  8195. String result = EvaluateContinue(pendingExpr, bfPassInstance);
  8196. if (result == "!pending")
  8197. {
  8198. BF_ASSERT(mDebugPendingExpr == NULL);
  8199. if (mDebugPendingExpr != NULL)
  8200. {
  8201. return "!retry"; // We already have a pending
  8202. }
  8203. mDebugPendingExpr = pendingExpr;
  8204. mDebugEvalThreadInfo = *mActiveThread;
  8205. mActiveThread->mIsAtBreakpointAddress = 0;
  8206. mActiveThread->mStoppedAtAddress = 0;
  8207. mActiveThread->mBreakpointAddressContinuing = 0;
  8208. }
  8209. else
  8210. delete pendingExpr;
  8211. return result;
  8212. }
  8213. String WinDebugger::Evaluate(const StringImpl& expr, int callStackIdx, int cursorPos, int language, DwEvalExpressionFlags expressionFlags)
  8214. {
  8215. DwFormatInfo formatInfo;
  8216. return Evaluate(expr, formatInfo, callStackIdx, cursorPos, language, expressionFlags);
  8217. }
  8218. static void ConvertDoubleToFloat80(double d, byte fp80[10])
  8219. {
  8220. uint64 di = *reinterpret_cast<uint64*>(&d);
  8221. uint64 m = di & (((uint64)1 << 52) - 1);
  8222. uint64 e = (di >> 52) & 0x7ff;
  8223. memset(fp80, 0, 10);
  8224. // sign bit is directly transferred
  8225. if (di & ((uint64)1 << 63))
  8226. fp80[9] |= 0x80;
  8227. if (!e && !m)
  8228. return; // zero
  8229. fp80[7] |= 0x80; // leading integer bit in mantissa (always 1 in normalized numbers)
  8230. if (e == 0x7ff)
  8231. {
  8232. fp80[9] |= 0x7f;
  8233. fp80[8] = 0xff;
  8234. if (m == 0)
  8235. return; // inf
  8236. fp80[7] |= 0x3f; // any nonzero value will be a NaN (SNaN or QNaN)
  8237. if (m & ((uint64)1 << 51))
  8238. fp80[7] |= 0x40; // QNaN
  8239. return;
  8240. }
  8241. int useExponent = (int)e - 1023;
  8242. if (!e)
  8243. {
  8244. // denormal; can renormalize though since fp80 supports lower exponents
  8245. BF_ASSERT(m != 0); // we should have trapped zero above
  8246. while (!(m & ((uint64)1 << 51)))
  8247. {
  8248. m <<= 1;
  8249. --useExponent;
  8250. }
  8251. // finally we have our leading 1 bit; strip that off and we have a normalized number again
  8252. m <<= 1;
  8253. --useExponent;
  8254. m &= (((uint64)1 << 52) - 1);
  8255. }
  8256. useExponent += 16383;
  8257. BF_ASSERT((useExponent > 0) && (useExponent < 0x7fff));
  8258. *reinterpret_cast<uint16*>(&fp80[8]) |= (uint16)useExponent;
  8259. *reinterpret_cast<uint64*>(&fp80[0]) |= (m << 11);
  8260. }
  8261. bool WinDebugger::AssignToReg(int callStackIdx, DbgTypedValue regVal, DbgTypedValue value, String& outError)
  8262. {
  8263. BF_ASSERT(regVal.mRegNum >= 0);
  8264. if (mCallStack.size() == 0)
  8265. {
  8266. outError = "No call stack";
  8267. return false;
  8268. }
  8269. if (callStackIdx >= (int)mCallStack.size())
  8270. {
  8271. outError = "Invalid call stack index";
  8272. return false;
  8273. }
  8274. auto registers = &mCallStack[callStackIdx]->mRegisters;
  8275. void* regPtr = NULL;
  8276. #ifdef BF_DBG_32
  8277. if ((regVal.mRegNum >= X86Reg_INTREG_FIRST) && (regVal.mRegNum <= X86Reg_INTREG_LAST))
  8278. {
  8279. BF_ASSERT(regVal.mType->mSize == sizeof(int32));
  8280. registers->mIntRegsArray[regVal.mRegNum - X86Reg_INTREG_FIRST] = (uint64)value.mUInt32; // don't sign-extend
  8281. }
  8282. else if ((regVal.mRegNum >= X86Reg_FPSTREG_FIRST) && (regVal.mRegNum <= X86Reg_FPSTREG_LAST))
  8283. {
  8284. BF_ASSERT(regVal.mType->mSize == sizeof(float) || regVal.mType->mSize == sizeof(double));
  8285. CPURegisters::FpMmReg* reg = &registers->mFpMmRegsArray[regVal.mRegNum - X86Reg_FPSTREG_FIRST];
  8286. double d;
  8287. if (regVal.mType->mSize == sizeof(float))
  8288. d = (double)value.mSingle;
  8289. else
  8290. d = value.mDouble;
  8291. ConvertDoubleToFloat80(d, reg->fp.fp80);
  8292. }
  8293. else if ((regVal.mRegNum >= X86Reg_MMREG_FIRST) && (regVal.mRegNum <= X86Reg_MMREG_LAST))
  8294. {
  8295. BF_ASSERT(regVal.mType->mSize == sizeof(int32) || regVal.mType->mSize == sizeof(int64));
  8296. CPURegisters::FpMmReg* reg = &registers->mFpMmRegsArray[regVal.mRegNum - X86Reg_MMREG_FIRST];
  8297. if (regVal.mType->mSize == sizeof(int32))
  8298. reg->mm = (uint64)value.mUInt32; // don't sign-extend
  8299. else if (regVal.mType->mSize == sizeof(int64))
  8300. reg->mm = value.mInt64;
  8301. // whenever we use the low 64 bits of the reg as mm, the upper 16 bits of the 80-bit float must be set to all-1s to indicate NaN
  8302. reg->fp.fp80[8] = reg->fp.fp80[9] = 0xFF;
  8303. }
  8304. else if ((regVal.mRegNum >= X86Reg_XMMREG_FIRST) && (regVal.mRegNum <= X86Reg_XMMREG_LAST))
  8305. {
  8306. int xmmMajor = (regVal.mRegNum - X86Reg_XMMREG_FIRST) >> 2;
  8307. int xmmMinor = (regVal.mRegNum - X86Reg_XMMREG_FIRST) & 3;
  8308. registers->mXmmRegsArray[xmmMajor].f[xmmMinor] = value.mSingle;
  8309. }
  8310. else if ((regVal.mRegNum >= X86Reg_M128_XMMREG_FIRST) && (regVal.mRegNum <= X86Reg_M128_XMMREG_LAST))
  8311. {
  8312. outError = "Cannot write directly to 128-bit XMM register, please use inner float components";
  8313. return false;
  8314. }
  8315. else if ((regVal.mRegNum >= X86Reg_FLAG_FIRST) && (regVal.mRegNum <= X86Reg_FLAG_LAST))
  8316. {
  8317. int flagBit = CPURegisters::GetFlagBitForRegister(regVal.mRegNum);
  8318. if (flagBit >= 0)
  8319. {
  8320. if (value.mBool)
  8321. registers->mIntRegs.efl |= ((uint64)1 << flagBit);
  8322. else
  8323. registers->mIntRegs.efl &= ~((uint64)1 << flagBit);
  8324. }
  8325. else
  8326. {
  8327. outError = "Unrecognized flag";
  8328. return false;
  8329. }
  8330. }
  8331. else if ((regVal.mRegNum >= X86Reg_CAT_FIRST) && (regVal.mRegNum <= X86Reg_CAT_LAST))
  8332. {
  8333. outError = "Cannot write directly to register categories, please use inner float components";
  8334. return false;
  8335. }
  8336. #else
  8337. if ((regVal.mRegNum >= X64Reg_INTREG_FIRST) && (regVal.mRegNum <= X64Reg_INTREG_LAST))
  8338. {
  8339. //BF_ASSERT(regVal.mType->mSize == sizeof(addr_target));
  8340. registers->mIntRegsArray[regVal.mRegNum - X64Reg_INTREG_FIRST] = value.GetInt64(); // don't sign-extend
  8341. regPtr = &registers->mIntRegsArray[regVal.mRegNum - X64Reg_INTREG_FIRST];
  8342. }
  8343. else if ((regVal.mRegNum >= X64Reg_FPSTREG_FIRST) && (regVal.mRegNum <= X64Reg_FPSTREG_LAST))
  8344. {
  8345. BF_ASSERT(regVal.mType->mSize == sizeof(float) || regVal.mType->mSize == sizeof(double));
  8346. CPURegisters::FpMmReg* reg = &registers->mFpMmRegsArray[regVal.mRegNum - X64Reg_FPSTREG_FIRST];
  8347. double d;
  8348. if (regVal.mType->mSize == sizeof(float))
  8349. d = (double)value.mSingle;
  8350. else
  8351. d = value.mDouble;
  8352. ConvertDoubleToFloat80(d, reg->fp.fp80);
  8353. regPtr = reg;
  8354. }
  8355. else if ((regVal.mRegNum >= X64Reg_MMREG_FIRST) && (regVal.mRegNum <= X64Reg_MMREG_LAST))
  8356. {
  8357. BF_ASSERT(regVal.mType->mSize == sizeof(int32) || regVal.mType->mSize == sizeof(int64));
  8358. CPURegisters::FpMmReg* reg = &registers->mFpMmRegsArray[regVal.mRegNum - X64Reg_MMREG_FIRST];
  8359. if (regVal.mType->mSize == sizeof(int32))
  8360. reg->mm = (uint64)value.mUInt32; // don't sign-extend
  8361. else if (regVal.mType->mSize == sizeof(int64))
  8362. reg->mm = value.mInt64;
  8363. // whenever we use the low 64 bits of the reg as mm, the upper 16 bits of the 80-bit float must be set to all-1s to indicate NaN
  8364. reg->fp.fp80[8] = reg->fp.fp80[9] = 0xFF;
  8365. regPtr = reg;
  8366. }
  8367. else if ((regVal.mRegNum >= X64Reg_XMMREG_FIRST) && (regVal.mRegNum <= X64Reg_XMMREG_LAST))
  8368. {
  8369. int xmmMajor = (regVal.mRegNum - X64Reg_XMMREG_FIRST) >> 2;
  8370. int xmmMinor = (regVal.mRegNum - X64Reg_XMMREG_FIRST) & 3;
  8371. if (value.mType->GetByteCount() == 4)
  8372. registers->mXmmRegsArray[xmmMajor].f[xmmMinor] = value.mSingle;
  8373. else if (value.mType->GetByteCount() == 8)
  8374. registers->mXmmDRegsArray[xmmMajor].d[xmmMinor] = value.mDouble;
  8375. else
  8376. BF_FATAL("Invalid XMM set value type");
  8377. regPtr = &registers->mXmmRegsArray[xmmMajor];
  8378. }
  8379. else if ((regVal.mRegNum >= X64Reg_M128_XMMREG_FIRST) && (regVal.mRegNum <= X64Reg_M128_XMMREG_LAST))
  8380. {
  8381. outError = "Cannot write directly to 128-bit XMM register, please use inner float components";
  8382. return false;
  8383. }
  8384. else if ((regVal.mRegNum >= X64Reg_FLAG_FIRST) && (regVal.mRegNum <= X64Reg_FLAG_LAST))
  8385. {
  8386. int flagBit = CPURegisters::GetFlagBitForRegister(regVal.mRegNum);
  8387. if (flagBit >= 0)
  8388. {
  8389. if (value.mBool)
  8390. registers->mIntRegs.efl |= ((uint64)1 << flagBit);
  8391. else
  8392. registers->mIntRegs.efl &= ~((uint64)1 << flagBit);
  8393. regPtr = &registers->mIntRegs.efl;
  8394. }
  8395. else
  8396. {
  8397. outError = "Unrecognized flag";
  8398. return false;
  8399. }
  8400. }
  8401. else if ((regVal.mRegNum >= X64Reg_CAT_FIRST) && (regVal.mRegNum <= X64Reg_CAT_LAST))
  8402. {
  8403. outError = "Cannot write directly to register categories, please use inner float components";
  8404. return false;
  8405. }
  8406. else
  8407. BF_FATAL("Not implemented");
  8408. #endif
  8409. if (callStackIdx == 0)
  8410. {
  8411. SetRegisters(&mCallStack[0]->mRegisters);
  8412. return true;
  8413. }
  8414. else
  8415. {
  8416. bool wasSaved = false;
  8417. for (int calleeStackIdx = callStackIdx - 1; calleeStackIdx >= 0; calleeStackIdx--)
  8418. {
  8419. auto calleeRegisters = &mCallStack[calleeStackIdx]->mRegisters;
  8420. if (!mDebugTarget->PropogateRegisterUpCallStack(registers, calleeRegisters, regPtr, wasSaved))
  8421. {
  8422. outError = "Failed to set register";
  8423. return false;
  8424. }
  8425. if (wasSaved)
  8426. return true;
  8427. }
  8428. // This register wasn't saved, so commit it to the callstack top
  8429. return AssignToReg(0, regVal, value, outError);
  8430. }
  8431. }
  8432. String WinDebugger::GetAutocompleteOutput(DwAutoComplete& autoComplete)
  8433. {
  8434. String val = "\n:autocomplete\n";
  8435. if (autoComplete.mInsertStartIdx != -1)
  8436. {
  8437. val += StrFormat("insertRange\t%d %d\n", autoComplete.mInsertStartIdx, autoComplete.mInsertEndIdx);
  8438. }
  8439. Array<AutoCompleteEntry*> entries;
  8440. for (auto& entry : autoComplete.mEntriesSet)
  8441. {
  8442. entries.Add(&entry);
  8443. }
  8444. std::sort(entries.begin(), entries.end(), [](AutoCompleteEntry* lhs, AutoCompleteEntry* rhs)
  8445. {
  8446. return stricmp(lhs->mDisplay, rhs->mDisplay) < 0;
  8447. });
  8448. for (auto entry : entries)
  8449. {
  8450. val += String(entry->mEntryType);
  8451. val += "\t";
  8452. val += String(entry->mDisplay);
  8453. val += "\n";
  8454. }
  8455. /*if (autoComplete.mEntries.size() != 0)
  8456. {
  8457. for (auto& entry : autoComplete.mEntries)
  8458. {
  8459. val += String(entry.mEntryType) + "\t" + String(entry.mDisplay) + "\n";
  8460. }
  8461. }*/
  8462. return val;
  8463. }
  8464. String WinDebugger::EvaluateToAddress(const StringImpl& expr, int callStackIdx, int cursorPos)
  8465. {
  8466. AutoCrit autoCrit(mDebugManager->mCritSect);
  8467. if (IsInRunState())
  8468. return "!Target not paused";
  8469. auto dbgModule = GetCallStackDbgModule(callStackIdx);
  8470. auto dbgCompileUnit = GetCallStackCompileUnit(callStackIdx);
  8471. BfParser parser(mBfSystem);
  8472. parser.mCompatMode = true;
  8473. BfPassInstance bfPassInstance(mBfSystem);
  8474. auto terminatedExpr = expr + ";";
  8475. parser.SetSource(terminatedExpr.c_str(), terminatedExpr.length());
  8476. parser.Parse(&bfPassInstance);
  8477. BfReducer bfReducer;
  8478. bfReducer.mAlloc = parser.mAlloc;
  8479. bfReducer.mSystem = mBfSystem;
  8480. bfReducer.mPassInstance = &bfPassInstance;
  8481. bfReducer.mVisitorPos = BfReducer::BfVisitorPos(parser.mRootNode);
  8482. bfReducer.mVisitorPos.MoveNext();
  8483. bfReducer.mSource = &parser;
  8484. auto exprNode = bfReducer.CreateExpression(parser.mRootNode->GetFirst());
  8485. parser.Close();
  8486. DwAutoComplete autoComplete;
  8487. DbgExprEvaluator dbgExprEvaluator(this, dbgModule, &bfPassInstance, callStackIdx, cursorPos);
  8488. if (cursorPos != -1)
  8489. dbgExprEvaluator.mAutoComplete = &autoComplete;
  8490. dbgExprEvaluator.mDbgCompileUnit = dbgCompileUnit;
  8491. DwFormatInfo formatInfo;
  8492. formatInfo.mCallStackIdx = callStackIdx;
  8493. DbgTypedValue exprResult;
  8494. if (exprNode != NULL)
  8495. exprResult = dbgExprEvaluator.Resolve(exprNode);
  8496. DbgType* resultType = exprResult.mType->RemoveModifiers();
  8497. String val;
  8498. if (bfPassInstance.HasFailed())
  8499. {
  8500. val = StrFormat("!%d\t%d\t%s", bfPassInstance.mErrors[0]->mSrcStart, bfPassInstance.mErrors[0]->GetSrcLength(), bfPassInstance.mErrors[0]->mError.c_str());
  8501. }
  8502. else if (exprResult.mType == NULL)
  8503. {
  8504. val = "!Invalid expression";
  8505. }
  8506. else if (!resultType->IsPointerOrRef())
  8507. {
  8508. if (exprResult.mSrcAddress != 0)
  8509. val = StrFormat("!Type '%s' is invalid. A sized pointer type is expected. Try using the '&' address-of operator.", exprResult.mType->ToString().c_str());
  8510. else
  8511. val = StrFormat("!Type '%s' is invalid. A sized pointer type is expected. An explicit cast may be required.", exprResult.mType->ToString().c_str());
  8512. }
  8513. else
  8514. {
  8515. auto innerType = resultType->mTypeParam;
  8516. int byteCount = innerType->GetByteCount();
  8517. if (byteCount == 0)
  8518. {
  8519. val = StrFormat("!Type '%s' is invalid. A sized pointer type is expected, try casting to a non-void pointer type.", exprResult.mType->ToString().c_str());
  8520. }
  8521. #ifdef BF_DBG_32
  8522. else if ((byteCount != 1) && (byteCount != 2) && (byteCount != 4))
  8523. {
  8524. val = StrFormat("!Element size is %d bytes. Only 1, 2, or 4 byte elements can be tracked. Try casting to an appropriately-sized pointer.", innerType->mSize);
  8525. }
  8526. #else
  8527. else if ((byteCount != 1) && (byteCount != 2) && (byteCount != 4) && (byteCount != 8))
  8528. {
  8529. val = StrFormat("!Element size is %d bytes. Only 1, 2, 4, or 8 byte elements can be tracked. Try casting to an appropriately-sized pointer.", innerType->mSize);
  8530. }
  8531. #endif
  8532. else
  8533. {
  8534. val = EncodeDataPtr(exprResult.mPtr, false) + "\n" + StrFormat("%d", byteCount);
  8535. }
  8536. }
  8537. if (cursorPos != -1)
  8538. val += GetAutocompleteOutput(autoComplete);
  8539. return val;
  8540. }
  8541. // This is currently only used for autocomplete during conditional breakpoint expression entry.
  8542. // If we want to use it for more than that then remove DwEvalExpressionFlags_ValidateOnly
  8543. String WinDebugger::EvaluateAtAddress(const StringImpl& expr, intptr atAddr, int cursorPos)
  8544. {
  8545. AutoCrit autoCrit(mDebugManager->mCritSect);
  8546. if (IsInRunState())
  8547. return "!Target not paused";
  8548. if (!IsPaused())
  8549. return "!Target not running";
  8550. WdStackFrame stackFrame;
  8551. memset(&stackFrame.mRegisters, 0, sizeof(stackFrame.mRegisters));
  8552. stackFrame.mHasGottenSubProgram = true;
  8553. *stackFrame.mRegisters.GetPCRegisterRef() = (intptr_target)atAddr;
  8554. stackFrame.mSubProgram = mDebugTarget->FindSubProgram((addr_target)atAddr);
  8555. if (stackFrame.mSubProgram == NULL)
  8556. return "!Invalid address";
  8557. mCallStack.push_back(&stackFrame);
  8558. int callStackIdx = (int)mCallStack.size() - 1;
  8559. String val = Evaluate(expr, callStackIdx, cursorPos, -1, DwEvalExpressionFlag_ValidateOnly);
  8560. mCallStack.pop_back();
  8561. return val;
  8562. }
  8563. String WinDebugger::GetAutoExpressions(int callStackIdx, uint64 memoryRangeStart, uint64 memoryRangeLen)
  8564. {
  8565. BP_ZONE("WinDebugger::GetAutoExpressions");
  8566. AutoCrit autoCrit(mDebugManager->mCritSect);
  8567. if (IsInRunState())
  8568. return "!Not paused";
  8569. if (!IsPaused())
  8570. return "!Not running";
  8571. if (!FixCallStackIdx(callStackIdx))
  8572. return "";
  8573. CPUStackFrame* stackFrame = (callStackIdx >= 0) ? mCallStack[callStackIdx] : mCallStack.front();
  8574. String result;
  8575. DbgAutoValueMapType dwarfAutos;
  8576. mDebugTarget->GetAutoValueNames(dwarfAutos, stackFrame, memoryRangeStart, memoryRangeLen);
  8577. for (auto const &a : dwarfAutos)
  8578. {
  8579. std::pair<uint64, uint64> varRange = a.mValue;
  8580. if (varRange.first != 0)
  8581. result += StrFormat("&%s\t%llu\t%llu\n", a.mKey.c_str(), varRange.second, varRange.first);
  8582. else
  8583. result += StrFormat("?%s\t%llu\n", a.mKey.c_str(), varRange.second);
  8584. }
  8585. #ifdef BF_DBG_64
  8586. // add int regs
  8587. const char* regStrs[] = { "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", "rip", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", 0 };
  8588. #else
  8589. // add int regs
  8590. const char* regStrs[] = { "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", "eip", 0 };
  8591. #endif
  8592. for (const char** p = regStrs; *p; ++p)
  8593. result += StrFormat("$%s\t%d\n", *p, sizeof(addr_target));
  8594. if (callStackIdx < (int)mCallStack.size() - 2)
  8595. {
  8596. WdStackFrame* prevStackFrame = mCallStack[callStackIdx + 1];
  8597. // Inlined methods have no stack frame
  8598. int stackSize = prevStackFrame->mRegisters.GetSP() - stackFrame->mRegisters.GetSP();
  8599. result += StrFormat("&$StackFrame\t%llu\t%llu\n", stackSize, stackFrame->mRegisters.GetSP());
  8600. }
  8601. return result;
  8602. }
  8603. String WinDebugger::GetAutoLocals(int stackFrameIdx, bool showRegs)
  8604. {
  8605. BP_ZONE("WinDebugger::GetAutoExpressions");
  8606. AutoCrit autoCrit(mDebugManager->mCritSect);
  8607. if (IsInRunState())
  8608. return "";
  8609. if (!IsPaused())
  8610. return "";
  8611. if (mCallStack.size() == 0)
  8612. UpdateCallStack();
  8613. String result;
  8614. Array<String> localList;
  8615. int actualStackFrameIdx = BF_MAX(0, stackFrameIdx);
  8616. UpdateCallStackMethod(actualStackFrameIdx);
  8617. if (actualStackFrameIdx >= mCallStack.size())
  8618. return "";
  8619. WdStackFrame* wdStackFrame = mCallStack[actualStackFrameIdx];
  8620. DbgSubprogram* dwSubprogram = wdStackFrame->mSubProgram;
  8621. if (dwSubprogram == NULL)
  8622. return "";
  8623. auto langage = dwSubprogram->GetLanguage();
  8624. DbgLineData* dwLineData = FindLineDataInSubprogram(wdStackFrame->GetSourcePC(), dwSubprogram);
  8625. if (dwLineData == NULL)
  8626. return "";
  8627. dwSubprogram->PopulateSubprogram();
  8628. mDebugTarget->GetAutoLocalsInBlock(localList, dwSubprogram, &dwSubprogram->mBlock, wdStackFrame, dwLineData);
  8629. String lastLocal;
  8630. for (auto local : localList)
  8631. {
  8632. if (langage == DbgLanguage_C)
  8633. {
  8634. if ((local == "this") && (strncmp(dwSubprogram->mName, "<lambda_", 8) == 0))
  8635. {
  8636. // Use explicit "$this" so we can see the actual capture
  8637. result += "$this\n";
  8638. continue;
  8639. }
  8640. }
  8641. bool wasAlias = false;
  8642. for (int i = 0; i < (int)local.length() - 1; i++)
  8643. {
  8644. if ((local[i] == '$') && (local[i + 1] == 'a'))
  8645. {
  8646. // Alias
  8647. wasAlias = true;
  8648. String localName = local.Substring(0, i) + "\n";
  8649. if (localName != lastLocal)
  8650. {
  8651. result += localName;
  8652. lastLocal = localName;
  8653. }
  8654. break;
  8655. }
  8656. }
  8657. if (!wasAlias)
  8658. result += local + "\n";
  8659. }
  8660. if (showRegs)
  8661. {
  8662. result += "$FLAGS\n";
  8663. UpdateRegisterUsage(stackFrameIdx);
  8664. for (int regIdx = 0; regIdx < (int)wdStackFrame->mRegForms.size(); regIdx++)
  8665. {
  8666. if (wdStackFrame->mRegForms[regIdx] != RegForm_Invalid)
  8667. result += "$" + String(CPURegisters::GetRegisterName(regIdx)) + "\n";
  8668. }
  8669. }
  8670. return result;
  8671. }
  8672. String WinDebugger::CompactChildExpression(const StringImpl& expr, const StringImpl& parentExpr, int callStackIdx)
  8673. {
  8674. DbgCompileUnit* compileUnit = GetCallStackCompileUnit(callStackIdx);
  8675. DbgModule* dbgModule = GetCallStackDbgModule(callStackIdx);
  8676. if (dbgModule == NULL)
  8677. return "!failed";
  8678. DbgLanguage language = DbgLanguage_Unknown;
  8679. if (compileUnit != NULL)
  8680. language = compileUnit->mLanguage;
  8681. BfPassInstance bfPassInstance(mBfSystem);
  8682. BfParser parser(mBfSystem);
  8683. parser.mCompatMode = language != DbgLanguage_Beef;
  8684. auto terminatedExpr = expr + ";";
  8685. parser.SetSource(terminatedExpr.c_str(), terminatedExpr.length());
  8686. parser.Parse(&bfPassInstance);
  8687. BfParser parentParser(mBfSystem);
  8688. auto terminatedParentExpr = parentExpr + ";";
  8689. parentParser.mCompatMode = language != DbgLanguage_Beef;
  8690. parentParser.SetSource(terminatedParentExpr.c_str(), terminatedParentExpr.length());
  8691. parentParser.Parse(&bfPassInstance);
  8692. BfReducer bfReducer;
  8693. bfReducer.mCompatMode = true;
  8694. bfReducer.mAlloc = parser.mAlloc;
  8695. bfReducer.mSystem = mBfSystem;
  8696. bfReducer.mPassInstance = &bfPassInstance;
  8697. bfReducer.mVisitorPos = BfReducer::BfVisitorPos(parser.mRootNode);
  8698. bfReducer.mVisitorPos.MoveNext();
  8699. bfReducer.mSource = &parser;
  8700. auto exprNode = bfReducer.CreateExpression(parser.mRootNode->GetFirst());
  8701. bfReducer.mAlloc = parentParser.mAlloc;
  8702. bfReducer.mVisitorPos = BfReducer::BfVisitorPos(parentParser.mRootNode);
  8703. bfReducer.mVisitorPos.MoveNext();
  8704. auto parentExprNode = bfReducer.CreateExpression(parentParser.mRootNode->GetFirst());
  8705. parser.Close();
  8706. if ((exprNode == NULL) || (parentExprNode == NULL))
  8707. return "!failed";
  8708. DbgExprEvaluator dbgExprEvaluator(this, dbgModule, &bfPassInstance, callStackIdx, -1);
  8709. DwFormatInfo formatInfo;
  8710. formatInfo.mCallStackIdx = callStackIdx;
  8711. String formatFlags;
  8712. String assignExpr;
  8713. if ((exprNode != NULL) && (exprNode->GetSrcEnd() < (int) expr.length()))
  8714. {
  8715. formatFlags = Trim(expr.Substring(exprNode->GetSrcEnd()));
  8716. if (formatFlags.length() > 0)
  8717. {
  8718. String errorString = "Invalid expression";
  8719. if (!ParseFormatInfo(dbgModule, formatFlags, &formatInfo, &bfPassInstance, NULL, &assignExpr, &errorString))
  8720. {
  8721. bfPassInstance.FailAt(errorString, parser.mSourceData, exprNode->GetSrcEnd(), (int) expr.length() - exprNode->GetSrcEnd());
  8722. formatFlags = "";
  8723. }
  8724. }
  8725. }
  8726. dbgExprEvaluator.mExplicitThis = formatInfo.mExplicitThis;
  8727. dbgExprEvaluator.mExplicitThisExpr = parentExprNode;
  8728. DbgTypedValue exprResult = dbgExprEvaluator.Resolve(exprNode);
  8729. BfAstNode* headNode = dbgExprEvaluator.FinalizeExplicitThisReferences(exprNode);
  8730. BfPrinter printer(parser.mRootNode, NULL, NULL);
  8731. printer.mIgnoreTrivia = true;
  8732. printer.mReformatting = true;
  8733. printer.VisitChild(headNode);
  8734. auto result = printer.mOutString;
  8735. if (formatInfo.mNoVisualizers)
  8736. result += ", nv";
  8737. if (formatInfo.mNoMembers)
  8738. result += ", nm";
  8739. if (formatInfo.mNoEdit)
  8740. result += ", ne";
  8741. if (formatInfo.mIgnoreDerivedClassInfo)
  8742. result += ", nd";
  8743. if (formatInfo.mDisplayType == DwDisplayType_Ascii)
  8744. result += ", s";
  8745. if (formatInfo.mDisplayType == DwDisplayType_Utf8)
  8746. result += ", s8";
  8747. if (formatInfo.mDisplayType == DwDisplayType_Utf16)
  8748. result += ", s16";
  8749. if (formatInfo.mDisplayType == DwDisplayType_Utf32)
  8750. result += ", s32";
  8751. return result;
  8752. }
  8753. String WinDebugger::GetThreadInfo()
  8754. {
  8755. AutoCrit autoCrit(mDebugManager->mCritSect);
  8756. String retStr;
  8757. if ((mActiveThread == NULL) && (!mIsRunning))
  8758. {
  8759. retStr = "";
  8760. }
  8761. else
  8762. {
  8763. if (mActiveThread != NULL)
  8764. retStr = StrFormat("%d", mActiveThread->mThreadId);
  8765. for (auto threadInfo : mThreadList)
  8766. {
  8767. SetAndRestoreValue<WdThreadInfo*> prevThread(mActiveThread, threadInfo);
  8768. retStr += "\n";
  8769. for (int pass = 0; pass < 2; pass++)
  8770. {
  8771. CPURegisters registers;
  8772. PopulateRegisters(&registers);
  8773. String locString = EncodeDataPtr((addr_target)registers.GetPC(), true);
  8774. TryGetThreadName(threadInfo);
  8775. bool hadThreadName = true;
  8776. String threadName = threadInfo->mName;
  8777. if (threadName.IsEmpty())
  8778. {
  8779. hadThreadName = false;
  8780. if (threadInfo->mThreadId == mProcessInfo.dwThreadId)
  8781. threadName = "Main Thread";
  8782. else
  8783. threadName = "Worker Thread";
  8784. }
  8785. bool isInvalid = false;
  8786. addr_target appendAddr = 0;
  8787. for (int stackIdx = 0; true; stackIdx++)
  8788. {
  8789. auto subProgram = mDebugTarget->FindSubProgram(registers.GetPC(), DbgOnDemandKind_LocalOnly);
  8790. if (subProgram != NULL)
  8791. {
  8792. if (subProgram->mLineInfo != NULL)
  8793. {
  8794. auto module = subProgram->mCompileUnit->mDbgModule;
  8795. if (module->mDisplayName.length() > 0)
  8796. {
  8797. locString = module->mDisplayName + "!" + subProgram->ToString();
  8798. if (!hadThreadName)
  8799. threadName = module->mDisplayName + " thread";
  8800. }
  8801. else
  8802. {
  8803. locString = subProgram->ToString();
  8804. }
  8805. appendAddr = 0;
  8806. break;
  8807. }
  8808. }
  8809. auto module = mDebugTarget->FindDbgModuleForAddress(registers.GetPC());
  8810. if (module == NULL)
  8811. {
  8812. isInvalid = true;
  8813. break;
  8814. }
  8815. appendAddr = (addr_target)registers.GetPC();
  8816. locString = module->mDisplayName + "!" + EncodeDataPtr((addr_target)registers.GetPC(), true);
  8817. if (!hadThreadName)
  8818. threadName = module->mDisplayName + " thread";
  8819. if ((mActiveThread == mExplicitStopThread) && (mActiveBreakpoint != NULL))
  8820. {
  8821. if ((mActiveBreakpoint->mAddr < subProgram->mBlock.mLowPC) ||
  8822. (mActiveBreakpoint->mAddr >= subProgram->mBlock.mHighPC))
  8823. break;
  8824. }
  8825. if (pass == 1) // Just take the first item
  8826. break;
  8827. if (stackIdx == 128)
  8828. break; // Too many!
  8829. // if ((ToLower(module->mDisplayName) != "ntdll.dll") && (ToLower(module->mDisplayName) != "kernel32.dll") && (ToLower(module->mDisplayName) != "kernelbase.dll"))
  8830. // break;
  8831. addr_target returnAddr;
  8832. if (!mDebugTarget->RollBackStackFrame(&registers, &returnAddr, true))
  8833. {
  8834. isInvalid = true;
  8835. break;
  8836. }
  8837. }
  8838. if ((isInvalid) && (pass == 0))
  8839. continue;
  8840. if (appendAddr != 0)
  8841. {
  8842. String symbolName;
  8843. addr_target offset;
  8844. DbgModule* dwarf;
  8845. if (mDebugTarget->FindSymbolAt(appendAddr, &symbolName, &offset, &dwarf))
  8846. {
  8847. String demangledName = BfDemangler::Demangle(symbolName, DbgLanguage_Unknown);
  8848. if (!dwarf->mDisplayName.empty())
  8849. demangledName = dwarf->mDisplayName + "!" + demangledName;
  8850. locString = demangledName + StrFormat("+0x%X", offset);
  8851. }
  8852. }
  8853. retStr += StrFormat("%d\t%s\t%s", threadInfo->mThreadId, threadName.c_str(), locString.c_str());
  8854. String attrs;
  8855. if (threadInfo->mFrozen)
  8856. {
  8857. attrs += "Fr";
  8858. }
  8859. if (!attrs.IsEmpty())
  8860. {
  8861. retStr += "\t";
  8862. retStr += attrs;
  8863. }
  8864. break;
  8865. }
  8866. }
  8867. }
  8868. return retStr;
  8869. }
  8870. void WinDebugger::SetActiveThread(int threadId)
  8871. {
  8872. AutoCrit autoCrit(mDebugManager->mCritSect);
  8873. if (mThreadMap.TryGetValue(threadId, &mActiveThread))
  8874. {
  8875. BfLogDbg("SetActiveThread %d\n", threadId);
  8876. ClearCallStack();
  8877. }
  8878. else
  8879. {
  8880. BfLogDbg("SetActiveThread %d FAILED\n", threadId);
  8881. }
  8882. }
  8883. int WinDebugger::GetActiveThread()
  8884. {
  8885. AutoCrit autoCrit(mDebugManager->mCritSect);
  8886. if (mActiveThread == NULL)
  8887. return -1;
  8888. return mActiveThread->mThreadId;
  8889. }
  8890. void WinDebugger::FreezeThread(int threadId)
  8891. {
  8892. AutoCrit autoCrit(mDebugManager->mCritSect);
  8893. BF_ASSERT(!IsInRunState());
  8894. auto thread = mThreadMap[threadId];
  8895. if (!thread->mFrozen)
  8896. {
  8897. thread->mFrozen = true;
  8898. ::SuspendThread(thread->mHThread);
  8899. BfLogDbg("SuspendThread %d from FreezeThread\n", thread->mThreadId);
  8900. }
  8901. }
  8902. void WinDebugger::ThawThread(int threadId)
  8903. {
  8904. AutoCrit autoCrit(mDebugManager->mCritSect);
  8905. BF_ASSERT(!IsInRunState());
  8906. auto thread = mThreadMap[threadId];
  8907. if (thread->mFrozen)
  8908. {
  8909. thread->mFrozen = false;
  8910. ::ResumeThread(thread->mHThread);
  8911. BfLogDbg("ResumeThread %d from ThawThread\n", thread->mThreadId);
  8912. }
  8913. }
  8914. bool WinDebugger::IsActiveThreadWaiting()
  8915. {
  8916. AutoCrit autoCrit(mDebugManager->mCritSect);
  8917. return mActiveThread == mDebuggerWaitingThread;
  8918. }
  8919. void WinDebugger::ClearCallStack()
  8920. {
  8921. AutoCrit autoCrit(mDebugManager->mCritSect);
  8922. BfLogDbg("ClearCallstack\n");
  8923. BF_ASSERT(mRunState != RunState_DebugEval);
  8924. for (auto wdStackFrame : mCallStack)
  8925. delete wdStackFrame;
  8926. mCallStack.Clear();
  8927. mIsPartialCallStack = true;
  8928. }
  8929. void WinDebugger::UpdateCallStack(bool slowEarlyOut)
  8930. {
  8931. AutoCrit autoCrit(mDebugManager->mCritSect);
  8932. if (!mIsPartialCallStack)
  8933. return;
  8934. BF_ASSERT(!IsInRunState());
  8935. uint32 tickStart = BFTickCount();
  8936. CPURegisters registers;
  8937. if (mCallStack.size() > 0)
  8938. {
  8939. WdStackFrame* wdStackFrame = mCallStack.back();
  8940. if (wdStackFrame->mIsEnd)
  8941. {
  8942. return;
  8943. }
  8944. memcpy(&registers, &wdStackFrame->mRegisters, sizeof(registers));
  8945. bool regsRolledBack = RollBackStackFrame(&registers, mCallStack.size() == 1);
  8946. // If we can't roll them back then mIsEnd should have been set for the previous frame
  8947. BF_ASSERT(regsRolledBack);
  8948. }
  8949. else
  8950. {
  8951. BF_ASSERT(mIsPartialCallStack);
  8952. mCallStack.Reserve(1024);
  8953. PopulateRegisters(&registers);
  8954. BfLogDbg("UpdateCallStack starting. Thread=%d PC=0x%p\n", mActiveThread->mThreadId, registers.GetPC());
  8955. }
  8956. bool isPartial = false;
  8957. // Incrementally fill callstack structure to avoid stepping slowdown during deep nesting
  8958. for (int fillIdx = 0; fillIdx < (slowEarlyOut ? 10000 : 100000); fillIdx++)
  8959. {
  8960. WdStackFrame* wdStackFrame = new WdStackFrame();
  8961. memcpy(&wdStackFrame->mRegisters, &registers, sizeof(registers));
  8962. wdStackFrame->mIsStart = mCallStack.size() == 0;
  8963. wdStackFrame->mIsEnd = false;
  8964. bool rollbackSuccess = false;
  8965. for (int tryCount = 0; tryCount < 16; tryCount++)
  8966. {
  8967. if (!RollBackStackFrame(&registers, wdStackFrame->mIsStart))
  8968. {
  8969. break;
  8970. }
  8971. if (registers.GetPC() > 0xFFFF)
  8972. {
  8973. rollbackSuccess = true;
  8974. break;
  8975. }
  8976. if (mCallStack.size() > 0)
  8977. break; // Only retry for the first frame
  8978. }
  8979. if (!rollbackSuccess)
  8980. wdStackFrame->mIsEnd = true;
  8981. if (registers.GetSP() <= wdStackFrame->mRegisters.GetSP())
  8982. {
  8983. // SP went the wrong direction, stop rolling back
  8984. wdStackFrame->mIsEnd = true;
  8985. }
  8986. mCallStack.push_back(wdStackFrame);
  8987. if (IsMiniDumpDebugger())
  8988. {
  8989. // Make sure to queue up any debug stuff we need
  8990. UpdateCallStackMethod((int)mCallStack.size() - 1);
  8991. }
  8992. if (wdStackFrame->mIsEnd)
  8993. break;
  8994. // Time-limit callstack generation. Most useful for debug mode.
  8995. if ((slowEarlyOut) && ((fillIdx % 100) == 0))
  8996. {
  8997. uint32 tickEnd = BFTickCount();
  8998. if (tickEnd - tickStart >= 10)
  8999. {
  9000. isPartial = true;
  9001. break;
  9002. }
  9003. }
  9004. }
  9005. if (!isPartial)
  9006. mIsPartialCallStack = false;
  9007. }
  9008. int WinDebugger::GetCallStackCount()
  9009. {
  9010. AutoCrit autoCrit(mDebugManager->mCritSect);
  9011. return (int)mCallStack.size();
  9012. }
  9013. int WinDebugger::GetRequestedStackFrameIdx()
  9014. {
  9015. AutoCrit autoCrit(mDebugManager->mCritSect);
  9016. if ((mActiveThread == mExplicitStopThread) && (mRequestedStackFrameIdx >= -1))
  9017. {
  9018. if (mActiveBreakpoint != NULL)
  9019. mRequestedStackFrameIdx = GetBreakStackFrameIdx();
  9020. if (mRequestedStackFrameIdx == -1)
  9021. mRequestedStackFrameIdx = 0;
  9022. return mRequestedStackFrameIdx;
  9023. }
  9024. int newCallStackIdx = 0;
  9025. while (true)
  9026. {
  9027. if (newCallStackIdx >= (int)mCallStack.size() - 1)
  9028. UpdateCallStack();
  9029. if (newCallStackIdx >= (int)mCallStack.size() - 1)
  9030. break;
  9031. intptr addr;
  9032. String file;
  9033. int hotIdx;
  9034. int defLineStart;
  9035. int defLineEnd;
  9036. int line;
  9037. int column;
  9038. int language;
  9039. int stackSize;
  9040. int8 flags;
  9041. GetStackFrameInfo(newCallStackIdx, &addr, &file, &hotIdx, &defLineStart, &defLineEnd, &line, &column, &language, &stackSize, &flags);
  9042. if (!file.empty())
  9043. return newCallStackIdx;
  9044. newCallStackIdx++;
  9045. }
  9046. return 0;
  9047. }
  9048. int WinDebugger::GetBreakStackFrameIdx()
  9049. {
  9050. AutoCrit autoCrit(mDebugManager->mCritSect);
  9051. if ((mActiveBreakpoint == NULL) || (mRunState != RunState_Breakpoint))
  9052. return -1;
  9053. if ((mBreakStackFrameIdx != -1) || (mActiveThread != mExplicitStopThread))
  9054. return mBreakStackFrameIdx;
  9055. mBreakStackFrameIdx = 0;
  9056. BF_ASSERT(mActiveBreakpoint != NULL);
  9057. if (mCallStack.IsEmpty())
  9058. UpdateCallStack();
  9059. if (!mCallStack.IsEmpty())
  9060. {
  9061. UpdateCallStackMethod(0);
  9062. for (int stackIdx = 0; stackIdx < (int)mCallStack.size(); stackIdx++)
  9063. {
  9064. auto callStackEntry = mCallStack[stackIdx];
  9065. if (callStackEntry->mSubProgram == NULL)
  9066. break;
  9067. if ((mActiveBreakpoint->mAddr < callStackEntry->mSubProgram->mBlock.mLowPC) ||
  9068. (mActiveBreakpoint->mAddr >= callStackEntry->mSubProgram->mBlock.mHighPC))
  9069. break;
  9070. DbgSubprogram* specificSubprogram = callStackEntry->mSubProgram;
  9071. auto dwLineData = callStackEntry->mSubProgram->FindClosestLine(mActiveBreakpoint->mAddr, &specificSubprogram);
  9072. if (dwLineData == NULL)
  9073. break;
  9074. if (mActiveBreakpoint->mLineData == dwLineData)
  9075. {
  9076. mBreakStackFrameIdx = stackIdx;
  9077. break;
  9078. }
  9079. }
  9080. }
  9081. return mBreakStackFrameIdx;
  9082. }
  9083. static const char* SafeString(const char* str)
  9084. {
  9085. if (str == NULL)
  9086. return "???";
  9087. return str;
  9088. }
  9089. void WinDebugger::UpdateRegisterUsage(int stackFrameIdx)
  9090. {
  9091. WdStackFrame* wdStackFrame = mCallStack[stackFrameIdx];
  9092. if (wdStackFrame->mRegForms.size() != 0)
  9093. return;
  9094. auto dwSubprogram = wdStackFrame->mSubProgram;
  9095. if (dwSubprogram == NULL)
  9096. return;
  9097. addr_target addr = dwSubprogram->mBlock.mLowPC;
  9098. const uint8* baseOp = nullptr;
  9099. while (addr < dwSubprogram->mBlock.mHighPC)
  9100. {
  9101. CPUInst inst;
  9102. if (!mDebugTarget->DecodeInstruction(addr, &inst))
  9103. break;
  9104. bool overrideForm = inst.mAddress <= (addr_target)wdStackFrame->mRegisters.GetPC();
  9105. inst.MarkRegsUsed(wdStackFrame->mRegForms, overrideForm);
  9106. addr += inst.GetLength();
  9107. }
  9108. }
  9109. // It's safe to pass an invalid idx in here
  9110. void WinDebugger::UpdateCallStackMethod(int stackFrameIdx)
  9111. {
  9112. if (mCallStack.empty())
  9113. return;
  9114. int startIdx = std::min(stackFrameIdx, (int)mCallStack.size() - 1);
  9115. while (startIdx >= 0)
  9116. {
  9117. WdStackFrame* wdStackFrame = mCallStack[startIdx];
  9118. if (wdStackFrame->mHasGottenSubProgram)
  9119. break;
  9120. startIdx--;
  9121. }
  9122. startIdx++;
  9123. for (int checkFrameIdx = startIdx; checkFrameIdx <= stackFrameIdx; checkFrameIdx++)
  9124. {
  9125. //BF_ASSERT(checkFrameIdx < mCallStack.size());
  9126. if (checkFrameIdx >= mCallStack.size())
  9127. break;
  9128. WdStackFrame* wdStackFrame = mCallStack[checkFrameIdx];
  9129. wdStackFrame->mHasGottenSubProgram = true;
  9130. addr_target pcAddress = (addr_target)wdStackFrame->GetSourcePC();
  9131. DbgSubprogram* dwSubprogram = mDebugTarget->FindSubProgram(pcAddress, DbgOnDemandKind_LocalOnly);
  9132. wdStackFrame->mHasGottenSubProgram = true;
  9133. wdStackFrame->mSubProgram = dwSubprogram;
  9134. if ((dwSubprogram == NULL) && (IsMiniDumpDebugger()))
  9135. {
  9136. // FindSymbolAt will queue up debug info if necessary...
  9137. String symbolName;
  9138. addr_target offset;
  9139. DbgModule* dbgModule;
  9140. mDebugTarget->FindSymbolAt(pcAddress, &symbolName, &offset, &dbgModule);
  9141. }
  9142. // Insert inlines
  9143. int insertIdx = checkFrameIdx + 1;
  9144. while ((dwSubprogram != NULL) && (dwSubprogram->mInlineeInfo != NULL))
  9145. {
  9146. WdStackFrame* inlineStackFrame = new WdStackFrame();
  9147. *inlineStackFrame = *wdStackFrame;
  9148. inlineStackFrame->mInInlineMethod = true;
  9149. wdStackFrame->mInInlineCall = true;
  9150. inlineStackFrame->mSubProgram = dwSubprogram->mInlineeInfo->mInlineParent;
  9151. mCallStack.Insert(insertIdx, inlineStackFrame);
  9152. dwSubprogram = dwSubprogram->mInlineeInfo->mInlineParent;
  9153. insertIdx++;
  9154. checkFrameIdx++;
  9155. }
  9156. }
  9157. }
  9158. void WinDebugger::GetCodeAddrInfo(intptr addr, String* outFile, int* outHotIdx, int* outDefLineStart, int* outDefLineEnd, int* outLine, int* outColumn)
  9159. {
  9160. AutoCrit autoCrit(mDebugManager->mCritSect);
  9161. DbgSubprogram* subProgram = NULL;
  9162. DbgLineData* callingLineData = FindLineDataAtAddress((addr_target)addr, &subProgram);
  9163. if (subProgram != NULL)
  9164. {
  9165. *outHotIdx = subProgram->mCompileUnit->mDbgModule->mHotIdx;
  9166. *outFile = subProgram->GetLineSrcFile(*callingLineData)->GetLocalPath();
  9167. *outLine = callingLineData->mLine;
  9168. *outColumn = callingLineData->mColumn;
  9169. FixupLineDataForSubprogram(subProgram);
  9170. DbgLineData* dwStartLineData = NULL;
  9171. DbgLineData* dwEndLineData = NULL;
  9172. if (subProgram->mLineInfo != NULL)
  9173. {
  9174. if (subProgram->mLineInfo->mLines.size() > 0)
  9175. {
  9176. dwStartLineData = &subProgram->mLineInfo->mLines[0];
  9177. dwEndLineData = &subProgram->mLineInfo->mLines.back();
  9178. }
  9179. }
  9180. else
  9181. {
  9182. if (subProgram->mInlineeInfo != NULL)
  9183. {
  9184. dwStartLineData = &subProgram->mInlineeInfo->mFirstLineData;
  9185. dwEndLineData = &subProgram->mInlineeInfo->mLastLineData;
  9186. }
  9187. }
  9188. if (dwEndLineData != NULL)
  9189. {
  9190. if (subProgram->mDeclLine != 0)
  9191. *outDefLineStart = subProgram->mDeclLine - 1;
  9192. else
  9193. *outDefLineStart = dwStartLineData->mLine;
  9194. *outDefLineEnd = dwEndLineData->mLine;
  9195. }
  9196. }
  9197. }
  9198. void WinDebugger::GetStackAllocInfo(intptr addr, int* outThreadId, int* outStackIdx)
  9199. {
  9200. AutoCrit autoCrit(mDebugManager->mCritSect);
  9201. *outThreadId = 0;
  9202. if (outStackIdx != NULL)
  9203. *outStackIdx = -1;
  9204. if (!IsPaused())
  9205. return;
  9206. for (auto thread : mThreadList)
  9207. {
  9208. NT_TIB64 tib = { 0 };
  9209. if (!ReadMemory((intptr)thread->mThreadLocalBase, sizeof(tib), &tib))
  9210. continue;
  9211. MEMORY_BASIC_INFORMATION stackInfo = { 0 };
  9212. if (VirtualQueryEx(mProcessInfo.hProcess, (void*)(tib.StackBase - 1), &stackInfo, sizeof(MEMORY_BASIC_INFORMATION)) == 0)
  9213. continue;
  9214. if ((addr >= (intptr)stackInfo.AllocationBase) && (addr < (intptr)tib.StackBase))
  9215. {
  9216. *outThreadId = thread->mThreadId;
  9217. if (outStackIdx == NULL)
  9218. return;
  9219. if (mActiveThread == thread)
  9220. {
  9221. UpdateCallStack(false);
  9222. for (int callStackIdx = 0; callStackIdx < (int)mCallStack.size(); callStackIdx++)
  9223. {
  9224. UpdateCallStackMethod(callStackIdx);
  9225. auto stackFrame = mCallStack[callStackIdx];
  9226. if (addr >= (intptr)stackFrame->mRegisters.GetSP())
  9227. {
  9228. *outStackIdx = callStackIdx;
  9229. }
  9230. }
  9231. }
  9232. return;
  9233. }
  9234. }
  9235. }
  9236. String WinDebugger::GetStackFrameInfo(int stackFrameIdx, intptr* addr, String* outFile, int* outHotIdx, int* outDefLineStart, int* outDefLineEnd,
  9237. int* outLine, int* outColumn, int* outLanguage, int* outStackSize, int8* outFlags)
  9238. {
  9239. enum FrameFlags
  9240. {
  9241. FrameFlags_Optimized = 1,
  9242. FrameFlags_HasPendingDebugInfo = 2,
  9243. FrameFlags_CanGetOldSource = 4,
  9244. FrameFlags_WasHotReplaced = 8,
  9245. };
  9246. AutoCrit autoCrit(mDebugManager->mCritSect);
  9247. if (mCallStack.size() == 0)
  9248. UpdateCallStack();
  9249. *addr = 0;
  9250. *outFile = "";
  9251. *outHotIdx = 0;
  9252. *outDefLineStart = -1;
  9253. *outDefLineEnd = -1;
  9254. *outLine = -1;
  9255. *outColumn = 0;
  9256. *outLanguage = 0;
  9257. *outStackSize = 0;
  9258. *outFlags = 0;
  9259. UpdateCallStackMethod(stackFrameIdx);
  9260. if (stackFrameIdx >= mCallStack.size())
  9261. {
  9262. return "";
  9263. }
  9264. int actualStackFrameIdx = BF_MAX(0, stackFrameIdx);
  9265. UpdateCallStackMethod(actualStackFrameIdx);
  9266. WdStackFrame* wdStackFrame = mCallStack[actualStackFrameIdx];
  9267. addr_target pcAddress = (addr_target)wdStackFrame->mRegisters.GetPC();
  9268. if (stackFrameIdx == -1)
  9269. pcAddress = mShowPCOverride;
  9270. *addr = pcAddress;
  9271. if (actualStackFrameIdx < (int)mCallStack.size() - 2)
  9272. {
  9273. WdStackFrame* prevStackFrame = mCallStack[actualStackFrameIdx + 1];
  9274. // Inlined methods have no stack frame
  9275. *outStackSize = prevStackFrame->mRegisters.GetSP() - wdStackFrame->mRegisters.GetSP();
  9276. }
  9277. const auto& _CheckHashSrcFile = [&](String& outStr, DbgModule* dbgModule, DbgSrcFile* srcFile)
  9278. {
  9279. if (srcFile->mHashKind != DbgHashKind_None)
  9280. {
  9281. outStr += "#";
  9282. if (srcFile->mHashKind == DbgHashKind_MD5)
  9283. {
  9284. for (int i = 0; i < 16; i++)
  9285. {
  9286. outStr += StrFormat("%02X", srcFile->mHash[i]);
  9287. }
  9288. }
  9289. else
  9290. {
  9291. for (int i = 0; i < 32; i++)
  9292. {
  9293. outStr += StrFormat("%02X", srcFile->mHash[i]);
  9294. }
  9295. }
  9296. }
  9297. };
  9298. if (wdStackFrame->mInInlineMethod)
  9299. {
  9300. WdStackFrame* nextStackFrame = mCallStack[actualStackFrameIdx - 1];
  9301. auto subProgram = nextStackFrame->mSubProgram;
  9302. // int callFileIdx = subProgram->mDeclFileIdx;
  9303. // if (callFileIdx > 0)
  9304. // {
  9305. // DbgSrcFile* srcFile = subProgram->mCompileUnit->mSrcFileRefs[callFileIdx - 1].mSrcFile;
  9306. // _CheckHashSrcFile(*outFile, subProgram->mCompileUnit->mDbgModule, srcFile);
  9307. // *outFile = srcFile->GetLocalPath();
  9308. // *outLine = subProgram->mDeclLine - 1;
  9309. // }
  9310. // else
  9311. {
  9312. FixupLineDataForSubprogram(subProgram->mInlineeInfo->mRootInliner);
  9313. DbgSubprogram* parentSubprogram = subProgram->mInlineeInfo->mInlineParent; // Require it be in the inline parent
  9314. auto foundLine = parentSubprogram->FindClosestLine(subProgram->mBlock.mLowPC, &parentSubprogram);
  9315. if (foundLine != NULL)
  9316. {
  9317. auto srcFile = parentSubprogram->GetLineSrcFile(*foundLine);
  9318. *outFile = srcFile->GetLocalPath();
  9319. _CheckHashSrcFile(*outFile, subProgram->mCompileUnit->mDbgModule, srcFile);
  9320. *outLine = foundLine->mLine;
  9321. }
  9322. }
  9323. *outLanguage = subProgram->GetLanguage();
  9324. *outHotIdx = subProgram->mCompileUnit->mDbgModule->mHotIdx;
  9325. *outColumn = -1;
  9326. DbgSubprogram* callingSubProgram = NULL;
  9327. DbgLineData* callingLineData = FindLineDataAtAddress(nextStackFrame->mSubProgram->mBlock.mLowPC - 1, &callingSubProgram);
  9328. if ((callingLineData != NULL) && (callingSubProgram == wdStackFrame->mSubProgram))
  9329. {
  9330. auto callingSrcFile = callingSubProgram->GetLineSrcFile(*callingLineData);
  9331. *outLanguage = callingSubProgram->mCompileUnit->mLanguage;
  9332. auto srcFile = callingSrcFile;
  9333. *outFile = srcFile->GetLocalPath();
  9334. _CheckHashSrcFile(*outFile, subProgram->mCompileUnit->mDbgModule, srcFile);
  9335. if (*outLine == callingLineData->mLine)
  9336. *outColumn = callingLineData->mColumn;
  9337. }
  9338. String name = wdStackFrame->mSubProgram->ToString();
  9339. DbgModule* dbgModule = wdStackFrame->mSubProgram->mCompileUnit->mDbgModule;
  9340. if (!dbgModule->mDisplayName.empty())
  9341. name = dbgModule->mDisplayName + "!" + name;
  9342. return name;
  9343. }
  9344. DbgSubprogram* dwSubprogram = wdStackFrame->mSubProgram;
  9345. if (dwSubprogram != NULL)
  9346. {
  9347. if (dwSubprogram->mIsOptimized)
  9348. *outFlags |= FrameFlags_Optimized;
  9349. String demangledName;
  9350. if ((dwSubprogram->mName != NULL) && (strncmp(dwSubprogram->mName, ":Sep@", 5) == 0))
  9351. {
  9352. char* p;
  9353. auto addr = strtoll(dwSubprogram->mName + 5, &p, 16);
  9354. if (addr != 0)
  9355. {
  9356. auto parentSubprogram = mDebugTarget->FindSubProgram(addr);
  9357. if (parentSubprogram != NULL)
  9358. demangledName = parentSubprogram->ToString();
  9359. }
  9360. }
  9361. if (demangledName.IsEmpty())
  9362. demangledName = dwSubprogram->ToString();
  9363. DbgSrcFile* dwSrcFile = NULL;
  9364. DbgLineData* dwLineData = NULL;
  9365. FixupLineDataForSubprogram(dwSubprogram);
  9366. addr_target findAddress = wdStackFrame->GetSourcePC();
  9367. DbgSubprogram* specificSubprogram = dwSubprogram;
  9368. dwLineData = dwSubprogram->FindClosestLine(findAddress, &specificSubprogram);
  9369. if (dwLineData != NULL)
  9370. dwSrcFile = dwSubprogram->GetLineSrcFile(*dwLineData);
  9371. DbgLineData* dwStartLineData = NULL;
  9372. DbgLineData* dwEndLineData = NULL;
  9373. if (dwSubprogram->mLineInfo != NULL)
  9374. {
  9375. if (dwSubprogram->mLineInfo->mLines.size() > 0)
  9376. {
  9377. dwStartLineData = &dwSubprogram->mLineInfo->mLines[0];
  9378. dwEndLineData = &dwSubprogram->mLineInfo->mLines.back();
  9379. }
  9380. }
  9381. else
  9382. {
  9383. if (dwSubprogram->mInlineeInfo != NULL)
  9384. {
  9385. dwStartLineData = &dwSubprogram->mInlineeInfo->mFirstLineData;
  9386. dwEndLineData = &dwSubprogram->mInlineeInfo->mLastLineData;
  9387. }
  9388. }
  9389. DbgModule* dbgModule = dwSubprogram->mCompileUnit->mDbgModule;
  9390. if (!dbgModule->mDisplayName.empty())
  9391. demangledName = dbgModule->mDisplayName + "!" + demangledName;
  9392. if (dwSubprogram->mWasHotReplaced)
  9393. demangledName = "#" + demangledName;
  9394. if (dbgModule->HasPendingDebugInfo())
  9395. *outFlags |= FrameFlags_HasPendingDebugInfo;
  9396. if (dbgModule->CanGetOldSource())
  9397. *outFlags |= FrameFlags_CanGetOldSource;
  9398. if (dwSubprogram->mWasHotReplaced)
  9399. *outFlags |= FrameFlags_WasHotReplaced;
  9400. if ((dwLineData != NULL) && (dwSrcFile != NULL))
  9401. {
  9402. *outFile = dwSrcFile->GetLocalPath();
  9403. _CheckHashSrcFile(*outFile, dbgModule, dwSrcFile);
  9404. *outHotIdx = dbgModule->mHotIdx;
  9405. *outLine = dwLineData->mLine;
  9406. *outColumn = dwLineData->mColumn;
  9407. *outLanguage = (int)dwSubprogram->mCompileUnit->mLanguage;
  9408. if (dwEndLineData != NULL)
  9409. {
  9410. if (dwSubprogram->mDeclLine != 0)
  9411. *outDefLineStart = dwSubprogram->mDeclLine - 1;
  9412. else
  9413. *outDefLineStart = dwStartLineData->mLine;
  9414. *outDefLineEnd = dwEndLineData->mLine;
  9415. }
  9416. return demangledName;
  9417. }
  9418. else
  9419. {
  9420. return demangledName + StrFormat("+0x%X", pcAddress - dwSubprogram->mBlock.mLowPC);
  9421. }
  9422. }
  9423. else
  9424. {
  9425. String symbolName;
  9426. addr_target offset;
  9427. DbgModule* dbgModule;
  9428. if (mDebugTarget->FindSymbolAt(pcAddress, &symbolName, &offset, &dbgModule))
  9429. {
  9430. if (dbgModule->HasPendingDebugInfo())
  9431. {
  9432. *outFlags |= FrameFlags_HasPendingDebugInfo;
  9433. if (mPendingDebugInfoLoad.Contains(dbgModule))
  9434. {
  9435. String outName = EncodeDataPtr(pcAddress, true);
  9436. if ((dbgModule != NULL) && (!dbgModule->mDisplayName.empty()))
  9437. outName = dbgModule->mDisplayName + "!<Loading...>" + outName;
  9438. return outName;
  9439. }
  9440. }
  9441. String demangledName = BfDemangler::Demangle(symbolName, DbgLanguage_Unknown);
  9442. if (!dbgModule->mDisplayName.empty())
  9443. demangledName = dbgModule->mDisplayName + "!" + demangledName;
  9444. return demangledName + StrFormat("+0x%X", offset);
  9445. }
  9446. }
  9447. DbgModule* dbgModule = mDebugTarget->FindDbgModuleForAddress(pcAddress);
  9448. if (dbgModule != NULL)
  9449. {
  9450. if (dbgModule->HasPendingDebugInfo())
  9451. *outFlags |= FrameFlags_HasPendingDebugInfo;
  9452. }
  9453. String outName = EncodeDataPtr(pcAddress, true);
  9454. if ((dbgModule != NULL) && (!dbgModule->mDisplayName.empty()))
  9455. outName = dbgModule->mDisplayName + "!" + outName;
  9456. return outName;
  9457. }
  9458. String WinDebugger::Callstack_GetStackFrameOldFileInfo(int stackFrameIdx)
  9459. {
  9460. AutoCrit autoCrit(mDebugManager->mCritSect);
  9461. if (!FixCallStackIdx(stackFrameIdx))
  9462. return "";
  9463. int actualStackFrameIdx = BF_MAX(0, stackFrameIdx);
  9464. UpdateCallStackMethod(actualStackFrameIdx);
  9465. WdStackFrame* wdStackFrame = mCallStack[actualStackFrameIdx];
  9466. DbgSubprogram* dwSubprogram = wdStackFrame->mSubProgram;
  9467. if (dwSubprogram != NULL)
  9468. {
  9469. DbgSrcFile* dwSrcFile = NULL;
  9470. DbgLineData* dwLineData = NULL;
  9471. FixupLineDataForSubprogram(dwSubprogram);
  9472. addr_target findAddress = wdStackFrame->GetSourcePC();
  9473. DbgSubprogram* dbgSubprogram = NULL;
  9474. DbgSrcFile* dbgSrcFile = NULL;
  9475. dwLineData = dwSubprogram->FindClosestLine(findAddress, &dbgSubprogram, &dbgSrcFile);
  9476. DbgModule* dbgModule = dwSubprogram->mCompileUnit->mDbgModule;
  9477. if (dbgSrcFile != NULL)
  9478. {
  9479. // Note: we must use mFilePath here, make sure we don't use GetLocalPath()
  9480. return dbgModule->GetOldSourceCommand(dbgSrcFile->mFilePath);
  9481. }
  9482. }
  9483. return "";
  9484. }
  9485. int WinDebugger::GetJmpState(int stackFrameIdx)
  9486. {
  9487. AutoCrit autoCrit(mDebugManager->mCritSect);
  9488. if (mCallStack.size() == 0)
  9489. UpdateCallStack();
  9490. int actualStackFrameIdx = BF_MAX(0, stackFrameIdx);
  9491. UpdateCallStackMethod(actualStackFrameIdx);
  9492. WdStackFrame* wdStackFrame = mCallStack[actualStackFrameIdx];
  9493. addr_target pcAddress = (addr_target)wdStackFrame->mRegisters.GetPC();
  9494. CPUInst inst;
  9495. if (!mDebugTarget->DecodeInstruction(pcAddress, &inst))
  9496. return -1;
  9497. return inst.GetJmpState(wdStackFrame->mRegisters.mIntRegs.efl);
  9498. }
  9499. intptr WinDebugger::GetStackFrameCalleeAddr(int stackFrameIdx)
  9500. {
  9501. AutoCrit autoCrit(mDebugManager->mCritSect);
  9502. if (mCallStack.size() == 0)
  9503. UpdateCallStack();
  9504. int actualStackFrameIdx = BF_MAX(0, stackFrameIdx);
  9505. UpdateCallStackMethod(actualStackFrameIdx);
  9506. WdStackFrame* wdStackFrame = mCallStack[actualStackFrameIdx];
  9507. addr_target pcAddress = (addr_target)wdStackFrame->mRegisters.GetPC();
  9508. if (stackFrameIdx == -1)
  9509. pcAddress = mShowPCOverride;
  9510. if (wdStackFrame->mInInlineMethod)
  9511. {
  9512. WdStackFrame* inlineStackFrame = mCallStack[actualStackFrameIdx - 1];
  9513. return inlineStackFrame->mSubProgram->mBlock.mLowPC - 1;
  9514. }
  9515. return pcAddress - 1;
  9516. }
  9517. String WinDebugger::GetStackMethodOwner(int stackFrameIdx, int& language)
  9518. {
  9519. AutoCrit autoCrit(mDebugManager->mCritSect);
  9520. if (mCallStack.size() == 0)
  9521. UpdateCallStack();
  9522. int actualStackFrameIdx = BF_MAX(0, stackFrameIdx);
  9523. if (actualStackFrameIdx >= (int)mCallStack.size())
  9524. actualStackFrameIdx = 0;
  9525. UpdateCallStackMethod(actualStackFrameIdx);
  9526. WdStackFrame* wdStackFrame = mCallStack[actualStackFrameIdx];
  9527. if (wdStackFrame->mSubProgram == NULL)
  9528. return "";
  9529. auto parentType = wdStackFrame->mSubProgram->GetParent();
  9530. if (parentType == NULL)
  9531. return "";
  9532. parentType = parentType->GetPrimaryType();
  9533. language = (int)parentType->GetLanguage();
  9534. return parentType->ToString();
  9535. }
  9536. String WinDebugger::FindCodeAddresses(const StringImpl& fileName, int line, int column, bool allowAutoResolve)
  9537. {
  9538. String result;
  9539. if (mDebugTarget == NULL)
  9540. return "";
  9541. DbgSrcFile* srcFile = mDebugTarget->GetSrcFile(fileName);
  9542. if (srcFile == NULL)
  9543. return result;
  9544. bool foundInSequence = false;
  9545. WdBreakpoint* prevBreakpoint = NULL;
  9546. int bestLineOffset = 0x7FFFFFFF;
  9547. for (auto dbgSubprogram : srcFile->mLineDataRefs)
  9548. {
  9549. for (auto& lineData : dbgSubprogram->mLineInfo->mLines)
  9550. {
  9551. auto lineSrcFile = dbgSubprogram->GetLineSrcFile(lineData);
  9552. if (lineSrcFile != srcFile)
  9553. continue;
  9554. int lineOffset = lineData.mLine - line;
  9555. if ((lineOffset >= 0) && (lineOffset <= 12) && (lineOffset <= bestLineOffset))
  9556. {
  9557. if (lineOffset < bestLineOffset)
  9558. {
  9559. bestLineOffset = lineOffset;
  9560. result = "";
  9561. }
  9562. if (!foundInSequence)
  9563. {
  9564. auto addr = dbgSubprogram->GetLineAddr(lineData);
  9565. result += EncodeDataPtr(addr, false) + "\t" + dbgSubprogram->ToString() + "\n";
  9566. }
  9567. }
  9568. // New sequence?
  9569. if (!lineData.IsStackFrameSetup())
  9570. foundInSequence = false;
  9571. }
  9572. }
  9573. return result;
  9574. }
  9575. String WinDebugger::GetAddressSourceLocation(intptr address)
  9576. {
  9577. DbgSubprogram* subProgram = NULL;
  9578. DbgLineData* lineData = FindLineDataAtAddress(address, &subProgram);
  9579. if (lineData != NULL)
  9580. return StrFormat("%s:%d:%d", subProgram->GetLineSrcFile(*lineData)->GetLocalPath().c_str(), lineData->mLine + 1, lineData->mColumn + 1);
  9581. String outSymbol;
  9582. addr_target offset = 0;
  9583. DbgModule* dbgModule;
  9584. if (mDebugTarget->FindSymbolAt(address, &outSymbol, &offset, &dbgModule))
  9585. {
  9586. if (offset < 0x10000)
  9587. {
  9588. outSymbol = BfDemangler::Demangle(outSymbol, DbgLanguage_Unknown);
  9589. if (offset > 0)
  9590. outSymbol += StrFormat("+%x", offset);
  9591. return outSymbol;
  9592. }
  9593. }
  9594. return StrFormat("0x%@", address);
  9595. }
  9596. String WinDebugger::GetAddressSymbolName(intptr address, bool demangle)
  9597. {
  9598. String outSymbol;
  9599. addr_target offset = 0;
  9600. DbgModule* dbgModule;
  9601. if (mDebugTarget->FindSymbolAt(address, &outSymbol, &offset, &dbgModule))
  9602. {
  9603. if (offset < 0x10000)
  9604. {
  9605. if (demangle)
  9606. outSymbol = BfDemangler::Demangle(outSymbol, DbgLanguage_Unknown);
  9607. if (offset > 0)
  9608. outSymbol += StrFormat("+%x", offset);
  9609. return outSymbol;
  9610. }
  9611. }
  9612. return StrFormat("0x%@", address);
  9613. }
  9614. String WinDebugger::DisassembleAtRaw(intptr inAddress)
  9615. {
  9616. addr_target address = (addr_target)inAddress;
  9617. const int addrBorder = 1024;
  9618. for (int offset = 0; offset < 8; offset++)
  9619. {
  9620. String result;
  9621. bool addOffset = true;
  9622. bool hadAddr = false;
  9623. DbgModule* dbgModule = mDebugTarget->FindDbgModuleForAddress(address);
  9624. DbgModuleMemoryCache* memCache = NULL;
  9625. defer
  9626. {
  9627. if (dbgModule == NULL)
  9628. delete memCache;
  9629. };
  9630. if ((dbgModule != NULL) && (dbgModule->mOrigImageData == NULL))
  9631. dbgModule = NULL;
  9632. result += "R\n"; // Raw
  9633. addr_target addrStart = address;
  9634. if (dbgModule != NULL)
  9635. {
  9636. dbgModule->ParseSymbolData();
  9637. memCache = dbgModule->mOrigImageData;
  9638. addrStart = BF_MAX((addr_target)dbgModule->mImageBase, address - addrBorder - offset);
  9639. }
  9640. else
  9641. {
  9642. memCache = new DbgModuleMemoryCache(addrStart & (4096 - 1), 4096 * 2);
  9643. }
  9644. //addr_target imageBase = dbgModule->mImageBase;
  9645. //int imageSize = dbgModule->mImageSize;
  9646. addr_target dataAddr = addrStart;
  9647. addr_target addrEnd = addrStart + addrBorder * 2 + 16;
  9648. while (dataAddr < addrEnd)
  9649. {
  9650. if (dataAddr == address)
  9651. hadAddr = true;
  9652. if (dataAddr > address)
  9653. {
  9654. if (!hadAddr)
  9655. {
  9656. if (offset == 7)
  9657. {
  9658. dataAddr = address;
  9659. }
  9660. break;
  9661. }
  9662. }
  9663. String outSymbol;
  9664. addr_target symOffset = 0;
  9665. DbgModule* symDWARF;
  9666. if (mDebugTarget->FindSymbolAt(dataAddr, &outSymbol, &symOffset, &symDWARF))
  9667. {
  9668. if (symOffset == 0)
  9669. {
  9670. outSymbol = BfDemangler::Demangle(outSymbol, DbgLanguage_Unknown);
  9671. if ((symDWARF != NULL) && (!symDWARF->mDisplayName.empty()))
  9672. outSymbol = symDWARF->mDisplayName + "!" + outSymbol;
  9673. result += "T " + outSymbol + ":\n";
  9674. }
  9675. }
  9676. CPUInst inst;
  9677. if (!mCPU->Decode(dataAddr, memCache, &inst))
  9678. {
  9679. if ((offset == 7) && (!hadAddr))
  9680. {
  9681. uint8 instData[1];
  9682. memCache->Read(dataAddr, instData, 1);
  9683. int instLen = 1;
  9684. #ifdef BF_DBG_32
  9685. result += StrFormat("D %08X: ", dataAddr);
  9686. #else
  9687. result += StrFormat("D %@: ", dataAddr);
  9688. #endif
  9689. for (int i = 0; i < instLen; i++)
  9690. result += StrFormat("%02X ", instData[i]);
  9691. for (int i = instLen; i < 8; i++)
  9692. result += " ";
  9693. result += "\n";
  9694. dataAddr++;
  9695. continue;
  9696. }
  9697. break;
  9698. }
  9699. int instLen = inst.GetLength();
  9700. #ifdef BF_DBG_32
  9701. result += StrFormat("D %08X: ", dataAddr);
  9702. #else
  9703. result += StrFormat("D %@: ", dataAddr);
  9704. #endif
  9705. uint8 instData[32];
  9706. int showInstLen = BF_MIN(32, instLen);
  9707. memCache->Read(dataAddr, instData, showInstLen);
  9708. for (int i = 0; i < showInstLen; i++)
  9709. result += StrFormat("%02X ", instData[i]);
  9710. for (int i = instLen; i < 8; i++)
  9711. result += " ";
  9712. result += mCPU->InstructionToString(&inst, dataAddr);
  9713. if ((inst.IsCall()) || (inst.IsBranch()))
  9714. {
  9715. addr_target targetAddr = inst.GetTarget();
  9716. if (targetAddr != 0)
  9717. {
  9718. if (mDebugTarget->FindSymbolAt(targetAddr, &outSymbol, &symOffset))
  9719. {
  9720. if (symOffset < 0x10000)
  9721. {
  9722. outSymbol = BfDemangler::Demangle(outSymbol, DbgLanguage_Unknown);
  9723. result += " ; " + outSymbol;
  9724. if (symOffset > 0)
  9725. result += StrFormat("+%x", symOffset);
  9726. //result += ">";
  9727. }
  9728. }
  9729. }
  9730. }
  9731. result += "\n";
  9732. dataAddr += instLen;
  9733. }
  9734. if (!hadAddr)
  9735. continue;
  9736. return result;
  9737. }
  9738. return "";
  9739. }
  9740. String WinDebugger::DisassembleAt(intptr inAddress)
  9741. {
  9742. BP_ZONE("WinDebugger::DisassembleAt");
  9743. AutoCrit autoCrit(mDebugManager->mCritSect);
  9744. addr_target address = (addr_target)inAddress;
  9745. if (mDebugTarget == NULL)
  9746. return "";
  9747. String result;
  9748. auto dwSubProgram = mDebugTarget->FindSubProgram(address);
  9749. if (dwSubProgram == NULL)
  9750. return DisassembleAtRaw(address);
  9751. dwSubProgram = dwSubProgram->GetRootInlineParent();
  9752. DbgModule* dwarf = dwSubProgram->mCompileUnit->mDbgModule;
  9753. int frameBaseRegister = mDebugTarget->GetFrameBaseRegister(dwSubProgram);
  9754. addr_target addrStart = dwSubProgram->mBlock.mLowPC;
  9755. addr_target addrEnd = dwSubProgram->mBlock.mHighPC;
  9756. auto dwCompileUnit = dwSubProgram->mCompileUnit;
  9757. {
  9758. FixupLineData(dwCompileUnit);
  9759. }
  9760. DbgSrcFile* dwSrcFile = NULL;
  9761. FixupLineDataForSubprogram(dwSubProgram);
  9762. DbgLineData* dwLineData = NULL;
  9763. if (dwSubProgram->mLineInfo != NULL)
  9764. dwLineData = &dwSubProgram->mLineInfo->mLines[0];
  9765. int nextLineDataIdx = 1;
  9766. if (dwSubProgram->mIsOptimized)
  9767. result += "O\n";
  9768. DbgSrcFile* srcFile = NULL;
  9769. int firstLine = 0;
  9770. int curLine = 0;
  9771. if (dwLineData != NULL)
  9772. {
  9773. srcFile = dwSubProgram->GetLineSrcFile(*dwLineData);
  9774. result += "S " + srcFile->GetLocalPath() + "\n";
  9775. curLine = BF_MAX(0, dwLineData->mLine - 5);
  9776. //for (; curLine <= dwLineData->mLine; curLine++)
  9777. result += StrFormat("L %d %d\n", curLine, dwLineData->mLine - curLine + 1);
  9778. curLine = dwLineData->mLine + 1;
  9779. firstLine = dwLineData->mLine;
  9780. }
  9781. Array<DbgSubprogram*> inlineStack;
  9782. Array<DbgBlock*> blockList;
  9783. blockList.push_back(&dwSubProgram->mBlock);
  9784. addr_target dataAddr = addrStart;
  9785. int decodeFailureCount = 0;
  9786. auto& _PopInlineStack = [&]()
  9787. {
  9788. int depth = inlineStack.size();
  9789. auto curStackEntry = inlineStack.back();
  9790. if (depth > 1)
  9791. result += StrFormat("T <<<%d Inline End ", depth);
  9792. else
  9793. result += "T <<< Inline End ";
  9794. result += curStackEntry->ToString();
  9795. result += "\n";
  9796. inlineStack.pop_back();
  9797. };
  9798. std::function<void(DbgSubprogram* subprogram, int depth)> _UpdateInlineStackHelper = [&](DbgSubprogram* subprogram, int depth)
  9799. {
  9800. int stackIdx = depth - 1;
  9801. if (stackIdx < inlineStack.size())
  9802. {
  9803. auto curStackEntry = inlineStack[stackIdx];
  9804. if (curStackEntry != subprogram)
  9805. _PopInlineStack();
  9806. }
  9807. if (depth > 1)
  9808. {
  9809. _UpdateInlineStackHelper(subprogram->mInlineeInfo->mInlineParent, depth - 1);
  9810. }
  9811. if (stackIdx >= inlineStack.size())
  9812. {
  9813. if (depth > 1)
  9814. result += StrFormat("T >>>%d Inline ", depth);
  9815. else
  9816. result += "T >>> Inline ";
  9817. result += subprogram->ToString();
  9818. result += "\n";
  9819. inlineStack.push_back(subprogram);
  9820. }
  9821. };
  9822. auto _UpdateInlineStack = [&](DbgSubprogram* subprogram)
  9823. {
  9824. if (subprogram == NULL)
  9825. {
  9826. while (!inlineStack.IsEmpty())
  9827. _PopInlineStack();
  9828. return;
  9829. }
  9830. int inlineDepth = subprogram->GetInlineDepth();
  9831. while (inlineDepth < inlineStack.size())
  9832. _PopInlineStack();
  9833. if (inlineDepth > 0)
  9834. _UpdateInlineStackHelper(subprogram, inlineDepth);
  9835. };
  9836. while (dataAddr < addrEnd)
  9837. {
  9838. // Pop off old scopes
  9839. while (blockList.size() > 0)
  9840. {
  9841. auto lastBlock = blockList.back();
  9842. if (dataAddr < lastBlock->mHighPC)
  9843. break;
  9844. blockList.pop_back();
  9845. }
  9846. // Check entry into new child scopes
  9847. auto lastBlock = blockList.back();
  9848. for (auto checkBlock : lastBlock->mSubBlocks)
  9849. {
  9850. if ((dataAddr >= checkBlock->mLowPC) && (dataAddr < checkBlock->mHighPC))
  9851. {
  9852. blockList.push_back(checkBlock);
  9853. break;
  9854. }
  9855. }
  9856. bool allowSourceJump = false;
  9857. if ((dwLineData != NULL) && (dwLineData->mContribSize != 0) && (dataAddr >= dwSubProgram->GetLineAddr(*dwLineData) + dwLineData->mContribSize))
  9858. {
  9859. DbgSubprogram* inlinedSubprogram = NULL;
  9860. auto inlinedLine = dwSubProgram->FindClosestLine(dataAddr, &inlinedSubprogram);
  9861. _UpdateInlineStack(dwSubProgram);
  9862. }
  9863. // Update line data
  9864. while ((dwLineData != NULL) && (dwSubProgram->GetLineAddr(*dwLineData) <= dataAddr))
  9865. {
  9866. _UpdateInlineStack(dwSubProgram->GetLineInlinee(*dwLineData));
  9867. const int lineLimit = 5; // 15
  9868. if (allowSourceJump)
  9869. curLine = dwLineData->mLine;
  9870. auto lineSrcFile = dwSubProgram->GetLineSrcFile(*dwLineData);
  9871. if (lineSrcFile != srcFile)
  9872. {
  9873. srcFile = lineSrcFile;
  9874. result += "S ";
  9875. result += srcFile->GetLocalPath();
  9876. result += "\n";
  9877. // Just show the one line from the new file
  9878. curLine = dwLineData->mLine;
  9879. }
  9880. if (dwLineData->mLine < curLine - 1)
  9881. {
  9882. // Jumping backwards - possibly into inlined method, or possibly in current method.
  9883. // Show previous 6 lines, for context
  9884. curLine = BF_MAX(0, dwLineData->mLine - lineLimit);
  9885. }
  9886. if ((curLine <= firstLine) && (dwLineData->mLine >= firstLine))
  9887. {
  9888. // Jumping from inlined method (declared above) back into main method
  9889. curLine = dwLineData->mLine;
  9890. }
  9891. if (curLine < dwLineData->mLine - lineLimit)
  9892. {
  9893. // Don't show huge span of source - only show the last 6 lines at maximum
  9894. curLine = dwLineData->mLine - lineLimit;
  9895. }
  9896. //for ( ; curLine <= dwLineData->mLine; curLine++)
  9897. result += StrFormat("L %d %d\n", curLine, dwLineData->mLine - curLine + 1);
  9898. curLine = dwLineData->mLine + 1;
  9899. DbgLineData* nextLineData = NULL;
  9900. while (nextLineDataIdx < dwSubProgram->mLineInfo->mLines.mSize)
  9901. {
  9902. nextLineData = &dwSubProgram->mLineInfo->mLines[nextLineDataIdx];
  9903. //TODO:
  9904. /*{
  9905. result += StrFormat("T LineIdx: %d (%@ to %@)", nextLineDataIdx, dwSubProgram->GetLineAddr(*nextLineData), dwSubProgram->GetLineAddr(*nextLineData) + nextLineData->mContribSize);
  9906. auto inlinee = dwSubProgram->GetLineInlinee(*nextLineData);
  9907. if (inlinee != NULL)
  9908. {
  9909. result += StrFormat(" Inlinee: %s Depth: %d", inlinee->mName, inlinee->GetInlineDepth());
  9910. }
  9911. result += "\n";
  9912. }*/
  9913. auto nextLineAddr = dwSubProgram->GetLineAddr(*nextLineData);
  9914. if (nextLineAddr > dataAddr)
  9915. {
  9916. if (nextLineDataIdx + 1 < dwSubProgram->mLineInfo->mLines.mSize)
  9917. {
  9918. auto peekLineData = &dwSubProgram->mLineInfo->mLines[nextLineDataIdx + 1];
  9919. if (peekLineData->mRelAddress == nextLineData->mRelAddress)
  9920. {
  9921. // Use the later entry
  9922. ++nextLineDataIdx;
  9923. continue;
  9924. }
  9925. }
  9926. break;
  9927. }
  9928. // If we go back to an older entry beacuse of a gap then we need to catch back up...
  9929. ++nextLineDataIdx;
  9930. nextLineData = NULL; // Keep searching...
  9931. }
  9932. dwLineData = nextLineData;
  9933. nextLineDataIdx++;
  9934. }
  9935. // Have we gone off the end of the inline function?
  9936. // We may not have an explicit non-inlined line data at the transition point...
  9937. while (!inlineStack.IsEmpty())
  9938. {
  9939. auto subProgram = inlineStack.back();
  9940. if (dataAddr < subProgram->mBlock.mHighPC)
  9941. break;
  9942. _PopInlineStack();
  9943. }
  9944. bool hadDecodeFailure = false;
  9945. CPUInst inst;
  9946. if (!mCPU->Decode(dataAddr, dwarf->mOrigImageData, &inst))
  9947. hadDecodeFailure = true;
  9948. if ((decodeFailureCount == 8) || ((decodeFailureCount > 0) && (!hadDecodeFailure)))
  9949. {
  9950. for (int i = decodeFailureCount; i < 4 + sizeof(addr_target); i++)
  9951. result += " ";
  9952. result += " ???\n";
  9953. decodeFailureCount = 0;
  9954. }
  9955. if (decodeFailureCount == 0)
  9956. {
  9957. #ifdef BF_DBG_32
  9958. result += StrFormat("D %08X: ", dataAddr);
  9959. #else
  9960. result += StrFormat("D %@: ", dataAddr);
  9961. #endif
  9962. }
  9963. if (hadDecodeFailure)
  9964. {
  9965. uint8 byte = 0;
  9966. dwarf->mOrigImageData->Read(dataAddr, &byte, 1);
  9967. result += StrFormat("%02X ", byte);
  9968. dataAddr++;
  9969. decodeFailureCount++;
  9970. continue;
  9971. }
  9972. int instLen = inst.GetLength();
  9973. uint8 instData[32];
  9974. int showInstLen = BF_MIN(32, instLen);
  9975. dwarf->mOrigImageData->Read(dataAddr, instData, showInstLen);
  9976. for (int i = 0; i < showInstLen; i++)
  9977. result += StrFormat("%02X ", instData[i]);
  9978. for (int i = instLen; i < 4 + sizeof(addr_target); i++)
  9979. result += " ";
  9980. result += " ";
  9981. result += mCPU->InstructionToString(&inst, dataAddr);
  9982. int reg;
  9983. int offset;
  9984. if (inst.GetIndexRegisterAndOffset(&reg, &offset))
  9985. {
  9986. for (int blockIdx = (int)blockList.size() - 1; blockIdx >= 0; blockIdx--)
  9987. {
  9988. auto dwBlock = blockList[blockIdx];
  9989. for (auto variable : dwBlock->mVariables)
  9990. {
  9991. int varRegister;
  9992. int varOffset;
  9993. if (mDebugTarget->GetVariableIndexRegisterAndOffset(variable, &varRegister, &varOffset))
  9994. {
  9995. if (varRegister == -1)
  9996. varRegister = frameBaseRegister;
  9997. if ((reg == varRegister) && (offset == varOffset))
  9998. {
  9999. result += " ; ";
  10000. result += variable->mName;
  10001. break;
  10002. }
  10003. }
  10004. }
  10005. }
  10006. }
  10007. else if ((inst.IsCall()) || (inst.IsBranch()) || (inst.IsLoadAddress()))
  10008. {
  10009. addr_target targetAddr = inst.GetTarget();
  10010. if (targetAddr != 0)
  10011. {
  10012. if ((targetAddr >= addrStart) && (targetAddr < addrEnd))
  10013. {
  10014. result += StrFormat("\nJ %s", EncodeDataPtr(targetAddr, false).c_str());
  10015. }
  10016. else
  10017. {
  10018. String outSymbol;
  10019. addr_target offset = 0;
  10020. if (mDebugTarget->FindSymbolAt(targetAddr, &outSymbol, &offset))
  10021. {
  10022. if (offset < 0x10000)
  10023. {
  10024. outSymbol = BfDemangler::Demangle(outSymbol, dwSubProgram->GetLanguage());
  10025. result += " ; " + outSymbol;
  10026. if (offset > 0)
  10027. result += StrFormat("+%x", offset);
  10028. }
  10029. }
  10030. }
  10031. }
  10032. }
  10033. result += "\n";
  10034. dataAddr += instLen;
  10035. }
  10036. // Why did we want to "show lines at end"??
  10037. // Show lines at end
  10038. /*if (curLine > 0)
  10039. {
  10040. for (int i = 0; i < 6; i++, curLine++)
  10041. result += StrFormat("L %d\n", curLine);
  10042. }*/
  10043. return result;
  10044. }
  10045. String WinDebugger::FindLineCallAddresses(intptr inAddress)
  10046. {
  10047. String callAddresses;
  10048. addr_target address = (addr_target)inAddress;
  10049. DbgSubprogram* dwSubprogram = NULL;
  10050. DbgLineData* startLineData = FindLineDataAtAddress(address, &dwSubprogram, NULL);
  10051. if (dwSubprogram == NULL)
  10052. return "";
  10053. CPURegisters registers;
  10054. PopulateRegisters(&registers);
  10055. auto inlinerSubprogram = dwSubprogram->GetRootInlineParent();
  10056. FixupLineDataForSubprogram(inlinerSubprogram);
  10057. if (inlinerSubprogram->mLineInfo->mLines.mSize == 0)
  10058. return "";
  10059. auto lineData = &inlinerSubprogram->mLineInfo->mLines[0];
  10060. addr_target addr = dwSubprogram->mBlock.mLowPC;
  10061. addr_target endAddr = dwSubprogram->mBlock.mHighPC;
  10062. DbgSubprogram* checkSubprogram = dwSubprogram;
  10063. DbgLineData* checkLineData = lineData;
  10064. addr_target checkLineAddr = 0;
  10065. int lineIdx = 0;
  10066. while (checkLineData != NULL)
  10067. {
  10068. //auto nextLineData = dwSubprogram->mCompileUnit->mLineDataMap.GetNext(checkLineData);
  10069. ++lineIdx;
  10070. DbgLineData* nextLineData = NULL;
  10071. addr_target nextLineAddr;
  10072. if (lineIdx < inlinerSubprogram->mLineInfo->mLines.size())
  10073. {
  10074. nextLineData = &inlinerSubprogram->mLineInfo->mLines[lineIdx];
  10075. nextLineAddr = dwSubprogram->GetLineAddr(*nextLineData);
  10076. }
  10077. else
  10078. nextLineAddr = inlinerSubprogram->mBlock.mHighPC;
  10079. // This stuff doesn't make sense...
  10080. DbgSubprogram* nextSubProgram;
  10081. if (nextLineData != NULL)
  10082. {
  10083. if (nextLineAddr > dwSubprogram->mBlock.mHighPC)
  10084. break;
  10085. endAddr = nextLineAddr;
  10086. nextSubProgram = mDebugTarget->FindSubProgram(endAddr);
  10087. if (nextSubProgram != NULL)
  10088. {
  10089. auto dbgModule = nextSubProgram->mCompileUnit->mDbgModule;
  10090. dbgModule->ParseSymbolData();
  10091. }
  10092. }
  10093. else
  10094. {
  10095. nextSubProgram = dwSubprogram;
  10096. endAddr = dwSubprogram->mBlock.mHighPC;
  10097. }
  10098. auto _HandleSection = [&]()
  10099. {
  10100. while (addr < endAddr)
  10101. {
  10102. CPUInst inst;
  10103. if (!mDebugTarget->DecodeInstruction(addr, &inst))
  10104. break;
  10105. if (inst.IsCall())
  10106. {
  10107. bool addSymbol = true;
  10108. if (addr < (addr_target)inAddress)
  10109. callAddresses += "-";
  10110. callAddresses += EncodeDataPtr(addr, false);
  10111. addr_target targetAddr = inst.GetTarget(&registers);
  10112. if (targetAddr != 0)
  10113. {
  10114. String outSymbol;
  10115. auto subprogram = mDebugTarget->FindSubProgram(targetAddr);
  10116. if (subprogram != NULL)
  10117. {
  10118. CreateFilterName(outSymbol, subprogram);
  10119. addSymbol = true;
  10120. }
  10121. else
  10122. {
  10123. addr_target offset = 0;
  10124. String fullSymbolName;
  10125. if (mDebugTarget->FindSymbolAt(targetAddr, &outSymbol, &offset))
  10126. {
  10127. if (offset < 0x200)
  10128. {
  10129. //outSymbol = BfDemangler::Demangle(outSymbol, dwSubprogram->GetLanguage());
  10130. if (outSymbol == "___chkstk_ms")
  10131. addSymbol = false;
  10132. else
  10133. {
  10134. String demangledName = BfDemangler::Demangle(outSymbol, DbgLanguage_C);
  10135. outSymbol.clear();
  10136. CreateFilterName(outSymbol, demangledName.c_str(), DbgLanguage_C);
  10137. }
  10138. }
  10139. else
  10140. outSymbol.clear();
  10141. }
  10142. }
  10143. if (addSymbol)
  10144. {
  10145. if (outSymbol.empty())
  10146. callAddresses += "\tFunc@" + EncodeDataPtr(targetAddr, false);
  10147. else
  10148. callAddresses += "\t" + outSymbol;
  10149. String attrs;
  10150. bool isFiltered = false;
  10151. if (subprogram != NULL)
  10152. {
  10153. subprogram->PopulateSubprogram();
  10154. isFiltered = subprogram->mIsStepFilteredDefault;
  10155. if (isFiltered)
  10156. attrs += "d"; // 'd' for default filtered
  10157. }
  10158. StepFilter* stepFilterPtr = NULL;
  10159. if (mDebugManager->mStepFilters.TryGetValue(outSymbol, &stepFilterPtr))
  10160. isFiltered = stepFilterPtr->IsFiltered(isFiltered);
  10161. if (isFiltered)
  10162. attrs += "f"; // 'f' for filter
  10163. if (!attrs.IsEmpty())
  10164. callAddresses += "\t" + attrs;
  10165. }
  10166. }
  10167. if (addSymbol)
  10168. callAddresses += "\n";
  10169. }
  10170. addr += inst.GetLength();
  10171. }
  10172. };
  10173. // For inlining - only add calls that are found either directly in our main block (not an inlined block)
  10174. // But add inlined methods when their parent is our current block
  10175. if ((checkSubprogram == dwSubprogram) && (checkLineData->mLine == startLineData->mLine))
  10176. {
  10177. _HandleSection();
  10178. }
  10179. else if ((checkSubprogram->mInlineeInfo != NULL) && (checkSubprogram->mInlineeInfo->mInlineParent == dwSubprogram))
  10180. {
  10181. if (checkLineAddr == checkSubprogram->mBlock.mLowPC)
  10182. {
  10183. addr_target inlineStartAddr = checkSubprogram->mBlock.mLowPC;
  10184. // Find the calling line
  10185. DbgSubprogram* callingSubprogram = dwSubprogram;
  10186. auto checkLineData = dwSubprogram->FindClosestLine(inlineStartAddr, &callingSubprogram);
  10187. if ((checkLineData != NULL) && (checkLineData->mCtxIdx == startLineData->mCtxIdx) && (checkLineData->mLine == startLineData->mLine))
  10188. {
  10189. if (inlineStartAddr <= (addr_target)inAddress)
  10190. callAddresses += "-";
  10191. callAddresses += EncodeDataPtr(inlineStartAddr, false);
  10192. String outSymbol;
  10193. CreateFilterName(outSymbol, checkSubprogram);
  10194. callAddresses += "\t" + outSymbol;
  10195. bool isFiltered = dwSubprogram->mIsStepFilteredDefault;
  10196. StepFilter* stepFilterPtr;
  10197. if (mDebugManager->mStepFilters.TryGetValue(outSymbol, &stepFilterPtr))
  10198. isFiltered = stepFilterPtr->IsFiltered(isFiltered);
  10199. if (isFiltered)
  10200. callAddresses += "\tf"; // 'f' for filter
  10201. callAddresses += "\n";
  10202. }
  10203. // if (checkSubprogram->mBlock.mHighPC < endAddr)
  10204. // {
  10205. // addr = checkSubprogram->mBlock.mHighPC;
  10206. // _HandleSection();
  10207. // }
  10208. }
  10209. // If we have unattributed data after the end of an inlined method, add that
  10210. if ((endAddr > checkSubprogram->mBlock.mHighPC) && (nextSubProgram == dwSubprogram))
  10211. {
  10212. addr = checkSubprogram->mBlock.mHighPC;
  10213. _HandleSection();
  10214. }
  10215. }
  10216. checkLineData = nextLineData;
  10217. checkSubprogram = nextSubProgram;
  10218. checkLineAddr = nextLineAddr;
  10219. addr = endAddr;
  10220. }
  10221. return callAddresses;
  10222. }
  10223. String WinDebugger::GetCurrentException()
  10224. {
  10225. AutoCrit autoCrit(mDebugManager->mCritSect);
  10226. String result = StrFormat("%s\n%08X",
  10227. EncodeDataPtr((addr_target)(intptr)mCurException.ExceptionAddress, true).c_str(),
  10228. mCurException.ExceptionCode);
  10229. String exStr;
  10230. switch (mCurException.ExceptionCode)
  10231. {
  10232. case EXCEPTION_ACCESS_VIOLATION:
  10233. {
  10234. String accessType;
  10235. if (mCurException.ExceptionInformation[0] == 0)
  10236. accessType = "reading from";
  10237. else if (mCurException.ExceptionInformation[0] == 8)
  10238. accessType = "executing";
  10239. else
  10240. accessType = "writing to";
  10241. exStr = StrFormat("EXCEPTION_ACCESS_VIOLATION %s %s", accessType.c_str(), EncodeDataPtr((addr_target)mCurException.ExceptionInformation[1], true).c_str());
  10242. }
  10243. break;
  10244. case EXCEPTION_DATATYPE_MISALIGNMENT:
  10245. exStr = "EXCEPTION_DATATYPE_MISALIGNMENT";
  10246. case EXCEPTION_SINGLE_STEP:
  10247. exStr = "EXCEPTION_SINGLE_STEP";
  10248. break;
  10249. case EXCEPTION_BREAKPOINT:
  10250. exStr = "EXCEPTION_BREAKPOINT";
  10251. break;
  10252. case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
  10253. exStr = "EXCEPTION_ARRAY_BOUNDS_EXCEEDED";
  10254. break;
  10255. case EXCEPTION_FLT_DENORMAL_OPERAND:
  10256. exStr = "EXCEPTION_FLT_DENORMAL_OPERAND";
  10257. break;
  10258. case EXCEPTION_FLT_DIVIDE_BY_ZERO:
  10259. exStr = "EXCEPTION_FLT_DIVIDE_BY_ZERO";
  10260. break;
  10261. case EXCEPTION_FLT_INEXACT_RESULT:
  10262. exStr = "EXCEPTION_FLT_INEXACT_RESULT";
  10263. break;
  10264. case EXCEPTION_FLT_INVALID_OPERATION:
  10265. exStr = "EXCEPTION_FLT_INVALID_OPERATIO";
  10266. break;
  10267. case EXCEPTION_FLT_OVERFLOW:
  10268. exStr = "EXCEPTION_FLT_OVERFLOW";
  10269. break;
  10270. case EXCEPTION_FLT_STACK_CHECK:
  10271. exStr = "EXCEPTION_FLT_STACK_CHECK";
  10272. break;
  10273. case EXCEPTION_FLT_UNDERFLOW:
  10274. exStr = "EXCEPTION_FLT_UNDERFLOW";
  10275. break;
  10276. case EXCEPTION_INT_DIVIDE_BY_ZERO:
  10277. exStr = "EXCEPTION_INT_DIVIDE_BY_ZERO";
  10278. break;
  10279. case EXCEPTION_INT_OVERFLOW:
  10280. exStr = "EXCEPTION_INT_OVERFLOW";
  10281. break;
  10282. case EXCEPTION_PRIV_INSTRUCTION:
  10283. exStr = "EXCEPTION_PRIV_INSTRUCTION";
  10284. break;
  10285. case EXCEPTION_IN_PAGE_ERROR:
  10286. exStr = "EXCEPTION_IN_PAGE_ERROR";
  10287. break;
  10288. case EXCEPTION_ILLEGAL_INSTRUCTION:
  10289. exStr = "EXCEPTION_ILLEGAL_INSTRUCTION";
  10290. break;
  10291. case EXCEPTION_NONCONTINUABLE_EXCEPTION:
  10292. exStr = "EXCEPTION_NONCONTINUABLE_EXCEPTION";
  10293. break;
  10294. case EXCEPTION_STACK_OVERFLOW:
  10295. exStr = "EXCEPTION_STACK_OVERFLOW";
  10296. break;
  10297. case EXCEPTION_INVALID_DISPOSITION:
  10298. exStr = "EXCEPTION_INVALID_DISPOSITION";
  10299. break;
  10300. case EXCEPTION_GUARD_PAGE:
  10301. exStr = "EXCEPTION_GUARD_PAGE";
  10302. break;
  10303. case EXCEPTION_INVALID_HANDLE:
  10304. exStr = "EXCEPTION_INVALID_HANDLE";
  10305. break;
  10306. case CONTROL_C_EXIT:
  10307. exStr = "CONTROL_C_EXIT";
  10308. break;
  10309. default:
  10310. exStr += StrFormat("EXCEPTION %08X", mCurException.ExceptionCode);
  10311. }
  10312. if (mActiveThread != NULL)
  10313. exStr += StrFormat(" in thread %d", mActiveThread->mThreadId);
  10314. if (!exStr.empty())
  10315. result += "\n" + exStr;
  10316. // After we retrieve the exception then we can go back to just being normal 'paused'
  10317. // This allows us to evaluate stuff, Set Next Statement, etc.
  10318. mRunState = RunState_Paused;
  10319. return result.c_str();
  10320. }
  10321. void WinDebugger::SetAliasPath(const StringImpl& origPath, const StringImpl& localPath)
  10322. {
  10323. AutoCrit autoCrit(mDebugManager->mCritSect);
  10324. String fixedOrigPath = FixPathAndCase(origPath);
  10325. String fixedLocalPath = FixPathAndCase(localPath);
  10326. auto origFile = mDebugTarget->AddSrcFile(origPath);
  10327. origFile->mLocalPath = FixPath(localPath);
  10328. mDebugTarget->mLocalToOrigSrcMap[fixedLocalPath] = fixedOrigPath;
  10329. // We invalidate the step filters, because previously-failing 'CheckSourceFileExist' checks may now succeed
  10330. mDebugManager->mStepFilterVersion++;
  10331. }
  10332. String WinDebugger::GetModulesInfo()
  10333. {
  10334. AutoCrit autoCrit(mDebugManager->mCritSect);
  10335. String str;
  10336. for (auto module : mDebugTarget->mDbgModules)
  10337. {
  10338. COFF* coff = (COFF*)module;
  10339. if (module->mHotIdx > 0)
  10340. continue;
  10341. str += module->mDisplayName;
  10342. str += "\t";
  10343. str += module->mFilePath;
  10344. str += "\t";
  10345. str += coff->mPDBPath;
  10346. str += "\t";
  10347. str += module->mVersion;
  10348. str += StrFormat("\t%@-%@\t%dk\t", module->mImageBase, module->mImageBase + module->mImageSize, module->mImageSize / 1024);
  10349. time_t timestamp = coff->mTimeStamp;
  10350. if (timestamp == 0)
  10351. timestamp = GetFileTimeWrite(coff->mFilePath);
  10352. if (timestamp != 0)
  10353. {
  10354. char timeString[256];
  10355. auto time_info = localtime(&timestamp);
  10356. strftime(timeString, sizeof(timeString), "%D %T", time_info);
  10357. str += timeString;
  10358. }
  10359. str += "\n";
  10360. }
  10361. return str;
  10362. }
  10363. void WinDebugger::CancelSymSrv()
  10364. {
  10365. AutoCrit autoCrit(mDebugManager->mCritSect);
  10366. if (mActiveSymSrvRequest != NULL)
  10367. mActiveSymSrvRequest->Cancel();
  10368. }
  10369. bool WinDebugger::HasPendingDebugLoads()
  10370. {
  10371. AutoCrit autoCrit(mDebugManager->mCritSect);
  10372. return (!mPendingImageLoad.IsEmpty()) || (!mPendingDebugInfoLoad.IsEmpty());
  10373. }
  10374. int WinDebugger::LoadDebugInfoForModule(DbgModule* dbgModule)
  10375. {
  10376. if (!dbgModule->HasPendingDebugInfo())
  10377. return 0;
  10378. if (dbgModule->RequestDebugInfo())
  10379. {
  10380. ClearCallStack(); // Make this re-resolve with debug info
  10381. return 1;
  10382. }
  10383. if (!mPendingDebugInfoLoad.Contains(dbgModule))
  10384. {
  10385. mPendingDebugInfoLoad.Add(dbgModule);
  10386. return 2;
  10387. }
  10388. return 0;
  10389. }
  10390. int WinDebugger::LoadDebugInfoForModule(const StringImpl& moduleName)
  10391. {
  10392. AutoCrit autoCrit(mDebugManager->mCritSect);
  10393. for (auto dbgModule : mDebugTarget->mDbgModules)
  10394. {
  10395. String checkModuleName = GetFileName(dbgModule->mFilePath);
  10396. if (moduleName.Equals(checkModuleName, StringImpl::CompareKind_OrdinalIgnoreCase))
  10397. {
  10398. return LoadDebugInfoForModule(dbgModule);
  10399. }
  10400. }
  10401. return 0;
  10402. }
  10403. int WinDebugger::LoadDebugInfoForModule(const StringImpl& modulePath, const StringImpl& debugFileName)
  10404. {
  10405. AutoCrit autoCrit(mDebugManager->mCritSect);
  10406. for (auto dbgModule : mDebugTarget->mDbgModules)
  10407. {
  10408. if (modulePath.Equals(dbgModule->mFilePath, StringImpl::CompareKind_OrdinalIgnoreCase))
  10409. {
  10410. auto coff = (COFF*)dbgModule;
  10411. String err;
  10412. if (coff->mDbgSymRequest != NULL)
  10413. {
  10414. dbgModule->mFailMsgPtr = &err;
  10415. if (coff->TryLoadPDB(debugFileName, coff->mDbgSymRequest->mWantGuid, coff->mDbgSymRequest->mWantAge))
  10416. {
  10417. ModuleChanged(dbgModule);
  10418. }
  10419. dbgModule->mFailMsgPtr = NULL;
  10420. }
  10421. else
  10422. {
  10423. err = StrFormat("Module '%s' already has debug information loaded", GetFileName(modulePath).c_str());
  10424. }
  10425. if (!err.IsEmpty())
  10426. {
  10427. mDebugManager->mOutMessages.push_back("error " + err);
  10428. }
  10429. return 0;
  10430. }
  10431. }
  10432. return 0;
  10433. }
  10434. void WinDebugger::FixupLineData(DbgCompileUnit* compileUnit)
  10435. {
  10436. if (!compileUnit || !compileUnit->mNeedsLineDataFixup)
  10437. return;
  10438. compileUnit->mNeedsLineDataFixup = false;
  10439. }
  10440. static int CompareLineData(const void* lineDataP1, const void* lineDataP2)
  10441. {
  10442. int cmpResult = (int)(((DbgLineData*)lineDataP1)->mRelAddress - ((DbgLineData*)lineDataP2)->mRelAddress);
  10443. if (cmpResult != 0)
  10444. return cmpResult;
  10445. // A larger contrib size means it's the 'outer' inlinee
  10446. cmpResult = -(((DbgLineData*)lineDataP1)->mContribSize - ((DbgLineData*)lineDataP2)->mContribSize);
  10447. if (cmpResult != 0)
  10448. return cmpResult;
  10449. return -(((DbgLineData*)lineDataP1)->mCtxIdx - ((DbgLineData*)lineDataP2)->mCtxIdx);
  10450. }
  10451. void WinDebugger::FixupLineDataForSubprogram(DbgSubprogram* subProgram)
  10452. {
  10453. if ((subProgram == NULL) || (!subProgram->mNeedLineDataFixup))
  10454. return;
  10455. BP_ZONE("FixupLineDataForSubprogram");
  10456. subProgram->mNeedLineDataFixup = false;
  10457. if (subProgram->mInlineeInfo != NULL)
  10458. FixupLineDataForSubprogram(subProgram->mInlineeInfo->mRootInliner);
  10459. if ((subProgram->mLineInfo == NULL) || (subProgram->mLineInfo->mLines.mSize == 0))
  10460. return;
  10461. //TODO: I think this was covering up a bug in DWARF line encoding? Figure this out
  10462. // if (subProgram->mLineInfo->mLines.mSize >= 2)
  10463. // {
  10464. // DbgLineData* line0 = &subProgram->mLineInfo->mLines[0];
  10465. // DbgLineData* line1 = &subProgram->mLineInfo->mLines[1];
  10466. //
  10467. //
  10468. // if ((line0->mRelAddress == line1->mRelAddress) && (!line0->IsStackFrameSetup()) && (line1->IsStackFrameSetup()))
  10469. // {
  10470. // CPUInst inst;
  10471. // if (mCPU->Decode(line0->mAddress, subProgram->mCompileUnit->mDbgModule->mOrigImageData, &inst))
  10472. // line1->mAddress += inst.GetLength();
  10473. // }
  10474. // }
  10475. qsort(subProgram->mLineInfo->mLines.mVals, subProgram->mLineInfo->mLines.mSize, sizeof(DbgLineData), CompareLineData);
  10476. // If we have multiple lines with the same line/column/context, merge them
  10477. if (!subProgram->mLineInfo->mLines.IsEmpty())
  10478. {
  10479. auto prevLine = &subProgram->mLineInfo->mLines[0];
  10480. for (int i = 1; i < subProgram->mLineInfo->mLines.mSize; i++)
  10481. {
  10482. auto nextLine = &subProgram->mLineInfo->mLines[i];
  10483. if ((nextLine->mLine == prevLine->mLine) && (nextLine->mColumn == prevLine->mColumn) && (nextLine->mCtxIdx == prevLine->mCtxIdx) &&
  10484. (nextLine->mRelAddress == prevLine->mRelAddress + prevLine->mContribSize))
  10485. {
  10486. prevLine->mContribSize += nextLine->mContribSize;
  10487. // This messed up inline cases because mContribSize actually INCLUDES inlined lines so it caused the address to skip too far
  10488. //nextLine->mRelAddress += nextLine->mContribSize;
  10489. //nextLine->mContribSize = 0;
  10490. }
  10491. else
  10492. {
  10493. prevLine = nextLine;
  10494. }
  10495. }
  10496. }
  10497. }
  10498. void WinDebugger::ReserveHotTargetMemory(int size)
  10499. {
  10500. HotTargetMemory hotTargetMemory;
  10501. hotTargetMemory.mOffset = 0;
  10502. hotTargetMemory.mSize = 0;
  10503. hotTargetMemory.mPtr = NULL;
  10504. if (size > 0)
  10505. {
  10506. // In 64-bit mode we have a reserved region on program load that we commit here because the offsets
  10507. // must be within 32-bits of the original EXE image, but in 32-bit mode we don't reserve anything
  10508. // until here
  10509. #ifdef BF_DBG_32
  10510. //hotTargetMemory.mSize = std::max(1024 * 1024, size);
  10511. BF_ASSERT((size & (mPageSize - 1)) == 0);
  10512. hotTargetMemory.mSize = size;
  10513. hotTargetMemory.mPtr = (addr_target)(intptr)VirtualAllocEx(mProcessInfo.hProcess, NULL, hotTargetMemory.mSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
  10514. mDebugTarget->mHotHeap->AddTrackedRegion(hotTargetMemory.mPtr, hotTargetMemory.mSize);
  10515. #else
  10516. hotTargetMemory.mSize = size;
  10517. hotTargetMemory.mPtr = mDebugTarget->mHotHeap->Alloc(size);
  10518. BF_ASSERT(hotTargetMemory.mPtr != 0);
  10519. auto ptr = ::VirtualAllocEx(mProcessInfo.hProcess, (void*)(intptr)hotTargetMemory.mPtr, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
  10520. BF_ASSERT(ptr == (void*)(intptr)hotTargetMemory.mPtr);
  10521. #endif
  10522. }
  10523. BfLogDbg("ReserveHotTargetMemory %p %d", hotTargetMemory.mPtr, hotTargetMemory.mSize);
  10524. int err = GetLastError();
  10525. mHotTargetMemory.push_back(hotTargetMemory);
  10526. }
  10527. addr_target WinDebugger::AllocHotTargetMemory(int size, bool canExecute, bool canWrite, int* outAllocSize)
  10528. {
  10529. int prot = PAGE_READWRITE;
  10530. if (canExecute && canWrite)
  10531. prot = PAGE_EXECUTE_READWRITE;
  10532. else if (canExecute)
  10533. prot = PAGE_EXECUTE_READ;
  10534. auto hotTargetMemory = (HotTargetMemory*)&mHotTargetMemory.back();
  10535. if (hotTargetMemory->mPtr == 0)
  10536. {
  10537. Fail("Failed to allocate memory for hot loading");
  10538. return 0;
  10539. }
  10540. size = (size + (mPageSize - 1)) & ~(mPageSize - 1);
  10541. *outAllocSize = size;
  10542. BF_ASSERT(hotTargetMemory->mOffset + size <= hotTargetMemory->mSize);
  10543. addr_target result = hotTargetMemory->mPtr + hotTargetMemory->mOffset;
  10544. ::VirtualProtectEx(mProcessInfo.hProcess, (void*)(intptr)result, size, prot, NULL);
  10545. BfLogDbg("AllocHotTargetMemory: %p %d %d %d\n", result, size, canExecute, canWrite);
  10546. hotTargetMemory->mOffset += size;
  10547. return result;
  10548. }
  10549. void WinDebugger::ReleaseHotTargetMemory(addr_target addr, int size)
  10550. {
  10551. #ifdef BF_DBG_32
  10552. ::VirtualFreeEx(mProcessInfo.hProcess, (void*)(intptr)addr, 0, MEM_RELEASE);
  10553. #else
  10554. mDebugTarget->mHotHeap->Release(addr, size);
  10555. ::VirtualFreeEx(mProcessInfo.hProcess, (void*)(intptr)addr, size, MEM_DECOMMIT);
  10556. #endif
  10557. }
  10558. void WinDebugger::CleanupHotHeap()
  10559. {
  10560. mDebugTarget->mLastHotHeapCleanIdx = mDebugTarget->mHotHeap->mBlockAllocIdx;
  10561. // Our criteria for determining whether a hot loaded file is still being used:
  10562. // 1) If we are currently executing a method from that object file.
  10563. // 2) If the symbol map has a symbol with that address.
  10564. // 3) If the static variable map contains a reference - including a conservative scan of the data
  10565. // This handles vdata references
  10566. // This is a conservative check which won't purge hot reloads that contain deleted
  10567. // methods (for example), but it will purge hot reloads where all the changed
  10568. // data has been overwritten.
  10569. // For delegate bindings, the original module declaring the bind creates a "preserve"
  10570. // global such as "bf_hs_preserve@_ZN5TestO4TestEv", whose preserved symbol ensures it
  10571. // doesn't get unloaded. The current version of that method resides in "_ZN5TestO4TestEv",
  10572. // ensuring that the method pointed to by the global variable is valid
  10573. mDebugTarget->mHotHeap->ClearReferencedFlags();
  10574. addr_target lowAddr = mDebugTarget->mHotHeap->mHotAreaStart;
  10575. addr_target highAddr = lowAddr + mDebugTarget->mHotHeap->mHotAreaSize;
  10576. // Do conservative scan through all thread stacks. Stack traces aren't 100% reliable, so we
  10577. // need to do a full conservative scan of any addresses stored in the stack
  10578. // to ensure we don't miss any return addresses
  10579. for (int threadIdx = 0; threadIdx < (int)mThreadList.size(); threadIdx++)
  10580. {
  10581. WdThreadInfo* threadInfo = mThreadList[threadIdx];
  10582. BF_CONTEXT lcContext;
  10583. lcContext.ContextFlags = BF_CONTEXT_CONTROL;
  10584. BF_GetThreadContext(threadInfo->mHThread, &lcContext);
  10585. addr_target checkStackAddr = BF_CONTEXT_SP(lcContext);
  10586. checkStackAddr &= ~(sizeof(addr_target) - 1);
  10587. // Conservative check on registers
  10588. for (int regNum = 0; regNum < sizeof(BF_CONTEXT)/sizeof(addr_target); regNum++)
  10589. {
  10590. addr_target checkAddr = ((addr_target*)&lcContext)[regNum];
  10591. if ((checkAddr >= lowAddr) && (checkAddr < highAddr))
  10592. mDebugTarget->mHotHeap->MarkBlockReferenced(checkAddr);
  10593. }
  10594. // Conservative check on all stack data
  10595. while (checkStackAddr < threadInfo->mStartSP)
  10596. {
  10597. addr_target checkAddrArr[1024];
  10598. int numAddrsChecking = BF_MIN(1024, (int)((threadInfo->mStartSP - checkStackAddr) / sizeof(addr_target)));
  10599. ReadMemory(checkStackAddr, numAddrsChecking * sizeof(addr_target), checkAddrArr);
  10600. checkStackAddr += numAddrsChecking * sizeof(addr_target);
  10601. for (int addrIdx = 0; addrIdx < numAddrsChecking; addrIdx++)
  10602. {
  10603. addr_target checkAddr = checkAddrArr[addrIdx];
  10604. if ((checkAddr >= lowAddr) && (checkAddr < highAddr))
  10605. mDebugTarget->mHotHeap->MarkBlockReferenced(checkAddr);
  10606. }
  10607. }
  10608. }
  10609. auto mainModule = mDebugTarget->mTargetBinary;
  10610. for (auto entry : mainModule->mSymbolNameMap)
  10611. {
  10612. auto dwSymbol = entry->mValue;
  10613. addr_target checkAddr = dwSymbol->mAddress;
  10614. if ((checkAddr >= lowAddr) && (checkAddr < highAddr))
  10615. mDebugTarget->mHotHeap->MarkBlockReferenced(checkAddr);
  10616. }
  10617. mDebugTarget->CleanupHotHeap();
  10618. BfLogDbg("Hot load memory used: %dk\n", (int)mDebugTarget->mHotHeap->GetUsedSize() / 1024);
  10619. }
  10620. int WinDebugger::EnableWriting(intptr address, int size)
  10621. {
  10622. DWORD oldProt;
  10623. bool success = ::VirtualProtectEx(mProcessInfo.hProcess, (void*)(intptr)address, size, PAGE_READWRITE, &oldProt);
  10624. if (!success)
  10625. {
  10626. int err = GetLastError();
  10627. }
  10628. return (int)oldProt;
  10629. }
  10630. int WinDebugger::SetProtection(intptr address, int size, int prot)
  10631. {
  10632. DWORD oldProt;
  10633. ::VirtualProtectEx(mProcessInfo.hProcess, (void*)(intptr)address, size, prot, &oldProt);
  10634. return (int)oldProt;
  10635. }
  10636. void WinDebugger::EnableMemCache()
  10637. {
  10638. mMemCacheAddr = 1;
  10639. }
  10640. void WinDebugger::DisableMemCache()
  10641. {
  10642. mMemCacheAddr = 0;
  10643. }
  10644. bool WinDebugger::ReadMemory(intptr address, uint64 length, void* dest, bool local)
  10645. {
  10646. if (local)
  10647. {
  10648. __try
  10649. {
  10650. memcpy(dest, (void*)address, length);
  10651. return true;
  10652. }
  10653. __except(EXCEPTION_EXECUTE_HANDLER)
  10654. {
  10655. return false;
  10656. }
  10657. }
  10658. if (mMemCacheAddr != 0)
  10659. {
  10660. addr_target targetAddr = (addr_target)address;
  10661. if ((targetAddr >= mMemCacheAddr) && (targetAddr + length <= mMemCacheAddr + WD_MEMCACHE_SIZE) && (mMemCacheAddr > 1))
  10662. {
  10663. memcpy(dest, mMemCacheData + (targetAddr - mMemCacheAddr), length);
  10664. return true;
  10665. }
  10666. // We need a new block
  10667. SIZE_T dwReadBytes;
  10668. if (::ReadProcessMemory(mProcessInfo.hProcess, (void*)(intptr)address, mMemCacheData, (SIZE_T)WD_MEMCACHE_SIZE, &dwReadBytes) != 0)
  10669. {
  10670. mMemCacheAddr = targetAddr;
  10671. memcpy(dest, mMemCacheData, length);
  10672. return true;
  10673. }
  10674. // Failed, turn off caching
  10675. mMemCacheAddr = 0;
  10676. }
  10677. SIZE_T dwReadBytes;
  10678. if (::ReadProcessMemory(mProcessInfo.hProcess, (void*)(intptr)address, dest, (SIZE_T)length, &dwReadBytes) != 0)
  10679. return true;
  10680. int lastErr = ::GetLastError();
  10681. memset(dest, 0, length);
  10682. return false;
  10683. }
  10684. bool WinDebugger::WriteMemory(intptr address, void* src, uint64 length)
  10685. {
  10686. SIZE_T dwBytesWritten = 0;
  10687. int result = ::WriteProcessMemory(mProcessInfo.hProcess, (void*)(intptr)address, src, (SIZE_T)length, &dwBytesWritten);
  10688. return result != 0;
  10689. }
  10690. addr_target WinDebugger::GetTLSOffset(int tlsIndex)
  10691. {
  10692. typedef LONG NTSTATUS;
  10693. typedef DWORD KPRIORITY;
  10694. typedef WORD UWORD;
  10695. enum THREADINFOCLASS
  10696. {
  10697. ThreadBasicInformation,
  10698. };
  10699. struct CLIENT_ID
  10700. {
  10701. HANDLE UniqueProcess;
  10702. HANDLE UniqueThread;
  10703. };
  10704. struct
  10705. {
  10706. NTSTATUS mExitStatus;
  10707. void* mTebBaseAddress;
  10708. CLIENT_ID mClientId;
  10709. KAFFINITY mAffinityMask;
  10710. KPRIORITY mPriority;
  10711. KPRIORITY mBasePriority;
  10712. } threadInfo = { 0 };
  10713. ULONG len = 0;
  10714. bool loadedManually = false;
  10715. static HMODULE module = NULL;
  10716. static NTSTATUS(__stdcall *NtQueryInformationThread)(HANDLE ThreadHandle, THREADINFOCLASS ThreadInformationClass, PVOID ThreadInformation, ULONG ThreadInformationLength, PULONG ReturnLength);
  10717. if (module == NULL)
  10718. {
  10719. module = GetModuleHandleA("ntdll.dll");
  10720. NtQueryInformationThread = reinterpret_cast<decltype(NtQueryInformationThread)>(GetProcAddress(module, "NtQueryInformationThread"));
  10721. }
  10722. if (NtQueryInformationThread == NULL)
  10723. return 0;
  10724. NTSTATUS status = NtQueryInformationThread(mActiveThread->mHThread, (THREADINFOCLASS)0, &threadInfo, sizeof(threadInfo), nullptr);
  10725. if (status < 0)
  10726. return 0;
  10727. #ifdef BF_DBG_32
  10728. addr_target tibAddr = ReadMemory<addr_target>((intptr)threadInfo.mTebBaseAddress + 0x0);
  10729. addr_target tlsTable = ReadMemory<addr_target>((intptr)tibAddr + 0x2C);
  10730. #else
  10731. addr_target tlsTable = ReadMemory<addr_target>((intptr)threadInfo.mTebBaseAddress + 0x58);
  10732. #endif
  10733. return ReadMemory<addr_target>(tlsTable + tlsIndex * sizeof(addr_target));
  10734. }
  10735. bool WinDebugger::WriteInstructions(intptr address, void* src, uint64 length)
  10736. {
  10737. SIZE_T dwBytesWritten = 0;
  10738. bool result = ::WriteProcessMemory(mProcessInfo.hProcess, (void*)(intptr)address, src, (SIZE_T)length, &dwBytesWritten) != 0;
  10739. result |= ::FlushInstructionCache(mProcessInfo.hProcess, (void*)(intptr)address, (SIZE_T)length) != 0;
  10740. BF_ASSERT(result);
  10741. BfLogDbg("WriteInstructions: %p %d\n", address, length);
  10742. return result;
  10743. }
  10744. DbgMemoryFlags WinDebugger::GetMemoryFlags(intptr address)
  10745. {
  10746. MEMORY_BASIC_INFORMATION memBasicInfo;
  10747. if (::VirtualQueryEx(mProcessInfo.hProcess, (void*)address, &memBasicInfo, sizeof(MEMORY_BASIC_INFORMATION)) == 0)
  10748. {
  10749. //BfLogDbg("VirtualQueryEx failed with %d\n", GetLastError());
  10750. return DbgMemoryFlags_None;
  10751. }
  10752. DbgMemoryFlags flags = DbgMemoryFlags_None;
  10753. if (memBasicInfo.AllocationProtect & PAGE_READWRITE)
  10754. {
  10755. flags = (DbgMemoryFlags)(flags | DbgMemoryFlags_Read);
  10756. flags = (DbgMemoryFlags)(flags | DbgMemoryFlags_Write);
  10757. }
  10758. if (memBasicInfo.AllocationProtect & PAGE_READONLY)
  10759. flags = (DbgMemoryFlags)(flags | DbgMemoryFlags_Read);
  10760. if (memBasicInfo.AllocationProtect & PAGE_WRITECOPY)
  10761. flags = (DbgMemoryFlags)(flags | DbgMemoryFlags_Write);
  10762. if (memBasicInfo.AllocationProtect & PAGE_EXECUTE)
  10763. flags = (DbgMemoryFlags)(flags | DbgMemoryFlags_Execute);
  10764. if (memBasicInfo.AllocationProtect & PAGE_EXECUTE_READ)
  10765. {
  10766. flags = (DbgMemoryFlags)(flags | DbgMemoryFlags_Execute);
  10767. flags = (DbgMemoryFlags)(flags | DbgMemoryFlags_Read);
  10768. }
  10769. if (memBasicInfo.AllocationProtect & PAGE_EXECUTE_READWRITE)
  10770. {
  10771. flags = (DbgMemoryFlags)(flags | DbgMemoryFlags_Execute);
  10772. flags = (DbgMemoryFlags)(flags | DbgMemoryFlags_Read);
  10773. flags = (DbgMemoryFlags)(flags | DbgMemoryFlags_Write);
  10774. }
  10775. if (memBasicInfo.AllocationProtect & PAGE_EXECUTE_WRITECOPY)
  10776. {
  10777. flags = (DbgMemoryFlags)(flags | DbgMemoryFlags_Execute);
  10778. flags = (DbgMemoryFlags)(flags | DbgMemoryFlags_Write);
  10779. }
  10780. return flags;
  10781. }
  10782. #ifdef BF_DBG_32
  10783. Debugger* Beefy::CreateDebugger32(DebugManager* debugManager, DbgMiniDump* miniDump)
  10784. #else
  10785. Debugger* Beefy::CreateDebugger64(DebugManager* debugManager, DbgMiniDump* miniDump)
  10786. #endif
  10787. {
  10788. if (miniDump != NULL)
  10789. {
  10790. auto debugger = new MiniDumpDebugger(debugManager, miniDump);
  10791. return debugger;
  10792. }
  10793. return new WinDebugger(debugManager);
  10794. }
  10795. #ifdef BF_DBG_32
  10796. void WdAllocTest()
  10797. {
  10798. Array<BeefyDbg32::WdStackFrame*> stackFrameList;
  10799. for (int i = 0; true; i++)
  10800. {
  10801. WdStackFrame* stackFrame = new WdStackFrame();
  10802. stackFrameList.push_back(stackFrame);
  10803. }
  10804. }
  10805. #endif
  10806. #endif //!defined BF32 || !defined BF_DBG_64
  10807. //ab