CeDebugger.cpp 116 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239
  1. #include "CeDebugger.h"
  2. #include "CeMachine.h"
  3. #include "BfCompiler.h"
  4. #include "../DebugManager.h"
  5. #include "BeefySysLib/util/BeefPerf.h"
  6. #include "BfParser.h"
  7. #include "BfReducer.h"
  8. #include "BeefySysLib/util/UTF8.h"
  9. #include "BfUtil.h"
  10. #include "BfExprEvaluator.h"
  11. #include "BeefySysLib/util/BitSet.h"
  12. #include "../DebugVisualizers.h"
  13. USING_NS_BF;
  14. static addr_ce DecodeTargetDataPtr(const char*& strRef)
  15. {
  16. addr_ce val = (addr_ce)stouln(strRef, sizeof(addr_ce) * 2);
  17. strRef += sizeof(addr_ce) * 2;
  18. return val;
  19. }
  20. //////////////////////////////////////////////////////////////////////////
  21. CePendingExpr::CePendingExpr()
  22. {
  23. mThreadId = -1;
  24. mCallStackIdx = -1;
  25. mParser = NULL;
  26. mCursorPos = -1;
  27. mExprNode = NULL;
  28. mIdleTicks = 0;
  29. mExplitType = NULL;
  30. mExpressionFlags = DwEvalExpressionFlag_None;
  31. }
  32. CePendingExpr::~CePendingExpr()
  33. {
  34. delete mParser;
  35. }
  36. //////////////////////////////////////////////////////////////////////////
  37. CeEvaluationContext::CeEvaluationContext(CeDebugger* winDebugger, const StringImpl& expr, CeFormatInfo* formatInfo, BfTypedValue contextValue)
  38. {
  39. Init(winDebugger, expr, formatInfo, contextValue);
  40. }
  41. void CeEvaluationContext::Init(CeDebugger* ceDebugger, const StringImpl& expr, CeFormatInfo* formatInfo, BfTypedValue contextValue)
  42. {
  43. mDebugger = ceDebugger;
  44. mCallStackIdx = 0;
  45. mParser = NULL;
  46. mReducer = NULL;
  47. mPassInstance = NULL;
  48. mExprEvaluator = NULL;
  49. mExprNode = NULL;
  50. if (expr.empty())
  51. return;
  52. int atPos = (int)expr.IndexOf('@');
  53. if ((atPos != -1) && (atPos < expr.mLength - 2) && (expr[atPos + 1] == '0') && (expr[atPos + 2] == 'x'))
  54. {
  55. bool isValid = true;
  56. for (int i = 0; i < atPos; i++)
  57. {
  58. char c = expr[i];
  59. if ((c < '0') || (c > '9'))
  60. {
  61. isValid = false;
  62. break;
  63. }
  64. }
  65. if (isValid)
  66. {
  67. int parseLength = expr.mLength;
  68. for (int i = 0; i < expr.mLength; i++)
  69. {
  70. if ((expr[i] == ',') || (::isspace((uint8)expr[i])))
  71. {
  72. parseLength = i;
  73. break;
  74. }
  75. }
  76. mExprString = expr.Substring(0, parseLength);
  77. String typeIdStr = expr.Substring(0, atPos);
  78. String addrStr = expr.Substring(atPos + 3, parseLength - atPos - 3);
  79. int typeId = strtol(typeIdStr.c_str(), NULL, 10);
  80. int64 addrVal = strtoll(addrStr.c_str(), NULL, 16);
  81. if ((typeId != 0) && (addrVal != 0))
  82. {
  83. auto type = ceDebugger->mCompiler->mContext->FindTypeById(typeId);
  84. if (type != NULL)
  85. {
  86. auto module = ceDebugger->mCeMachine->mCeModule;
  87. if (type->IsObjectOrInterface())
  88. {
  89. mResultOverride = BfTypedValue(module->mBfIRBuilder->CreateIntToPtr(
  90. module->mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, (uint64)addrVal), module->mBfIRBuilder->MapType(type)), type);
  91. }
  92. else
  93. {
  94. mResultOverride = BfTypedValue(module->mBfIRBuilder->CreateConstAggCE(module->mBfIRBuilder->MapType(type), (addr_ce)addrVal), type, true);
  95. }
  96. }
  97. }
  98. return;
  99. }
  100. }
  101. mParser = new BfParser(ceDebugger->mCompiler->mSystem);
  102. mPassInstance = new BfPassInstance(ceDebugger->mCompiler->mSystem);
  103. auto terminatedExpr = expr + ";";
  104. mParser->SetSource(terminatedExpr.c_str(), (int)terminatedExpr.length());
  105. mParser->Parse(mPassInstance);
  106. mReducer = new BfReducer();
  107. mReducer->mAlloc = mParser->mAlloc;
  108. mReducer->mSystem = ceDebugger->mCompiler->mSystem;
  109. mReducer->mPassInstance = mPassInstance;
  110. mReducer->mVisitorPos = BfReducer::BfVisitorPos(mParser->mRootNode);
  111. mReducer->mVisitorPos.MoveNext();
  112. mReducer->mSource = mParser;
  113. mExprNode = mReducer->CreateExpression(mParser->mRootNode->GetFirst());
  114. mParser->Close();
  115. mExprEvaluator = new BfExprEvaluator(ceDebugger->mCeMachine->mCeModule);
  116. if ((formatInfo != NULL) && (mExprNode != NULL) && (mExprNode->GetSrcEnd() < (int)expr.length()))
  117. {
  118. String formatFlags = expr.Substring(mExprNode->GetSrcEnd());
  119. String errorString = "Invalid expression";
  120. if (!ceDebugger->ParseFormatInfo(formatFlags, formatInfo, mPassInstance, NULL, NULL, &errorString, contextValue))
  121. {
  122. mPassInstance->FailAt(errorString, mParser->mSourceData, mExprNode->GetSrcEnd(), (int)expr.length() - mExprNode->GetSrcEnd());
  123. formatFlags = "";
  124. }
  125. }
  126. if (formatInfo != NULL)
  127. {
  128. mExplicitThis = formatInfo->mExplicitThis;
  129. mCallStackIdx = formatInfo->mCallStackIdx;
  130. }
  131. mExprNode->ToString(mExprString);
  132. }
  133. bool CeEvaluationContext::HasExpression()
  134. {
  135. return !mExprString.IsEmpty();
  136. }
  137. CeEvaluationContext::~CeEvaluationContext()
  138. {
  139. delete mParser;
  140. delete mReducer;
  141. delete mExprEvaluator;
  142. delete mPassInstance;
  143. }
  144. BfTypedValue CeEvaluationContext::EvaluateInContext(BfTypedValue contextTypedValue)
  145. {
  146. if (mResultOverride)
  147. return mResultOverride;
  148. if (mExprNode == NULL)
  149. return BfTypedValue();
  150. mPassInstance->ClearErrors();
  151. auto ceFrame = mDebugger->GetFrame(mCallStackIdx);
  152. auto module = mDebugger->mCeMachine->mCeModule;
  153. SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(module->mCurTypeInstance, ceFrame->mFunction->mMethodInstance->GetOwner());
  154. SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(module->mCurMethodInstance, ceFrame->mFunction->mMethodInstance);
  155. SetAndRestoreValue<BfPassInstance*> prevPassInstance(mDebugger->mCompiler->mPassInstance, mPassInstance);
  156. SetAndRestoreValue<bool> prevIgnoreWrites(module->mBfIRBuilder->mIgnoreWrites, true);
  157. BfMethodState methodState;
  158. SetAndRestoreValue<BfMethodState*> prevMethodState(module->mCurMethodState, &methodState);
  159. methodState.mTempKind = module->mCurMethodInstance->mMethodDef->mIsStatic ? BfMethodState::TempKind_Static : BfMethodState::TempKind_NonStatic;
  160. CeDbgState dbgState;
  161. dbgState.mActiveFrame = ceFrame;
  162. dbgState.mCeContext = mDebugger->mCeMachine->mCurContext;
  163. if (contextTypedValue)
  164. dbgState.mExplicitThis = contextTypedValue;
  165. else
  166. dbgState.mExplicitThis = mExplicitThis;
  167. SetAndRestoreValue<CeDbgState*> prevDbgState(mDebugger->mCurDbgState, &dbgState);
  168. BfTypedValue exprResult;
  169. mExprEvaluator->VisitChildNoRef(mExprNode);
  170. auto result = mExprEvaluator->mResult;
  171. if ((result) && (!result.mType->IsComposite()))
  172. result = module->LoadValue(result);
  173. return result;
  174. }
  175. bool CeEvaluationContext::HadError()
  176. {
  177. return (mPassInstance != NULL) && (mPassInstance->mFailedIdx != 0);
  178. }
  179. String CeEvaluationContext::GetErrorStr()
  180. {
  181. if (mPassInstance == NULL)
  182. return "";
  183. String errorStr = mPassInstance->mErrors[0]->mError;
  184. if (mExprNode != NULL)
  185. {
  186. errorStr += ": ";
  187. errorStr += mExprNode->ToString();
  188. }
  189. return errorStr;
  190. }
  191. //////////////////////////////////////////////////////////////////////////
  192. CeDebugger::CeDebugger(DebugManager* debugManager, BfCompiler* bfCompiler)
  193. {
  194. mDebugManager = debugManager;
  195. mCompiler = bfCompiler;
  196. mCeMachine = bfCompiler->mCEMachine;
  197. mRunState = RunState_Running;
  198. mCeMachine->mDebugger = this;
  199. mCeMachine->mDebugEvent.Reset();
  200. mDebugPendingExpr = NULL;
  201. mCurDbgState = NULL;
  202. mBreakpointVersion = 0;
  203. mBreakpointCacheDirty = false;
  204. mBreakpointFramesDirty = false;
  205. mCurDisasmFuncId = 0;
  206. mActiveBreakpoint = NULL;
  207. mCurEvaluationContext = NULL;
  208. }
  209. CeDebugger::~CeDebugger()
  210. {
  211. mCeMachine->mDebugEvent.Set(true);
  212. mCeMachine->mDebugger = NULL;
  213. delete mDebugPendingExpr;
  214. for (auto breakpoint : mBreakpoints)
  215. delete breakpoint;
  216. for (auto kv : mFileInfo)
  217. delete kv.mValue;
  218. }
  219. void CeDebugger::OutputMessage(const StringImpl& msg)
  220. {
  221. if (this == NULL)
  222. return;
  223. AutoCrit autoCrit(mDebugManager->mCritSect);
  224. mDebugManager->mOutMessages.push_back("msg " + msg);
  225. }
  226. void CeDebugger::OutputRawMessage(const StringImpl& msg)
  227. {
  228. if (this == NULL)
  229. return;
  230. AutoCrit autoCrit(mDebugManager->mCritSect);
  231. mDebugManager->mOutMessages.push_back(msg);
  232. }
  233. int CeDebugger::GetAddrSize()
  234. {
  235. return sizeof(addr_ce);
  236. }
  237. bool CeDebugger::CanOpen(const StringImpl& fileName, DebuggerResult* outResult)
  238. {
  239. return false;
  240. }
  241. void CeDebugger::OpenFile(const StringImpl& launchPath, const StringImpl& targetPath, const StringImpl& args, const StringImpl& workingDir, const Array<uint8>& envBlock, bool hotSwapEnabled)
  242. {
  243. }
  244. bool CeDebugger::Attach(int processId, BfDbgAttachFlags attachFlags)
  245. {
  246. return false;
  247. }
  248. void CeDebugger::Run()
  249. {
  250. }
  251. void CeDebugger::HotLoad(const Array<String>& objectFiles, int hotIdx)
  252. {
  253. }
  254. void CeDebugger::InitiateHotResolve(DbgHotResolveFlags flags)
  255. {
  256. }
  257. intptr CeDebugger::GetDbgAllocHeapSize()
  258. {
  259. return intptr();
  260. }
  261. String CeDebugger::GetDbgAllocInfo()
  262. {
  263. return String();
  264. }
  265. void CeDebugger::Update()
  266. {
  267. if ((mRunState == RunState_Terminated) || (mRunState == RunState_Terminating))
  268. return;
  269. AutoCrit autoCrit(mCeMachine->mCritSect);
  270. if (mCeMachine->mDbgPaused)
  271. {
  272. mRunState = RunState_Paused;
  273. }
  274. else
  275. {
  276. mRunState = RunState_Running;
  277. }
  278. }
  279. void CeDebugger::UpdateBreakpointFrames()
  280. {
  281. if (mBreakpointCacheDirty)
  282. UpdateBreakpointCache();
  283. for (auto& callStack : mCeMachine->mCurContext->mCallStack)
  284. {
  285. if (callStack.mFunction->mBreakpointVersion != mBreakpointVersion)
  286. UpdateBreakpoints(callStack.mFunction);
  287. }
  288. }
  289. void CeDebugger::ContinueDebugEvent()
  290. {
  291. mRunState = RunState_Running;
  292. mActiveBreakpoint = NULL;
  293. if (mBreakpointFramesDirty)
  294. UpdateBreakpointFrames();
  295. mCeMachine->mDebugEvent.Set();
  296. }
  297. void CeDebugger::ForegroundTarget()
  298. {
  299. }
  300. Breakpoint* CeDebugger::CreateBreakpoint(const StringImpl& fileName, int lineNum, int wantColumn, int instrOffset)
  301. {
  302. ClearBreakpointCache();
  303. auto breakpoint = new CeBreakpoint();
  304. breakpoint->mFilePath = fileName;
  305. breakpoint->mRequestedLineNum = lineNum;
  306. breakpoint->mLineNum = lineNum;
  307. breakpoint->mColumn = wantColumn;
  308. breakpoint->mInstrOffset = instrOffset;
  309. mBreakpoints.Add(breakpoint);
  310. mBreakpointVersion++;
  311. return breakpoint;
  312. }
  313. Breakpoint* CeDebugger::CreateMemoryBreakpoint(intptr addr, int byteCount)
  314. {
  315. return nullptr;
  316. }
  317. Breakpoint* CeDebugger::CreateSymbolBreakpoint(const StringImpl& symbolName)
  318. {
  319. return nullptr;
  320. }
  321. Breakpoint* CeDebugger::CreateAddressBreakpoint(intptr address)
  322. {
  323. return nullptr;
  324. }
  325. uintptr CeDebugger::GetBreakpointAddr(Breakpoint* breakpoint)
  326. {
  327. if (mBreakpointCacheDirty)
  328. {
  329. UpdateBreakpointCache();
  330. UpdateBreakpointAddrs();
  331. }
  332. return breakpoint->GetAddr();
  333. }
  334. void CeDebugger::CheckBreakpoint(Breakpoint* breakpoint)
  335. {
  336. }
  337. void CeDebugger::HotBindBreakpoint(Breakpoint* breakpoint, int lineNum, int hotIdx)
  338. {
  339. }
  340. int64 CeDebugger::ValueToInt(const BfTypedValue& typedVal)
  341. {
  342. auto constant = mCeMachine->mCeModule->mBfIRBuilder->GetConstant(typedVal.mValue);
  343. if (constant == NULL)
  344. return 0;
  345. if (typedVal.IsAddr())
  346. {
  347. BfType* type = typedVal.mType;
  348. if (type->IsTypedPrimitive())
  349. type = type->GetUnderlyingType();
  350. if ((type->IsInteger()) || (type->IsBoolean()))
  351. {
  352. auto primType = (BfPrimitiveType*)type;
  353. auto ceTypedVal = GetAddr(constant);
  354. if (ceTypedVal)
  355. {
  356. auto ceContext = mCeMachine->mCurContext;
  357. int64 val = 0;
  358. memcpy(&val, ceContext->mMemory.mVals + ceTypedVal.mAddr, type->mSize);
  359. switch (primType->mTypeDef->mTypeCode)
  360. {
  361. case BfTypeCode_Int8:
  362. val = *(int8*)&val;
  363. break;
  364. case BfTypeCode_Int16:
  365. val = *(int8*)&val;
  366. break;
  367. case BfTypeCode_Int32:
  368. val = *(int8*)&val;
  369. break;
  370. }
  371. return val;
  372. }
  373. }
  374. return 0;
  375. }
  376. if ((BfIRConstHolder::IsInt(constant->mTypeCode)) || (constant->mTypeCode == BfTypeCode_Boolean))
  377. return constant->mInt64;
  378. return 0;
  379. }
  380. void CeDebugger::DeleteBreakpoint(Breakpoint* breakpoint)
  381. {
  382. if (mActiveBreakpoint == breakpoint)
  383. mActiveBreakpoint = NULL;
  384. mBreakpoints.Remove((CeBreakpoint*)breakpoint);
  385. delete breakpoint;
  386. ClearBreakpointCache();
  387. }
  388. void CeDebugger::DetachBreakpoint(Breakpoint* breakpoint)
  389. {
  390. }
  391. void CeDebugger::MoveBreakpoint(Breakpoint* breakpoint, int lineNum, int wantColumn, bool rebindNow)
  392. {
  393. breakpoint->mLineNum = lineNum;
  394. breakpoint->mColumn = wantColumn;
  395. ClearBreakpointCache();
  396. }
  397. void CeDebugger::MoveMemoryBreakpoint(Breakpoint* breakpoint, intptr addr, int byteCount)
  398. {
  399. }
  400. void CeDebugger::DisableBreakpoint(Breakpoint* breakpoint)
  401. {
  402. }
  403. void CeDebugger::SetBreakpointCondition(Breakpoint* breakpoint, const StringImpl& condition)
  404. {
  405. }
  406. void CeDebugger::SetBreakpointLogging(Breakpoint* breakpoint, const StringImpl& logging, bool breakAfterLogging)
  407. {
  408. }
  409. Breakpoint* CeDebugger::FindBreakpointAt(intptr address)
  410. {
  411. return nullptr;
  412. }
  413. Breakpoint* CeDebugger::GetActiveBreakpoint()
  414. {
  415. return mActiveBreakpoint;
  416. }
  417. void CeDebugger::BreakAll()
  418. {
  419. mCeMachine->mSpecialCheck = true;
  420. mCeMachine->mDbgWantBreak = true;
  421. }
  422. bool CeDebugger::TryRunContinue()
  423. {
  424. return false;
  425. }
  426. bool CeDebugger::SetupStep(int frameIdx)
  427. {
  428. auto ceFrame = GetFrame(frameIdx);
  429. if (ceFrame == NULL)
  430. {
  431. ContinueDebugEvent();
  432. return false;
  433. }
  434. int entryIdx = 0;
  435. auto curEntry = ceFrame->mFunction->FindEmitEntry(ceFrame->GetInstIdx(), &entryIdx);
  436. if (curEntry == NULL)
  437. {
  438. ContinueDebugEvent();
  439. return false;
  440. }
  441. auto ceMachine = mCeMachine;
  442. auto ceContext = mCeMachine->mCurContext;
  443. if (entryIdx < ceFrame->mFunction->mEmitTable.mSize - 1)
  444. {
  445. int checkIdx = entryIdx + 1;
  446. while (checkIdx < ceFrame->mFunction->mEmitTable.mSize)
  447. {
  448. auto checkEntry = &ceFrame->mFunction->mEmitTable[checkIdx];
  449. ceMachine->mStepState.mNextInstIdx = checkEntry->mCodePos;
  450. if ((checkEntry->mScope != curEntry->mScope) || (checkEntry->mLine != curEntry->mLine))
  451. break;
  452. ++checkIdx;
  453. }
  454. }
  455. else
  456. ceMachine->mStepState.mNextInstIdx = ceFrame->mFunction->mCode.mSize;
  457. ceMachine->mStepState.mStartDepth = ceContext->mCallStack.mSize - frameIdx;
  458. ceMachine->mSpecialCheck = true;
  459. ContinueDebugEvent();
  460. return true;
  461. }
  462. void CeDebugger::StepInto(bool inAssembly)
  463. {
  464. if (!SetupStep())
  465. return;
  466. mCeMachine->mStepState.mKind = inAssembly ? CeStepState::Kind_StepInfo_Asm : CeStepState::Kind_StepInfo;
  467. }
  468. void CeDebugger::StepIntoSpecific(intptr addr)
  469. {
  470. }
  471. void CeDebugger::StepOver(bool inAssembly)
  472. {
  473. if (!SetupStep())
  474. return;
  475. mCeMachine->mStepState.mKind = inAssembly ? CeStepState::Kind_StepOver_Asm : CeStepState::Kind_StepOver;
  476. }
  477. void CeDebugger::StepOut(bool inAssembly)
  478. {
  479. if (!SetupStep(1))
  480. return;
  481. mCeMachine->mStepState.mKind = inAssembly ? CeStepState::Kind_StepOut_Asm : CeStepState::Kind_StepOut;
  482. }
  483. void CeDebugger::SetNextStatement(bool inAssembly, const StringImpl& fileName, int64 lineNumOrAsmAddr, int wantColumn)
  484. {
  485. auto ceFrame = GetFrame(0);
  486. if (ceFrame == NULL)
  487. return;
  488. if (inAssembly)
  489. {
  490. int32 instIdx = (int32)lineNumOrAsmAddr;
  491. if (instIdx < ceFrame->mFunction->mCode.mSize)
  492. {
  493. mCeMachine->mSpecialCheck = true;
  494. mCeMachine->mStepState.mKind = CeStepState::Kind_Jmp;
  495. mCeMachine->mStepState.mNextInstIdx = instIdx;
  496. ContinueDebugEvent();
  497. }
  498. }
  499. else
  500. {
  501. for (auto& emitEntry : ceFrame->mFunction->mEmitTable)
  502. {
  503. if (emitEntry.mScope == -1)
  504. continue;
  505. auto& scope = ceFrame->mFunction->mDbgScopes[emitEntry.mScope];
  506. if ((FileNameEquals(fileName, scope.mFilePath) && (emitEntry.mLine == lineNumOrAsmAddr)))
  507. {
  508. mCeMachine->mSpecialCheck = true;
  509. mCeMachine->mStepState.mKind = CeStepState::Kind_Jmp;
  510. mCeMachine->mStepState.mNextInstIdx = emitEntry.mCodePos;
  511. ContinueDebugEvent();
  512. return;
  513. }
  514. }
  515. }
  516. }
  517. CeFrame* CeDebugger::GetFrame(int callStackIdx)
  518. {
  519. auto ceContext = mCeMachine->mCurContext;
  520. if (ceContext == NULL)
  521. return NULL;
  522. if (callStackIdx < ceContext->mCallStack.mSize)
  523. {
  524. int stackIdx = ceContext->mCallStack.mSize - callStackIdx - 1;
  525. auto ceFrame = &ceContext->mCallStack[stackIdx];
  526. return ceFrame;
  527. }
  528. return NULL;
  529. }
  530. String CeDebugger::EvaluateContinue(CePendingExpr* pendingExpr, BfPassInstance& bfPassInstance)
  531. {
  532. auto ceFrame = GetFrame(pendingExpr->mCallStackIdx);
  533. if (ceFrame == NULL)
  534. {
  535. return "!failed";
  536. }
  537. if (pendingExpr->mExprNode == NULL)
  538. {
  539. return "!failed";
  540. }
  541. auto module = mCeMachine->mCeModule;
  542. SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(module->mCurTypeInstance, ceFrame->mFunction->mMethodInstance->GetOwner());
  543. SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(module->mCurMethodInstance, ceFrame->mFunction->mMethodInstance);
  544. SetAndRestoreValue<BfPassInstance*> prevPassInstance(mCompiler->mPassInstance, &bfPassInstance);
  545. SetAndRestoreValue<bool> prevIgnoreWrites(module->mBfIRBuilder->mIgnoreWrites, true);
  546. BfMethodState methodState;
  547. SetAndRestoreValue<BfMethodState*> prevMethodState(module->mCurMethodState, &methodState);
  548. methodState.mTempKind = module->mCurMethodInstance->mMethodDef->mIsStatic ? BfMethodState::TempKind_Static : BfMethodState::TempKind_NonStatic;
  549. CeDbgState dbgState;
  550. dbgState.mActiveFrame = ceFrame;
  551. dbgState.mCeContext = mCeMachine->mCurContext;
  552. dbgState.mExplicitThis = pendingExpr->mFormatInfo.mExplicitThis;
  553. dbgState.mDbgExpressionFlags = pendingExpr->mExpressionFlags;
  554. SetAndRestoreValue<CeDbgState*> prevDbgState(mCurDbgState, &dbgState);
  555. BfTypedValue exprResult;
  556. if (auto typeRef = BfNodeDynCast<BfTypeReference>(pendingExpr->mExprNode))
  557. {
  558. auto resultType = mCeMachine->mCeModule->ResolveTypeRef(typeRef);
  559. if (resultType != NULL)
  560. exprResult = BfTypedValue(resultType);
  561. }
  562. else
  563. {
  564. BfExprEvaluator exprEvaluator(mCeMachine->mCeModule);
  565. exprEvaluator.mBfEvalExprFlags = (BfEvalExprFlags)(exprEvaluator.mBfEvalExprFlags | BfEvalExprFlags_Comptime);
  566. exprEvaluator.VisitChildNoRef(pendingExpr->mExprNode);
  567. exprResult = exprEvaluator.mResult;
  568. if ((exprResult) && (!exprResult.mType->IsComposite()))
  569. exprResult = module->LoadValue(exprResult);
  570. }
  571. if (dbgState.mBlockedSideEffects)
  572. return "!sideeffects";
  573. if (!exprResult)
  574. {
  575. auto resultType = mCeMachine->mCeModule->ResolveTypeRef(pendingExpr->mExprNode, {}, BfPopulateType_Data, BfResolveTypeRefFlag_IgnoreLookupError);
  576. if (resultType != NULL)
  577. {
  578. exprResult = BfTypedValue(resultType);
  579. bfPassInstance.ClearErrors();
  580. }
  581. }
  582. String val;
  583. if (bfPassInstance.HasFailed())
  584. {
  585. BfLogDbgExpr("Evaluate Failed: %s\n", bfPassInstance.mErrors[0]->mError.c_str());
  586. val = StrFormat("!%d\t%d\t%s", bfPassInstance.mErrors[0]->GetSrcStart(), bfPassInstance.mErrors[0]->GetSrcLength(), bfPassInstance.mErrors[0]->mError.c_str());
  587. }
  588. else
  589. {
  590. val = TypedValueToString(exprResult, pendingExpr->mExprNode->ToString(), pendingExpr->mFormatInfo, (pendingExpr->mExpressionFlags & DwEvalExpressionFlag_FullPrecision) != 0);
  591. if ((!val.empty()) && (val[0] == '!'))
  592. return val;
  593. if (pendingExpr->mFormatInfo.mRawString)
  594. return val;
  595. if (bfPassInstance.HasMessages())
  596. {
  597. for (auto error : bfPassInstance.mErrors)
  598. {
  599. if (error->mIsWarning)
  600. {
  601. val += "\n:warn\t";
  602. val += error->mError;
  603. }
  604. }
  605. }
  606. if (!pendingExpr->mFormatInfo.mReferenceId.empty())
  607. val += "\n:referenceId\t" + pendingExpr->mFormatInfo.mReferenceId;
  608. // if ((exprResult.mSrcAddress != 0) && (HasMemoryBreakpoint(exprResult.mSrcAddress, exprResult.mType->GetByteCount())))
  609. // val += StrFormat("\n:break\t%@", exprResult.mSrcAddress);
  610. auto checkType = exprResult.mType;
  611. if (checkType->IsObject())
  612. val += "\n:type\tobject";
  613. else if (checkType->IsPointer())
  614. val += "\n:type\tpointer";
  615. else if (checkType->IsInteger())
  616. val += "\n:type\tint";
  617. else if (checkType->IsFloat())
  618. val += "\n:type\tfloat";
  619. }
  620. if (dbgState.mHadSideEffects)
  621. val += "\n:sideeffects";
  622. auto resultConstant = module->mBfIRBuilder->GetConstant(exprResult.mValue);
  623. if (resultConstant != NULL)
  624. {
  625. auto ceResultTyped = GetAddr(resultConstant);
  626. if (ceResultTyped.mAddr != 0)
  627. val += "\n:canEdit";
  628. }
  629. return val;
  630. }
  631. String CeDebugger::Evaluate(const StringImpl& expr, CeFormatInfo formatInfo, int callStackIdx, int cursorPos, int language, DwEvalExpressionFlags expressionFlags)
  632. {
  633. BP_ZONE_F("WinDebugger::Evaluate %s", BP_DYN_STR(expr.c_str()));
  634. AutoCrit autoCrit(mCeMachine->mCritSect);
  635. if ((expressionFlags & DwEvalExpressionFlag_RawStr) != 0)
  636. {
  637. formatInfo.mRawString = true;
  638. }
  639. bool valIsAddr = false;
  640. BfParser* parser = new BfParser(mCompiler->mSystem);
  641. BfPassInstance bfPassInstance(mCompiler->mSystem);
  642. auto parseAsType = false;
  643. auto terminatedExpr = expr;
  644. terminatedExpr.Trim();
  645. if (terminatedExpr.EndsWith(">"))
  646. parseAsType = true;
  647. else if ((terminatedExpr.StartsWith("comptype(")) && (!terminatedExpr.Contains('.')))
  648. parseAsType = true;
  649. if (!parseAsType)
  650. terminatedExpr += ";";
  651. if ((terminatedExpr.length() > 2) && (terminatedExpr[0] == '@'))
  652. {
  653. if (terminatedExpr[1] == '!') // Return string as error
  654. {
  655. int errorEnd = (int)terminatedExpr.IndexOf("@!", 2);
  656. if (errorEnd != -1)
  657. return terminatedExpr.Substring(1, errorEnd - 1);
  658. else
  659. return terminatedExpr.Substring(1);
  660. }
  661. else if (terminatedExpr[1] == '>') // Return string as text
  662. {
  663. int errorEnd = (int)terminatedExpr.IndexOf("@>", 2);
  664. if (errorEnd != -1)
  665. return terminatedExpr.Substring(2, errorEnd - 1);
  666. else
  667. return terminatedExpr.Substring(2);
  668. }
  669. }
  670. parser->SetSource(terminatedExpr.c_str(), (int)terminatedExpr.length());
  671. parser->Parse(&bfPassInstance);
  672. BfReducer bfReducer;
  673. bfReducer.mAlloc = parser->mAlloc;
  674. bfReducer.mSystem = mCompiler->mSystem;
  675. bfReducer.mPassInstance = &bfPassInstance;
  676. bfReducer.mVisitorPos = BfReducer::BfVisitorPos(parser->mRootNode);
  677. bfReducer.mVisitorPos.MoveNext();
  678. bfReducer.mSource = parser;
  679. BfAstNode* exprNode = NULL;
  680. if (parseAsType)
  681. exprNode = bfReducer.CreateTypeRef(parser->mRootNode->mChildArr.GetAs<BfAstNode*>(0));
  682. else
  683. exprNode = bfReducer.CreateExpression(parser->mRootNode->mChildArr.GetAs<BfAstNode*>(0));
  684. parser->Close();
  685. formatInfo.mCallStackIdx = callStackIdx;
  686. CePendingExpr* pendingExpr = new CePendingExpr();
  687. pendingExpr->mParser = parser;
  688. pendingExpr->mCallStackIdx = callStackIdx;
  689. pendingExpr->mCursorPos = cursorPos;
  690. pendingExpr->mExpressionFlags = expressionFlags;
  691. pendingExpr->mExprNode = exprNode;
  692. BfType* explicitType = NULL;
  693. String formatFlags;
  694. String assignExpr;
  695. int assignExprOffset = -1;
  696. if ((exprNode != NULL) && (exprNode->GetSrcEnd() < (int)expr.length()))
  697. {
  698. int formatOffset = exprNode->GetSrcEnd();
  699. while (formatOffset < (int)expr.length())
  700. {
  701. char c = expr[formatOffset];
  702. if (c == ' ')
  703. formatOffset++;
  704. else
  705. break;
  706. }
  707. formatFlags = Trim(expr.Substring(formatOffset));
  708. bool isComplexType = false;
  709. for (char c : formatFlags)
  710. if (c == '>')
  711. isComplexType = true;
  712. if (isComplexType)
  713. {
  714. //explicitType = dbgModule->FindType(expr);
  715. }
  716. if ((explicitType == NULL) && (formatFlags.length() > 0))
  717. {
  718. String errorString = "Invalid expression";
  719. if (!ParseFormatInfo(formatFlags, &formatInfo, &bfPassInstance, &assignExprOffset, &assignExpr, &errorString))
  720. {
  721. if (formatInfo.mRawString)
  722. return "";
  723. bfPassInstance.FailAt(errorString, parser->mSourceData, exprNode->GetSrcEnd(), (int)expr.length() - exprNode->GetSrcEnd());
  724. formatFlags = "";
  725. }
  726. if (assignExprOffset != -1)
  727. assignExprOffset += formatOffset;
  728. }
  729. }
  730. if (assignExpr.length() > 0)
  731. {
  732. String newEvalStr = exprNode->ToString() + " = ";
  733. int errorOffset = (int)newEvalStr.length();
  734. newEvalStr += assignExpr;
  735. String result = Evaluate(newEvalStr, formatInfo, callStackIdx, cursorPos, language, expressionFlags);
  736. if (result[0] == '!')
  737. {
  738. int tabPos = (int)result.IndexOf('\t');
  739. if (tabPos > 0)
  740. {
  741. int errorStart = atoi(result.Substring(1, tabPos - 1).c_str());
  742. if (errorStart >= errorOffset)
  743. {
  744. result = StrFormat("!%d", errorStart - errorOffset + assignExprOffset) + result.Substring(tabPos);
  745. }
  746. }
  747. }
  748. return result;
  749. }
  750. pendingExpr->mExplitType = explicitType;
  751. pendingExpr->mFormatInfo = formatInfo;
  752. String result = EvaluateContinue(pendingExpr, bfPassInstance);
  753. if (result == "!pending")
  754. {
  755. BF_ASSERT(mDebugPendingExpr == NULL);
  756. if (mDebugPendingExpr != NULL)
  757. {
  758. return "!retry"; // We already have a pending
  759. }
  760. mDebugPendingExpr = pendingExpr;
  761. }
  762. else
  763. delete pendingExpr;
  764. return result;
  765. }
  766. void CeDebugger::ClearBreakpointCache()
  767. {
  768. if (!mCeMachine->mDbgPaused)
  769. mCeMachine->mSpecialCheck = true;
  770. mBreakpointFramesDirty = true;
  771. mBreakpointCacheDirty = true;
  772. for (auto kv : mFileInfo)
  773. delete kv.mValue;
  774. mFileInfo.Clear();
  775. }
  776. void CeDebugger::UpdateBreakpointAddrs()
  777. {
  778. for (auto breakpoint : mBreakpoints)
  779. {
  780. breakpoint->mCurBindAddr = 1;
  781. }
  782. CeFunction* ceFunction = NULL;
  783. if (!mCeMachine->mFunctionIdMap.TryGetValue(mCurDisasmFuncId, &ceFunction))
  784. return;
  785. if (ceFunction->mBreakpointVersion != mBreakpointVersion)
  786. UpdateBreakpoints(ceFunction);
  787. for (auto kv : ceFunction->mBreakpoints)
  788. kv.mValue.mBreakpoint->mCurBindAddr = ((intptr)ceFunction->mId << 32) | kv.mKey;
  789. }
  790. void CeDebugger::UpdateBreakpointCache()
  791. {
  792. AutoCrit autoCrit(mCeMachine->mCritSect);
  793. mBreakpointCacheDirty = false;
  794. if (!mFileInfo.IsEmpty())
  795. return;
  796. for (int i = 0; i < (int)mBreakpoints.mSize; i++)
  797. {
  798. auto breakpoint = mBreakpoints[i];
  799. breakpoint->mIdx = i;
  800. String fileName = breakpoint->mFilePath;
  801. fileName = FixPathAndCase(fileName);
  802. CeFileInfo** valuePtr;
  803. CeFileInfo* fileInfo = NULL;
  804. if (mFileInfo.TryAdd(fileName, NULL, &valuePtr))
  805. {
  806. fileInfo = new CeFileInfo();
  807. *valuePtr = fileInfo;
  808. }
  809. else
  810. fileInfo = *valuePtr;
  811. fileInfo->mOrderedBreakpoints.Add(breakpoint);
  812. }
  813. for (auto kv : mFileInfo)
  814. {
  815. kv.mValue->mOrderedBreakpoints.Sort([](CeBreakpoint* lhs, CeBreakpoint* rhs)
  816. {
  817. return lhs->mLineNum < rhs->mLineNum;
  818. });
  819. }
  820. }
  821. static int CompareBreakpoint(CeBreakpoint* breakpoint, const int& lineNum)
  822. {
  823. return breakpoint->mRequestedLineNum - lineNum;
  824. }
  825. void CeDebugger::UpdateBreakpoints(CeFunction* ceFunction)
  826. {
  827. AutoCrit autoCrit(mCeMachine->mCritSect);
  828. UpdateBreakpointCache();
  829. ceFunction->UnbindBreakpoints();
  830. String path;
  831. int scope = -1;
  832. CeFileInfo* ceFileInfo = NULL;
  833. BitSet usedBreakpointSet(mBreakpoints.mSize);
  834. for (auto& emitEntry : ceFunction->mEmitTable)
  835. {
  836. if (emitEntry.mScope != scope)
  837. {
  838. if (emitEntry.mScope != -1)
  839. {
  840. path = FixPathAndCase(ceFunction->mDbgScopes[emitEntry.mScope].mFilePath);
  841. if (!mFileInfo.TryGetValue(path, &ceFileInfo))
  842. ceFileInfo = NULL;
  843. }
  844. else
  845. ceFileInfo = NULL;
  846. scope = emitEntry.mScope;
  847. }
  848. if (ceFileInfo != NULL)
  849. {
  850. int idx = ceFileInfo->mOrderedBreakpoints.BinarySearchAlt<int>(emitEntry.mLine, CompareBreakpoint);
  851. if (idx < 0)
  852. idx = ~idx - 1;
  853. while (idx > 0)
  854. {
  855. auto breakpoint = ceFileInfo->mOrderedBreakpoints[idx - 1];
  856. if (breakpoint->mLineNum < emitEntry.mLine)
  857. break;
  858. idx--;
  859. }
  860. int tryBindCount = 0;
  861. int bestRequestedBindLine = 0;
  862. while ((idx >= 0) && (idx < ceFileInfo->mOrderedBreakpoints.mSize))
  863. {
  864. auto breakpoint = ceFileInfo->mOrderedBreakpoints[idx];
  865. if (usedBreakpointSet.IsSet(breakpoint->mIdx))
  866. {
  867. idx++;
  868. continue;
  869. }
  870. CeBreakpointBind* breakpointBind = NULL;
  871. if (tryBindCount > 0)
  872. {
  873. if (breakpoint->mRequestedLineNum > bestRequestedBindLine)
  874. break;
  875. }
  876. else
  877. {
  878. int lineDiff = emitEntry.mLine - breakpoint->mLineNum;
  879. if ((lineDiff < 0) || (lineDiff > 4))
  880. break;
  881. if ((breakpoint->mHasBound) && (lineDiff != 0))
  882. break;
  883. bestRequestedBindLine = breakpoint->mRequestedLineNum;
  884. }
  885. tryBindCount++;
  886. int codePos = emitEntry.mCodePos;
  887. if (breakpoint->mInstrOffset > 0)
  888. {
  889. int instrOffsetLeft = breakpoint->mInstrOffset;
  890. while (instrOffsetLeft > 0)
  891. {
  892. auto& opRef = *(CeOp*)(&ceFunction->mCode[codePos]);
  893. int instSize = mCeMachine->GetInstSize(ceFunction, codePos);
  894. codePos += instSize;
  895. instrOffsetLeft--;
  896. }
  897. }
  898. if (ceFunction->mBreakpoints.TryAdd(codePos, NULL, &breakpointBind))
  899. {
  900. usedBreakpointSet.Set(breakpoint->mIdx);
  901. breakpoint->mLineNum = emitEntry.mLine;
  902. breakpoint->mHasBound = true;
  903. auto& opRef = *(CeOp*)(&ceFunction->mCode[codePos]);
  904. breakpointBind->mPrevOpCode = opRef;
  905. breakpointBind->mBreakpoint = breakpoint;
  906. opRef = CeOp_DbgBreak;
  907. }
  908. idx++;
  909. }
  910. }
  911. }
  912. ceFunction->mBreakpointVersion = mBreakpointVersion;
  913. }
  914. CeDbgTypeInfo* CeDebugger::GetDbgTypeInfo(int typeId)
  915. {
  916. CeDbgTypeInfo* dbgTypeInfo = NULL;
  917. if (mDbgTypeInfoMap.TryAdd(typeId, NULL, &dbgTypeInfo))
  918. {
  919. auto type = mCeMachine->mCeModule->mContext->FindTypeById(typeId);
  920. if (type == NULL)
  921. {
  922. mDbgTypeInfoMap.Remove(typeId);
  923. return NULL;
  924. }
  925. dbgTypeInfo->mType = type;
  926. auto typeInst = type->ToTypeInstance();
  927. if (typeInst != NULL)
  928. {
  929. for (int fieldIdx = 0; fieldIdx < typeInst->mFieldInstances.mSize; fieldIdx++)
  930. {
  931. auto& fieldInst = typeInst->mFieldInstances[fieldIdx];
  932. if (fieldInst.mDataIdx > 0)
  933. {
  934. while (fieldInst.mDataIdx >= dbgTypeInfo->mFieldOffsets.mSize)
  935. dbgTypeInfo->mFieldOffsets.Add(CeDbgFieldEntry());
  936. dbgTypeInfo->mFieldOffsets[fieldInst.mDataIdx].mType = fieldInst.mResolvedType;
  937. dbgTypeInfo->mFieldOffsets[fieldInst.mDataIdx].mDataOffset = fieldInst.mDataOffset;
  938. }
  939. if (fieldInst.mConstIdx != -1)
  940. {
  941. auto constant = typeInst->mConstHolder->GetConstantById(fieldInst.mConstIdx);
  942. if ((constant != NULL) && (BfIRConstHolder::IsInt(constant->mTypeCode)))
  943. {
  944. CeDbgTypeInfo::ConstIntEntry constIntEntry;
  945. constIntEntry.mFieldIdx = fieldIdx;
  946. constIntEntry.mVal = constant->mInt64;
  947. dbgTypeInfo->mConstIntEntries.Add(constIntEntry);
  948. }
  949. }
  950. }
  951. }
  952. }
  953. return dbgTypeInfo;
  954. }
  955. CeDbgTypeInfo* CeDebugger::GetDbgTypeInfo(BfIRType irType)
  956. {
  957. if ((irType.mKind == BfIRTypeData::TypeKind_TypeId) || (irType.mKind == BfIRTypeData::TypeKind_TypeInstId))
  958. return GetDbgTypeInfo(irType.mId);
  959. if (irType.mKind == BfIRTypeData::TypeKind_TypeInstPtrId)
  960. {
  961. auto type = mCeMachine->mCeModule->mContext->FindTypeById(irType.mId);
  962. if (type->IsObjectOrInterface())
  963. return GetDbgTypeInfo(irType.mId);
  964. else
  965. return GetDbgTypeInfo(mCeMachine->mCeModule->CreatePointerType(type)->mTypeId);
  966. }
  967. return NULL;
  968. }
  969. static bool IsNormalChar(uint32 c)
  970. {
  971. return (c < 0x80);
  972. }
  973. template <typename T>
  974. static String IntTypeToString(T val, const StringImpl& name, DwDisplayInfo* displayInfo, CeFormatInfo& formatInfo)
  975. {
  976. auto intDisplayType = displayInfo->mIntDisplayType;
  977. if (formatInfo.mDisplayType == DwDisplayType_Decimal)
  978. intDisplayType = DwIntDisplayType_Decimal;
  979. else if (formatInfo.mDisplayType == DwDisplayType_HexUpper)
  980. intDisplayType = DwIntDisplayType_HexadecimalUpper;
  981. else if (formatInfo.mDisplayType == DwDisplayType_HexLower)
  982. intDisplayType = DwIntDisplayType_HexadecimalLower;
  983. if (intDisplayType == DwIntDisplayType_Binary)
  984. {
  985. String binary;
  986. for (int i = 0; i < sizeof(T) * 8; i++)
  987. {
  988. if ((i != 0) && (i % 4 == 0))
  989. binary = "'" + binary;
  990. if ((i != 0) && (i % 16 == 0))
  991. binary = "'" + binary;
  992. binary = ((val & ((T)1 << i)) ? "1" : "0") + binary;
  993. }
  994. return StrFormat("0b'%s\n%s", binary.c_str(), name.c_str());
  995. }
  996. if (intDisplayType == DwIntDisplayType_Octal)
  997. {
  998. String format;
  999. if (sizeof(T) == 8)
  1000. {
  1001. format = StrFormat("0o%%lo\n%s", name.c_str());
  1002. }
  1003. else
  1004. format = StrFormat("0o%%0%do\n%s", sizeof(val) * 2, name.c_str());
  1005. return StrFormat(format.c_str(), (std::make_unsigned<T>::type)(val));
  1006. }
  1007. if (intDisplayType == DwIntDisplayType_HexadecimalUpper)
  1008. {
  1009. String format;
  1010. if (sizeof(T) == 8)
  1011. {
  1012. format = StrFormat("0x%%l@\n%s", name.c_str());
  1013. }
  1014. else
  1015. format = StrFormat("0x%%0%dX\n%s", sizeof(val) * 2, name.c_str());
  1016. return StrFormat(format.c_str(), (std::make_unsigned<T>::type)(val));
  1017. }
  1018. //TODO: Implement HexadecimalLower
  1019. if (intDisplayType == DwIntDisplayType_HexadecimalLower)
  1020. {
  1021. String format;
  1022. if (sizeof(T) == 8)
  1023. {
  1024. format = StrFormat("0x%%l@\n%s", name.c_str());
  1025. }
  1026. else
  1027. format = StrFormat("0x%%0%dX\n%s", sizeof(val) * 2, name.c_str());
  1028. return StrFormat(format.c_str(), (std::make_unsigned<T>::type)(val));
  1029. }
  1030. if (std::is_unsigned<T>::value)
  1031. {
  1032. if (sizeof(T) == 8)
  1033. {
  1034. if (val > 0x7FFFFFFFF)
  1035. return StrFormat("%llu\n%s\n:editVal\t%lluUL", val, name.c_str(), val);
  1036. else
  1037. return StrFormat("%llu\n%s", val, name.c_str());
  1038. }
  1039. else
  1040. return StrFormat("%u\n%s", val, name.c_str());
  1041. }
  1042. else
  1043. {
  1044. if (sizeof(T) == 8)
  1045. {
  1046. if ((val > 0x7FFFFFFFF) || (val < -0x80000000LL))
  1047. return StrFormat("%lld\n%s\n:editVal\t%lldL", val, name.c_str(), val);
  1048. else
  1049. return StrFormat("%lld\n%s", val, name.c_str(), val);
  1050. }
  1051. else
  1052. return StrFormat("%d\n%s", val, name.c_str());
  1053. }
  1054. }
  1055. DwDisplayInfo* CeDebugger::GetDisplayInfo(const StringImpl& referenceId)
  1056. {
  1057. DwDisplayInfo* displayInfo = &mDebugManager->mDefaultDisplayInfo;
  1058. if (!referenceId.empty())
  1059. {
  1060. mDebugManager->mDisplayInfos.TryGetValue(referenceId, &displayInfo);
  1061. }
  1062. return displayInfo;
  1063. }
  1064. String CeDebugger::GetMemberList(BfType* type, addr_ce addr, addr_ce addrInst, bool isStatic)
  1065. {
  1066. auto typeInst = type->ToTypeInstance();
  1067. if (typeInst == NULL)
  1068. return "";
  1069. auto module = typeInst->mModule;
  1070. String retVal;
  1071. int fieldCount = 0;
  1072. if ((typeInst->mBaseType != NULL) &&
  1073. (!typeInst->mBaseType->IsInstanceOf(mCompiler->mBfObjectTypeDef)) &&
  1074. (!typeInst->mBaseType->IsInstanceOf(mCompiler->mValueTypeTypeDef)))
  1075. {
  1076. retVal += StrFormat("[base]\tthis,this=%d@0x%X, nd, na, nv", typeInst->mBaseType->mTypeId, addr);
  1077. fieldCount++;
  1078. }
  1079. auto ceContext = mCompiler->mCEMachine->mCurContext;
  1080. bool didStaticCtor = ceContext->mStaticCtorExecSet.Contains(type->mTypeId);
  1081. bool hasStaticFields = false;
  1082. for (auto& fieldInst : typeInst->mFieldInstances)
  1083. {
  1084. auto fieldDef = fieldInst.GetFieldDef();
  1085. if (fieldDef == NULL)
  1086. continue;
  1087. if (fieldDef->mIsStatic != isStatic)
  1088. {
  1089. if (fieldDef->mIsStatic)
  1090. hasStaticFields = true;
  1091. continue;
  1092. }
  1093. if (fieldCount > 0)
  1094. retVal += "\n";
  1095. retVal += fieldDef->mName;
  1096. if (fieldDef->mIsStatic)
  1097. {
  1098. if (didStaticCtor)
  1099. retVal += StrFormat("\tcomptype(%d).%s", type->mTypeId, fieldDef->mName.c_str());
  1100. else
  1101. retVal += StrFormat("\tcomptype(%d).%s", type->mTypeId, fieldDef->mName.c_str());
  1102. }
  1103. else
  1104. {
  1105. retVal += "\t";
  1106. retVal += fieldDef->mName;
  1107. retVal += StrFormat(",this=%d@0x%X", typeInst->mTypeId, addrInst);
  1108. }
  1109. fieldCount++;
  1110. }
  1111. if (hasStaticFields)
  1112. {
  1113. if (fieldCount > 0)
  1114. retVal += "\n";
  1115. retVal += StrFormat("Static values\tcomptype(%d)", typeInst->mTypeId);
  1116. }
  1117. return retVal;
  1118. }
  1119. bool CeDebugger::ParseFormatInfo(const StringImpl& formatInfoStr, CeFormatInfo* formatInfo, BfPassInstance* bfPassInstance, int* assignExprOffset, String* assignExprString, String* errorString, BfTypedValue contextTypedValue)
  1120. {
  1121. String formatFlags = formatInfoStr;
  1122. if (assignExprOffset != NULL)
  1123. *assignExprOffset = -1;
  1124. while (formatFlags.length() > 0)
  1125. {
  1126. formatFlags = Trim(formatFlags);
  1127. if (formatFlags.IsEmpty())
  1128. break;
  1129. if (formatFlags[0] != ',')
  1130. {
  1131. return false;
  1132. }
  1133. else
  1134. {
  1135. int nextComma = (int)formatFlags.IndexOf(',', 1);
  1136. int quotePos = (int)formatFlags.IndexOf('"', 1);
  1137. if ((quotePos != -1) && (quotePos < nextComma))
  1138. {
  1139. int nextQuotePos = (int)formatFlags.IndexOf('"', quotePos + 1);
  1140. if (nextQuotePos != -1)
  1141. nextComma = (int)formatFlags.IndexOf(',', nextQuotePos + 1);
  1142. }
  1143. if (nextComma == -1)
  1144. nextComma = (int)formatFlags.length();
  1145. String formatCmd = formatFlags.Substring(1, nextComma - 1);
  1146. formatCmd = Trim(formatCmd);
  1147. bool hadError = false;
  1148. if (strncmp(formatCmd.c_str(), "this=", 5) == 0)
  1149. {
  1150. formatCmd = formatFlags.Substring(1);
  1151. formatCmd = Trim(formatCmd);
  1152. String thisExpr = formatCmd.Substring(5);
  1153. if (thisExpr.empty())
  1154. break;
  1155. CeEvaluationContext dbgEvaluationContext(this, thisExpr, formatInfo);
  1156. formatInfo->mExplicitThis = dbgEvaluationContext.EvaluateInContext(contextTypedValue);
  1157. if (dbgEvaluationContext.HadError())
  1158. {
  1159. if (errorString != NULL)
  1160. *errorString = dbgEvaluationContext.GetErrorStr();
  1161. return false;
  1162. }
  1163. formatFlags = thisExpr.Substring(dbgEvaluationContext.mExprString.GetLength());
  1164. continue;
  1165. }
  1166. else if (strncmp(formatCmd.c_str(), "count=", 6) == 0)
  1167. {
  1168. formatCmd = formatFlags.Substring(1);
  1169. formatCmd = Trim(formatCmd);
  1170. String countExpr = formatCmd.Substring(6);
  1171. if (countExpr.empty())
  1172. break;
  1173. CeEvaluationContext dbgEvaluationContext(this, countExpr, formatInfo);
  1174. BfTypedValue countValue = dbgEvaluationContext.EvaluateInContext(contextTypedValue);
  1175. if ((countValue) && (countValue.mType->IsInteger()))
  1176. formatInfo->mOverrideCount = (intptr)ValueToInt(countValue);
  1177. if (dbgEvaluationContext.HadError())
  1178. {
  1179. if (errorString != NULL)
  1180. *errorString = dbgEvaluationContext.GetErrorStr();
  1181. return false;
  1182. }
  1183. formatFlags = countExpr.Substring(dbgEvaluationContext.mExprString.GetLength());
  1184. continue;
  1185. }
  1186. else if (strncmp(formatCmd.c_str(), "maxcount=", 9) == 0)
  1187. {
  1188. formatCmd = formatFlags.Substring(1);
  1189. formatCmd = Trim(formatCmd);
  1190. String countExpr = formatCmd.Substring(9);
  1191. if (countExpr.empty())
  1192. break;
  1193. CeEvaluationContext dbgEvaluationContext(this, countExpr, formatInfo);
  1194. BfTypedValue countValue = dbgEvaluationContext.EvaluateInContext(contextTypedValue);
  1195. if ((countValue) && (countValue.mType->IsInteger()))
  1196. formatInfo->mMaxCount = (intptr)ValueToInt(countValue);
  1197. if (dbgEvaluationContext.HadError())
  1198. {
  1199. if (errorString != NULL)
  1200. *errorString = dbgEvaluationContext.GetErrorStr();
  1201. return false;
  1202. }
  1203. formatFlags = countExpr.Substring(dbgEvaluationContext.mExprString.GetLength());
  1204. continue;
  1205. }
  1206. else if (strncmp(formatCmd.c_str(), "arraysize=", 10) == 0)
  1207. {
  1208. formatCmd = formatFlags.Substring(1);
  1209. formatCmd = Trim(formatCmd);
  1210. String countExpr = formatCmd.Substring(10);
  1211. if (countExpr.empty())
  1212. break;
  1213. CeEvaluationContext dbgEvaluationContext(this, countExpr, formatInfo);
  1214. BfTypedValue countValue = dbgEvaluationContext.EvaluateInContext(contextTypedValue);
  1215. if ((countValue) && (countValue.mType->IsInteger()))
  1216. formatInfo->mArrayLength = (intptr)ValueToInt(countValue);
  1217. if (dbgEvaluationContext.HadError())
  1218. {
  1219. if (errorString != NULL)
  1220. *errorString = dbgEvaluationContext.GetErrorStr();
  1221. return false;
  1222. }
  1223. formatFlags = countExpr.Substring(dbgEvaluationContext.mExprString.GetLength());
  1224. continue;
  1225. }
  1226. else if (strncmp(formatCmd.c_str(), "assign=", 7) == 0)
  1227. {
  1228. formatCmd = formatFlags.Substring(1);
  1229. formatCmd = Trim(formatCmd);
  1230. String assignExpr = formatCmd.Substring(7);
  1231. if (assignExpr.empty())
  1232. break;
  1233. CeEvaluationContext dbgEvaluationContext(this, assignExpr, formatInfo);
  1234. if (dbgEvaluationContext.HadError())
  1235. {
  1236. if (errorString != NULL)
  1237. *errorString = dbgEvaluationContext.GetErrorStr();
  1238. return false;
  1239. }
  1240. if (assignExprOffset != NULL)
  1241. {
  1242. //TODO: Keep track of the offset directly, this is a hack
  1243. *assignExprOffset = (int)formatInfoStr.IndexOf("assign=") + 7;
  1244. }
  1245. if (assignExprString != NULL)
  1246. *assignExprString = dbgEvaluationContext.mExprNode->ToString();
  1247. formatFlags = assignExpr.Substring(dbgEvaluationContext.mExprNode->GetSrcEnd());
  1248. continue;
  1249. }
  1250. else if (strncmp(formatCmd.c_str(), "refid=", 6) == 0)
  1251. {
  1252. formatInfo->mReferenceId = formatCmd.Substring(6);
  1253. if (formatInfo->mReferenceId[0] == '\"')
  1254. formatInfo->mReferenceId = formatInfo->mReferenceId.Substring(1, formatInfo->mReferenceId.length() - 2);
  1255. }
  1256. else if (strncmp(formatCmd.c_str(), "_=", 2) == 0)
  1257. {
  1258. formatInfo->mSubjectExpr = formatCmd.Substring(2);
  1259. if (formatInfo->mSubjectExpr[0] == '\"')
  1260. formatInfo->mSubjectExpr = formatInfo->mSubjectExpr.Substring(1, formatInfo->mSubjectExpr.length() - 2);
  1261. }
  1262. else if (strncmp(formatCmd.c_str(), "expectedType=", 13) == 0)
  1263. {
  1264. formatInfo->mExpectedType = formatCmd.Substring(13);
  1265. if (formatInfo->mExpectedType[0] == '\"')
  1266. formatInfo->mExpectedType = formatInfo->mExpectedType.Substring(1, formatInfo->mExpectedType.length() - 2);
  1267. }
  1268. else if (strncmp(formatCmd.c_str(), "namespaceSearch=", 16) == 0)
  1269. {
  1270. formatInfo->mNamespaceSearch = formatCmd.Substring(16);
  1271. if (formatInfo->mNamespaceSearch[0] == '\"')
  1272. formatInfo->mNamespaceSearch = formatInfo->mNamespaceSearch.Substring(1, formatInfo->mNamespaceSearch.length() - 2);
  1273. }
  1274. else if (formatCmd == "d")
  1275. {
  1276. formatInfo->mDisplayType = DwDisplayType_Decimal;
  1277. }
  1278. else if (formatCmd == "x")
  1279. {
  1280. formatInfo->mDisplayType = DwDisplayType_HexLower;
  1281. }
  1282. else if (formatCmd == "X")
  1283. {
  1284. formatInfo->mDisplayType = DwDisplayType_HexUpper;
  1285. }
  1286. else if (formatCmd == "s")
  1287. {
  1288. formatInfo->mHidePointers = true;
  1289. formatInfo->mDisplayType = DwDisplayType_Ascii;
  1290. }
  1291. else if (formatCmd == "s8")
  1292. {
  1293. formatInfo->mHidePointers = true;
  1294. formatInfo->mDisplayType = DwDisplayType_Utf8;
  1295. }
  1296. else if (formatCmd == "s16")
  1297. {
  1298. formatInfo->mHidePointers = true;
  1299. formatInfo->mDisplayType = DwDisplayType_Utf16;
  1300. }
  1301. else if (formatCmd == "s32")
  1302. {
  1303. formatInfo->mHidePointers = true;
  1304. formatInfo->mDisplayType = DwDisplayType_Utf32;
  1305. }
  1306. else if (formatCmd == "nd")
  1307. {
  1308. formatInfo->mIgnoreDerivedClassInfo = true;
  1309. }
  1310. else if (formatCmd == "na")
  1311. {
  1312. formatInfo->mHidePointers = true;
  1313. }
  1314. else if (formatCmd == "nm")
  1315. {
  1316. formatInfo->mNoMembers = true;
  1317. }
  1318. else if (formatCmd == "ne")
  1319. {
  1320. formatInfo->mNoEdit = true;
  1321. }
  1322. else if (formatCmd == "nv")
  1323. {
  1324. formatInfo->mNoVisualizers = true;
  1325. }
  1326. else if (formatCmd == "rawStr")
  1327. {
  1328. formatInfo->mRawString = true;
  1329. }
  1330. else if (((!formatCmd.IsEmpty()) && ((formatCmd[0] >= '0') && (formatCmd[0] <= '9'))) ||
  1331. (formatCmd.StartsWith("(")))
  1332. {
  1333. String countExpr = formatCmd;
  1334. if (countExpr.empty())
  1335. break;
  1336. CeEvaluationContext dbgEvaluationContext(this, countExpr, formatInfo);
  1337. BfTypedValue countValue = dbgEvaluationContext.EvaluateInContext(contextTypedValue);
  1338. if ((countValue) && (countValue.mType->IsInteger()))
  1339. formatInfo->mArrayLength = (intptr)ValueToInt(countValue);
  1340. if (dbgEvaluationContext.HadError())
  1341. {
  1342. if (errorString != NULL)
  1343. *errorString = dbgEvaluationContext.GetErrorStr();
  1344. return false;
  1345. }
  1346. formatFlags = dbgEvaluationContext.mExprString;
  1347. continue;
  1348. }
  1349. else
  1350. hadError = true;
  1351. if (hadError)
  1352. {
  1353. if (errorString != NULL)
  1354. *errorString = "Invalid format flags";
  1355. return false;
  1356. }
  1357. formatFlags = formatFlags.Substring(nextComma);
  1358. }
  1359. }
  1360. return true;
  1361. }
  1362. String CeDebugger::MaybeQuoteFormatInfoParam(const StringImpl& str)
  1363. {
  1364. bool needsQuote = false;
  1365. for (int i = 0; i < (int)str.length(); i++)
  1366. {
  1367. char c = str[i];
  1368. if (c == ',')
  1369. needsQuote = true;
  1370. }
  1371. if (!needsQuote)
  1372. return str;
  1373. String qStr = "\"";
  1374. qStr += str;
  1375. qStr += "\"";
  1376. return qStr;
  1377. }
  1378. BfTypedValue CeDebugger::EvaluateInContext(const BfTypedValue& contextTypedValue, const StringImpl& subExpr, CeFormatInfo* formatInfo, String* outReferenceId, String* outErrors)
  1379. {
  1380. CeEvaluationContext dbgEvaluationContext(this, subExpr, formatInfo, contextTypedValue);
  1381. // if (formatInfo != NULL)
  1382. // {
  1383. // dbgEvaluationContext.mDbgExprEvaluator->mSubjectExpr = formatInfo->mSubjectExpr;
  1384. // }
  1385. //dbgEvaluationContext.mDbgExprEvaluator->mReferenceId = outReferenceId;
  1386. SetAndRestoreValue<CeEvaluationContext*> prevEvalContext(mCurEvaluationContext, &dbgEvaluationContext);
  1387. //mCountResultOverride = -1;
  1388. auto result = dbgEvaluationContext.EvaluateInContext(contextTypedValue);
  1389. // if ((formatInfo != NULL) && (dbgEvaluationContext.mDbgExprEvaluator->mCountResultOverride != -1))
  1390. // formatInfo->mOverrideCount = dbgEvaluationContext.mDbgExprEvaluator->mCountResultOverride;
  1391. if (dbgEvaluationContext.mPassInstance->HasFailed())
  1392. {
  1393. if (outErrors != NULL)
  1394. {
  1395. int errIdx = 0;
  1396. for (auto err : dbgEvaluationContext.mPassInstance->mErrors)
  1397. {
  1398. if (errIdx > 0)
  1399. (*outErrors) += "\n";
  1400. (*outErrors) += err->mError;
  1401. errIdx++;
  1402. }
  1403. }
  1404. return BfTypedValue();
  1405. }
  1406. return result;
  1407. }
  1408. void CeDebugger::DbgVisFailed(DebugVisualizerEntry* debugVis, const StringImpl& evalString, const StringImpl& errors)
  1409. {
  1410. bool onlyMemError = errors.StartsWith("Failed to read") && !errors.Contains('\n');
  1411. if ((!debugVis->mShowedError) && (!onlyMemError))
  1412. {
  1413. debugVis->mShowedError = true;
  1414. String errStr = StrFormat("DbgVis '%s' failed while evaluating condition '%s'\n", debugVis->mName.c_str(), evalString.c_str());
  1415. String spacedErrors = errors;
  1416. spacedErrors.Insert(0, " ");
  1417. spacedErrors.Replace("\n", "\n ");
  1418. errStr += spacedErrors;
  1419. OutputMessage(errStr);
  1420. }
  1421. }
  1422. bool CeDebugger::EvalCondition(DebugVisualizerEntry* debugVis, BfTypedValue typedVal, CeFormatInfo& formatInfo, const StringImpl& condition, const Array<String>& dbgVisWildcardCaptures, String& errorStr)
  1423. {
  1424. auto ceModule = mCeMachine->mCeModule;
  1425. CeFormatInfo displayStrFormatInfo = formatInfo;
  1426. displayStrFormatInfo.mHidePointers = false;
  1427. displayStrFormatInfo.mRawString = false;
  1428. String errors;
  1429. const String conditionStr = mDebugManager->mDebugVisualizers->DoStringReplace(condition, dbgVisWildcardCaptures);
  1430. BfTypedValue evalResult = EvaluateInContext(typedVal, conditionStr, &displayStrFormatInfo, NULL, &errors);
  1431. if ((!evalResult) || (!evalResult.mType->IsBoolean()))
  1432. {
  1433. if (formatInfo.mRawString)
  1434. return false;
  1435. errorStr += "<DbgVis Failed>";
  1436. DbgVisFailed(debugVis, conditionStr, errors);
  1437. return false;
  1438. }
  1439. evalResult = ceModule->LoadValue(evalResult);
  1440. if (auto constant = ceModule->mBfIRBuilder->GetConstant(evalResult.mValue))
  1441. {
  1442. if (constant->mTypeCode == BfTypeCode_Boolean)
  1443. return constant->mBool;
  1444. }
  1445. return false;
  1446. }
  1447. String CeDebugger::GetArrayItems(DebugVisualizerEntry* debugVis, BfType* valueType, BfTypedValue& curNode, int& count, String* outContinuationData)
  1448. {
  1449. CeEvaluationContext conditionEvaluationContext(this, debugVis->mCondition);
  1450. auto ceModule = mCeMachine->mCeModule;
  1451. String addrs;
  1452. bool checkLeft = true;
  1453. addr_ce curNodeAddr = 0;
  1454. int usedCount = 0;
  1455. while (usedCount < count)
  1456. {
  1457. if ((!curNode) || (!curNode.mType->IsPointer()))
  1458. break;
  1459. curNode = ceModule->LoadValue(curNode);
  1460. BfTypedValue condVal = conditionEvaluationContext.EvaluateInContext(curNode);
  1461. if (!condVal)
  1462. break;
  1463. auto ceTypedVal = GetAddr(curNode);
  1464. if (!ceTypedVal)
  1465. break;
  1466. if (ValueToInt(condVal) != 0)
  1467. {
  1468. auto val = curNode;
  1469. if (valueType == NULL)
  1470. {
  1471. //String typeAddr = val.mType->ToStringRaw();
  1472. String typeAddr = StrFormat("comptype(%d)", val.mType->mTypeId);
  1473. // RPad
  1474. typeAddr.Append(' ', sizeof(addr_ce) * 2 - (int)typeAddr.length());
  1475. addrs += typeAddr;
  1476. }
  1477. String addr = EncodeDataPtr(ceTypedVal.mAddr, false);
  1478. addrs += addr;
  1479. usedCount++;
  1480. }
  1481. auto elemType = curNode.mType->GetUnderlyingType();
  1482. curNodeAddr = ceTypedVal.mAddr + elemType->GetStride();
  1483. curNode.mValue = ceModule->mBfIRBuilder->CreateIntToPtr(curNodeAddr, ceModule->mBfIRBuilder->MapType(curNode.mType));
  1484. }
  1485. count = usedCount;
  1486. if (outContinuationData != NULL)
  1487. {
  1488. *outContinuationData += EncodeDataPtr(debugVis, false) + EncodeDataPtr(valueType, false) +
  1489. EncodeDataPtr(curNode.mType, false) + EncodeDataPtr(curNodeAddr, false);
  1490. }
  1491. return addrs;
  1492. }
  1493. String CeDebugger::GetLinkedListItems(DebugVisualizerEntry* debugVis, addr_ce endNodePtr, BfType* valueType, BfTypedValue& curNode, int& count, String* outContinuationData)
  1494. {
  1495. CeEvaluationContext nextEvaluationContext(this, debugVis->mNextPointer);
  1496. CeEvaluationContext valueEvaluationContext(this, debugVis->mValuePointer);
  1497. String addrs;
  1498. bool checkLeft = true;
  1499. //TODO;
  1500. // int mapIdx;
  1501. // for (mapIdx = 0; mapIdx < count; mapIdx++)
  1502. // {
  1503. // if (curNode.mPtr == endNodePtr)
  1504. // break;
  1505. // BfTypedValue val = valueEvaluationContext.EvaluateInContext(curNode);
  1506. // if (!val)
  1507. // break;
  1508. // if (val.mPtr == 0)
  1509. // break;
  1510. //
  1511. // if (valueType == NULL)
  1512. // {
  1513. // String typeAddr = val.mType->ToStringRaw();
  1514. // // RPad
  1515. // typeAddr.Append(' ', sizeof(addr_ce) * 2 - typeAddr.length());
  1516. // addrs += typeAddr;
  1517. // }
  1518. //
  1519. // String addr = EncodeDataPtr(val.mPtr, false);
  1520. // addrs += addr;
  1521. //
  1522. // curNode = nextEvaluationContext.EvaluateInContext(curNode);
  1523. // }
  1524. // count = mapIdx;
  1525. //
  1526. // if (outContinuationData != NULL)
  1527. // {
  1528. // *outContinuationData += EncodeDataPtr(debugVis, false) + EncodeDataPtr(endNodePtr, false) + EncodeDataPtr(valueType, false) +
  1529. // EncodeDataPtr(curNode.mType, false) + EncodeDataPtr(curNode.mPtr, false);
  1530. // }
  1531. return addrs;
  1532. }
  1533. String CeDebugger::GetDictionaryItems(DebugVisualizerEntry* debugVis, BfTypedValue dictValue, int bucketIdx, int nodeIdx, int& count, String* outContinuationData)
  1534. {
  1535. CeEvaluationContext nextEvaluationContext(this, debugVis->mNextPointer);
  1536. BfTypedValue bucketsPtr = EvaluateInContext(dictValue, debugVis->mBuckets);
  1537. BfTypedValue entriesPtr = EvaluateInContext(dictValue, debugVis->mEntries);
  1538. if ((!bucketsPtr) || (!entriesPtr))
  1539. {
  1540. count = -1;
  1541. return "";
  1542. }
  1543. String addrs;
  1544. //TODO:
  1545. // int entrySize = entriesPtr.mType->mTypeParam->GetStride();
  1546. // int bucketIdxSize = bucketsPtr.mType->mTypeParam->GetStride();
  1547. //
  1548. // bool checkLeft = true;
  1549. //
  1550. // int encodeCount = 0;
  1551. // while (encodeCount < count)
  1552. // {
  1553. // if (nodeIdx != -1)
  1554. // {
  1555. // BfTypedValue entryValue;
  1556. // entryValue.mSrcAddress = entriesPtr.mPtr + (nodeIdx * entrySize);
  1557. // entryValue.mType = entriesPtr.mType->mTypeParam;
  1558. //
  1559. // addrs += EncodeDataPtr(entryValue.mSrcAddress, false);
  1560. //
  1561. // BfTypedValue nextValue = nextEvaluationContext.EvaluateInContext(entryValue);
  1562. // if ((!nextValue) || (!nextValue.mType->IsInteger()))
  1563. // {
  1564. // break;
  1565. // }
  1566. //
  1567. // nodeIdx = (int)nextValue.GetInt64();
  1568. // encodeCount++;
  1569. // }
  1570. // else
  1571. // {
  1572. // if (bucketIdxSize == 4)
  1573. // nodeIdx = ReadMemory<int>(bucketsPtr.mPtr + bucketIdx * sizeof(int32));
  1574. // else
  1575. // nodeIdx = (int)ReadMemory<int64>(bucketsPtr.mPtr + bucketIdx * sizeof(int64));
  1576. // bucketIdx++;
  1577. // }
  1578. // }
  1579. //
  1580. // count = encodeCount;
  1581. //
  1582. // if (outContinuationData != NULL)
  1583. // {
  1584. // *outContinuationData += EncodeDataPtr(debugVis, false) + EncodeDataPtr(dictValue.mType, false) + EncodeDataPtr(dictValue.mSrcAddress, false) +
  1585. // EncodeDataPtr((addr_ce)bucketIdx, false) + EncodeDataPtr((addr_ce)nodeIdx, false);
  1586. // }
  1587. return addrs;
  1588. }
  1589. String CeDebugger::GetTreeItems(DebugVisualizerEntry* debugVis, Array<addr_ce>& parentList, BfType*& valueType, BfTypedValue& curNode, int count, String* outContinuationData)
  1590. {
  1591. CeEvaluationContext leftEvaluationContext(this, debugVis->mLeftPointer);
  1592. CeEvaluationContext rightEvaluationContext(this, debugVis->mRightPointer);
  1593. CeEvaluationContext valueEvaluationContext(this, debugVis->mValuePointer);
  1594. CeEvaluationContext conditionEvaluationContext(this, debugVis->mCondition);
  1595. String addrs;
  1596. //TODO:
  1597. // bool checkLeft = true;
  1598. //
  1599. // if ((curNode.mPtr & 2) != 0) // Flag from continuation
  1600. // {
  1601. // checkLeft = false;
  1602. // curNode.mPtr &= (addr_ce)~2;
  1603. // }
  1604. //
  1605. // HashSet<intptr> seenAddrs;
  1606. //
  1607. // for (int mapIdx = 0; mapIdx < count; mapIdx++)
  1608. // {
  1609. // BfTypedValue readNode;
  1610. // while (true)
  1611. // {
  1612. // bool checkNode = (curNode.mPtr & 1) == 0;
  1613. //
  1614. // readNode = curNode;
  1615. // readNode.mPtr &= (addr_ce)~1;
  1616. //
  1617. // if (checkLeft)
  1618. // {
  1619. // BfTypedValue leftValue = leftEvaluationContext.EvaluateInContext(readNode);
  1620. // bool isEmpty = leftValue.mPtr == NULL;
  1621. // if ((leftValue) && (conditionEvaluationContext.HasExpression()))
  1622. // {
  1623. // auto condValue = conditionEvaluationContext.EvaluateInContext(leftValue);
  1624. // if (condValue)
  1625. // isEmpty = !condValue.mBool;
  1626. // }
  1627. // if (isEmpty)
  1628. // {
  1629. // checkLeft = false;
  1630. // break; // Handle node
  1631. // }
  1632. //
  1633. // parentList.push_back(curNode.mPtr);
  1634. // curNode = leftValue;
  1635. // }
  1636. // else if (checkNode)
  1637. // {
  1638. // break; // Handle node
  1639. // }
  1640. // else
  1641. // {
  1642. // BfTypedValue rightValue = rightEvaluationContext.EvaluateInContext(readNode);
  1643. // bool isEmpty = rightValue.mPtr == NULL;
  1644. // if ((rightValue) && (conditionEvaluationContext.HasExpression()))
  1645. // {
  1646. // auto condValue = conditionEvaluationContext.EvaluateInContext(rightValue);
  1647. // if (condValue)
  1648. // isEmpty = !condValue.mBool;
  1649. // }
  1650. // if (!isEmpty)
  1651. // {
  1652. // curNode = rightValue;
  1653. // checkLeft = true;
  1654. // }
  1655. // else
  1656. // {
  1657. // if (parentList.size() == 0)
  1658. // {
  1659. // // Failed
  1660. // break;
  1661. // }
  1662. //
  1663. // curNode.mPtr = parentList.back();
  1664. // parentList.pop_back();
  1665. // continue; // Don't check against seenAddrs
  1666. // }
  1667. // }
  1668. //
  1669. // if (!seenAddrs.Add(curNode.mPtr))
  1670. // {
  1671. // // Failed!
  1672. // return "";
  1673. // }
  1674. // }
  1675. //
  1676. //
  1677. // BfTypedValue val = valueEvaluationContext.EvaluateInContext(readNode);
  1678. // if (valueType == NULL)
  1679. // valueType = val.mType;
  1680. //
  1681. // String addr = EncodeDataPtr(val.mPtr, false);
  1682. // addrs += addr;
  1683. //
  1684. // curNode.mPtr |= 1; // Node handled
  1685. // }
  1686. //
  1687. // if (!checkLeft)
  1688. // curNode.mPtr |= 2;
  1689. //
  1690. // if (outContinuationData != NULL)
  1691. // {
  1692. // *outContinuationData += EncodeDataPtr(debugVis, false) + EncodeDataPtr(valueType, false) + EncodeDataPtr(curNode.mType, false) + EncodeDataPtr(curNode.mPtr, false);
  1693. // for (auto parent : parentList)
  1694. // *outContinuationData += EncodeDataPtr(parent, false);
  1695. // }
  1696. return addrs;
  1697. }
  1698. String CeDebugger::GetCollectionContinuation(const StringImpl& continuationData, int callStackIdx, int count)
  1699. {
  1700. if (!mCeMachine->mDbgPaused)
  1701. return "";
  1702. auto ceModule = mCeMachine->mCeModule;
  1703. const char* dataPtr = continuationData.c_str();
  1704. DebugVisualizerEntry* debugVis = (DebugVisualizerEntry*)DecodeLocalDataPtr(dataPtr);
  1705. if (debugVis->mCollectionType == DebugVisualizerEntry::CollectionType_TreeItems)
  1706. {
  1707. //TODO:
  1708. // DbgType* valueType = (DbgType*)DecodeLocalDataPtr(dataPtr);
  1709. // BfTypedValue curNode;
  1710. // curNode.mType = (DbgType*)DecodeLocalDataPtr(dataPtr);
  1711. // curNode.mPtr = DecodeTargetDataPtr(dataPtr);
  1712. //
  1713. // Array<addr_ce> parentList;
  1714. // String newContinuationData;
  1715. // while (*dataPtr != 0)
  1716. // parentList.push_back(DecodeTargetDataPtr(dataPtr));
  1717. //
  1718. // String retVal = GetTreeItems(dbgCompileUnit, debugVis, parentList, valueType, curNode, count, &newContinuationData);
  1719. // retVal += "\n" + newContinuationData;
  1720. // return retVal;
  1721. }
  1722. else if (debugVis->mCollectionType == DebugVisualizerEntry::CollectionType_LinkedList)
  1723. {
  1724. //TODO:
  1725. // addr_ce endNodePtr = DecodeTargetDataPtr(dataPtr);
  1726. // DbgType* valueType = (DbgType*)DecodeLocalDataPtr(dataPtr);
  1727. // BfTypedValue curNode;
  1728. // curNode.mType = (DbgType*)DecodeLocalDataPtr(dataPtr);
  1729. // curNode.mPtr = DecodeTargetDataPtr(dataPtr);
  1730. //
  1731. // String newContinuationData;
  1732. //
  1733. // if (count < 0)
  1734. // count = 3;
  1735. //
  1736. // String retVal = GetLinkedListItems(dbgCompileUnit, debugVis, endNodePtr, valueType, curNode, count, &newContinuationData);
  1737. // retVal += "\n" + newContinuationData;
  1738. // return retVal;
  1739. }
  1740. else if (debugVis->mCollectionType == DebugVisualizerEntry::CollectionType_Array)
  1741. {
  1742. BfType* valueType = (BfType*)DecodeLocalDataPtr(dataPtr);
  1743. auto nodeType = (BfType*)DecodeLocalDataPtr(dataPtr);
  1744. BfTypedValue curNode = BfTypedValue(
  1745. ceModule->mBfIRBuilder->CreateIntToPtr(DecodeTargetDataPtr(dataPtr), ceModule->mBfIRBuilder->MapType(nodeType)),
  1746. nodeType);
  1747. String newContinuationData;
  1748. if (count < 0)
  1749. count = 3;
  1750. String retVal = GetArrayItems(debugVis, valueType, curNode, count, &newContinuationData);
  1751. retVal += "\n" + newContinuationData;
  1752. return retVal;
  1753. }
  1754. else if (debugVis->mCollectionType == DebugVisualizerEntry::CollectionType_Dictionary)
  1755. {
  1756. //TODO:
  1757. // BfTypedValue dictValue;
  1758. // dictValue.mType = (DbgType*)DecodeLocalDataPtr(dataPtr);
  1759. // dictValue.mSrcAddress = DecodeTargetDataPtr(dataPtr);
  1760. //
  1761. // int bucketIdx = (int)DecodeTargetDataPtr(dataPtr);
  1762. // int nodeIdx = (int)DecodeTargetDataPtr(dataPtr);
  1763. //
  1764. // String newContinuationData;
  1765. // String retVal = GetDictionaryItems(dbgCompileUnit, debugVis, dictValue, bucketIdx, nodeIdx, count, &newContinuationData);
  1766. // retVal += "\n" + newContinuationData;
  1767. // return retVal;
  1768. }
  1769. return "";
  1770. }
  1771. CeTypedValue CeDebugger::GetAddr(BfConstant* constant)
  1772. {
  1773. auto module = mCeMachine->mCeModule;
  1774. auto ceContext = mCeMachine->mCurContext;
  1775. if (constant->mConstType == BfConstType_GlobalVar)
  1776. {
  1777. auto globalVar = (BfGlobalVar*)constant;
  1778. String varName(globalVar->mName);
  1779. if (varName.StartsWith("__bfStrObj"))
  1780. {
  1781. int stringId = atoi(varName.c_str() + 10);
  1782. auto addr = ceContext->GetString(stringId);
  1783. return CeTypedValue(addr, globalVar->mType);
  1784. }
  1785. else if (varName.StartsWith("__bfStrData"))
  1786. {
  1787. auto stringType = module->ResolveTypeDef(module->mCompiler->mStringTypeDef)->ToTypeInstance();
  1788. int stringId = atoi(varName.c_str() + 11);
  1789. auto addr = ceContext->GetString(stringId) + stringType->mInstSize;
  1790. return CeTypedValue(addr, globalVar->mType);
  1791. }
  1792. CeStaticFieldInfo* fieldInfo = NULL;
  1793. if (ceContext->mStaticFieldMap.TryAdd(globalVar->mName, NULL, &fieldInfo))
  1794. {
  1795. auto dbgTypeInfo = GetDbgTypeInfo(globalVar->mType);
  1796. if (dbgTypeInfo != NULL)
  1797. {
  1798. uint8* ptr = ceContext->CeMalloc(dbgTypeInfo->mType->mSize);
  1799. if (dbgTypeInfo->mType->mSize > 0)
  1800. memset(ptr, 0, dbgTypeInfo->mType->mSize);
  1801. fieldInfo->mAddr = (addr_ce)(ptr - ceContext->mMemory.mVals);
  1802. }
  1803. else
  1804. fieldInfo->mAddr = 0;
  1805. }
  1806. return CeTypedValue(fieldInfo->mAddr, globalVar->mType);
  1807. }
  1808. else if (constant->mConstType == BfConstType_AggCE)
  1809. {
  1810. auto aggCE = (BfConstantAggCE*)constant;
  1811. return CeTypedValue(aggCE->mCEAddr, aggCE->mType);
  1812. }
  1813. else if (constant->mConstType == BfConstType_BitCast)
  1814. {
  1815. auto constBitCast = (BfConstantBitCast*)constant;
  1816. auto val = GetAddr(module->mBfIRBuilder->GetConstantById(constBitCast->mTarget));
  1817. if (!val)
  1818. return val;
  1819. return CeTypedValue(val.mAddr, constBitCast->mToType);
  1820. }
  1821. else if (constant->mConstType == BfConstType_IntToPtr)
  1822. {
  1823. auto fromPtrToInt = (BfConstantIntToPtr*)constant;
  1824. auto val = GetAddr(module->mBfIRBuilder->GetConstantById(fromPtrToInt->mTarget));
  1825. if (!val)
  1826. return val;
  1827. return CeTypedValue(val.mAddr, fromPtrToInt->mToType);
  1828. }
  1829. else if (constant->mConstType == BfConstType_GEP32_1)
  1830. {
  1831. auto gepConst = (BfConstantGEP32_1*)constant;
  1832. auto constant = module->mBfIRBuilder->GetConstantById(gepConst->mTarget);
  1833. auto typedVal = GetAddr(constant);
  1834. if (!typedVal)
  1835. return CeTypedValue();
  1836. auto dbgTypeInfo = GetDbgTypeInfo(typedVal.mType);
  1837. if (dbgTypeInfo == NULL)
  1838. return CeTypedValue();
  1839. if (!dbgTypeInfo->mType->IsPointer())
  1840. {
  1841. NOP;
  1842. }
  1843. auto addr = typedVal.mAddr;
  1844. if (gepConst->mIdx0 != 0)
  1845. addr += gepConst->mIdx0 * dbgTypeInfo->mType->GetUnderlyingType()->GetStride();
  1846. return CeTypedValue(addr, module->mBfIRBuilder->MapType(dbgTypeInfo->mType));
  1847. }
  1848. else if (constant->mConstType == BfConstType_GEP32_2)
  1849. {
  1850. auto gepConst = (BfConstantGEP32_2*)constant;
  1851. auto constant = module->mBfIRBuilder->GetConstantById(gepConst->mTarget);
  1852. auto typedVal = GetAddr(constant);
  1853. if (!typedVal.mAddr)
  1854. return CeTypedValue();
  1855. auto dbgTypeInfo = GetDbgTypeInfo(typedVal.mType);
  1856. if ((dbgTypeInfo != NULL) && (dbgTypeInfo->mType->IsPointer()))
  1857. dbgTypeInfo = GetDbgTypeInfo(dbgTypeInfo->mType->GetUnderlyingType()->mTypeId);
  1858. if (dbgTypeInfo == NULL)
  1859. return CeTypedValue();
  1860. auto addr = typedVal.mAddr;
  1861. if (gepConst->mIdx0 != 0)
  1862. addr += gepConst->mIdx0 * dbgTypeInfo->mType->GetStride();
  1863. if (gepConst->mIdx1 != 0)
  1864. addr += dbgTypeInfo->mFieldOffsets[gepConst->mIdx1].mDataOffset;
  1865. auto ptrType = module->CreatePointerType(dbgTypeInfo->mFieldOffsets[gepConst->mIdx1].mType);
  1866. return CeTypedValue(addr, module->mBfIRBuilder->MapType(ptrType));
  1867. }
  1868. else if ((constant->mTypeCode == BfTypeCode_Int32) ||
  1869. (constant->mTypeCode == BfTypeCode_Int64) ||
  1870. (constant->mTypeCode == BfTypeCode_IntPtr))
  1871. {
  1872. return CeTypedValue((addr_ce)constant->mInt64, module->mBfIRBuilder->GetPrimitiveType(constant->mTypeCode));
  1873. }
  1874. return CeTypedValue();
  1875. }
  1876. CeTypedValue CeDebugger::GetAddr(const BfTypedValue typedVal)
  1877. {
  1878. auto constant = mCeMachine->mCeModule->mBfIRBuilder->GetConstant(typedVal.mValue);
  1879. if (constant == NULL)
  1880. return CeTypedValue();
  1881. return GetAddr(constant);
  1882. }
  1883. #define GET_FROM(ptr, T) *((T*)(ptr += sizeof(T)) - 1)
  1884. String CeDebugger::ReadString(BfTypeCode charType, intptr addr, intptr maxLength, CeFormatInfo& formatInfo)
  1885. {
  1886. int origMaxLength = (int)maxLength;
  1887. if (addr == 0)
  1888. return "";
  1889. BP_ZONE("WinDebugger::ReadString");
  1890. String retVal = "\"";
  1891. bool wasTerminated = false;
  1892. String valString;
  1893. intptr maxShowSize = 255;
  1894. if (maxLength == -1)
  1895. maxLength = formatInfo.mOverrideCount;
  1896. else if (formatInfo.mOverrideCount != -1)
  1897. maxLength = BF_MIN(formatInfo.mOverrideCount, maxLength);
  1898. if (formatInfo.mMaxCount != -1)
  1899. maxLength = BF_MIN(formatInfo.mMaxCount, maxLength);
  1900. if (maxLength == -1)
  1901. maxLength = 8 * 1024 * 1024; // Is 8MB crazy?
  1902. if (!formatInfo.mRawString)
  1903. maxLength = BF_MIN(maxLength, maxShowSize);
  1904. //EnableMemCache();
  1905. bool readFailed = false;
  1906. intptr strPtr = addr;
  1907. int charLen = 1;
  1908. if (charType == BfTypeCode_Char16)
  1909. charLen = 2;
  1910. else if (charType == BfTypeCode_Char32)
  1911. charLen = 4;
  1912. bool isUTF8 = formatInfo.mDisplayType == DwDisplayType_Utf8;
  1913. int readSize = BF_MIN(1024, (int)maxLength * charLen);
  1914. uint8 buf[1024];
  1915. uint8* bufPtr = NULL;
  1916. uint8* bufEnd = NULL;
  1917. bool hasHighAscii = false;
  1918. int i;
  1919. for (i = 0; i < maxLength; i++)
  1920. {
  1921. if (bufPtr >= bufEnd)
  1922. {
  1923. while (true)
  1924. {
  1925. if (readSize < charLen)
  1926. {
  1927. readFailed = true;
  1928. break;
  1929. }
  1930. if (ReadMemory(strPtr, readSize, buf))
  1931. break;
  1932. readSize /= 2;
  1933. }
  1934. if (readFailed)
  1935. break;
  1936. bufPtr = buf;
  1937. bufEnd = buf + readSize;
  1938. }
  1939. switch (charLen)
  1940. {
  1941. case 1:
  1942. {
  1943. char c = GET_FROM(bufPtr, char);
  1944. if ((c != 0) || (formatInfo.mOverrideCount != -1))
  1945. {
  1946. if ((uint8)c >= 0x80)
  1947. hasHighAscii = true;
  1948. valString.Append(c);
  1949. }
  1950. else
  1951. wasTerminated = true;
  1952. }
  1953. break;
  1954. case 2:
  1955. {
  1956. uint16 c16 = GET_FROM(bufPtr, uint16);
  1957. if ((c16 != 0) || (formatInfo.mOverrideCount != -1))
  1958. {
  1959. char str[8];
  1960. u8_toutf8(str, 8, c16);
  1961. valString += str;
  1962. }
  1963. else
  1964. wasTerminated = true;
  1965. }
  1966. break;
  1967. case 4:
  1968. {
  1969. uint32 c32 = GET_FROM(bufPtr, uint32);
  1970. if ((c32 != 0) || (formatInfo.mOverrideCount != -1))
  1971. {
  1972. char str[8];
  1973. u8_toutf8(str, 8, c32);
  1974. valString += str;
  1975. }
  1976. else
  1977. wasTerminated = true;
  1978. }
  1979. break;
  1980. }
  1981. if ((wasTerminated) && (formatInfo.mOverrideCount != -1))
  1982. {
  1983. valString += '\x00';
  1984. wasTerminated = false;
  1985. }
  1986. if ((wasTerminated) || (readFailed))
  1987. {
  1988. break;
  1989. }
  1990. strPtr += charLen;
  1991. }
  1992. //DisableMemCache();
  1993. if (formatInfo.mOverrideCount != -1)
  1994. {
  1995. if (i == formatInfo.mOverrideCount)
  1996. wasTerminated = true;
  1997. }
  1998. if (strPtr == addr + origMaxLength)
  1999. wasTerminated = true;
  2000. if (valString.length() == formatInfo.mOverrideCount)
  2001. wasTerminated = true;
  2002. // if (formatInfo.mDisplayType == DwDisplayType_Ascii)
  2003. // {
  2004. // // Our encoding for retVal is already assumed to be UTF8, so the special case here actually Ascii
  2005. // valString = UTF8Encode(ToWString(valString));
  2006. // }
  2007. if (formatInfo.mRawString)
  2008. {
  2009. if ((formatInfo.mDisplayType == DwDisplayType_Utf8) || (!hasHighAscii))
  2010. return valString;
  2011. String utf8Str;
  2012. for (int i = 0; i < (int)valString.length(); i++)
  2013. {
  2014. char c = valString[i];
  2015. if ((uint8)c >= 0x80)
  2016. {
  2017. utf8Str += (char)(0xC0 | (((uint8)c & 0xFF) >> 6));
  2018. utf8Str += (char)(0x80 | ((uint8)c & 0x3F));
  2019. }
  2020. else
  2021. utf8Str += c;
  2022. }
  2023. return utf8Str;
  2024. }
  2025. if ((readFailed) && (valString.IsEmpty()))
  2026. return "< Failed to read string >";
  2027. retVal += SlashString(valString, true, true, true);
  2028. // We could go over 'maxShowSize' if we have a lot of slashed chars. An uninitialized string can be filled with '\xcc' chars
  2029. if ((!formatInfo.mRawString) && ((int)retVal.length() > maxShowSize))
  2030. {
  2031. retVal = retVal.Substring(0, maxShowSize);
  2032. wasTerminated = false;
  2033. }
  2034. if (wasTerminated)
  2035. retVal += "\"";
  2036. else
  2037. retVal += "...";
  2038. return retVal;
  2039. }
  2040. void CeDebugger::ProcessEvalString(BfTypedValue useTypedValue, String& evalStr, String& displayString, CeFormatInfo& formatInfo, DebugVisualizerEntry* debugVis, bool limitLength)
  2041. {
  2042. for (int i = 0; i < (int)evalStr.length(); i++)
  2043. {
  2044. char c = evalStr[i];
  2045. char nextC = 0;
  2046. if (i < (int)evalStr.length() - 1)
  2047. nextC = evalStr[i + 1];
  2048. if ((c == '{') && (nextC != '{'))
  2049. {
  2050. // Evaluate
  2051. int endIdx = i;
  2052. for (; endIdx < (int)evalStr.length(); endIdx++)
  2053. {
  2054. //TODO: Do better parsing - this paren could be inside a string, for example
  2055. if (evalStr[endIdx] == '}')
  2056. break;
  2057. }
  2058. CeFormatInfo displayStrFormatInfo = formatInfo;
  2059. displayStrFormatInfo.mTotalSummaryLength = formatInfo.mTotalSummaryLength + (int)displayString.length();
  2060. displayStrFormatInfo.mHidePointers = false;
  2061. if ((limitLength) && (displayStrFormatInfo.mTotalSummaryLength > 255))
  2062. {
  2063. displayString += "...";
  2064. }
  2065. else
  2066. {
  2067. String evalString = evalStr.Substring(i + 1, endIdx - i - 1);
  2068. String errors;
  2069. BfTypedValue evalResult = EvaluateInContext(useTypedValue, evalString, &displayStrFormatInfo, NULL, &errors);
  2070. if (evalResult)
  2071. {
  2072. if (displayStrFormatInfo.mNoEdit)
  2073. formatInfo.mNoEdit = true;
  2074. String result = TypedValueToString(evalResult, evalString, displayStrFormatInfo, NULL);
  2075. if ((formatInfo.mRawString) && (limitLength))
  2076. {
  2077. displayString = result;
  2078. return;
  2079. }
  2080. int crPos = (int)result.IndexOf('\n');
  2081. if (crPos != -1)
  2082. displayString += result.Substring(0, crPos);
  2083. else
  2084. displayString += result;
  2085. }
  2086. else if (debugVis != NULL)
  2087. {
  2088. displayString += "<DbgVis Failed>";
  2089. DbgVisFailed(debugVis, evalString, errors);
  2090. }
  2091. else
  2092. {
  2093. displayString += "<Eval Failed>";
  2094. }
  2095. }
  2096. i = endIdx;
  2097. continue;
  2098. }
  2099. else if ((c == '{') && (nextC == '{'))
  2100. {
  2101. // Skip next paren
  2102. i++;
  2103. }
  2104. else if ((c == '}') && (nextC == '}'))
  2105. {
  2106. // Skip next paren
  2107. i++;
  2108. }
  2109. displayString += c;
  2110. }
  2111. }
  2112. String CeDebugger::TypedValueToString(const BfTypedValue& typedValue, const StringImpl& expr, CeFormatInfo& formatInfo, bool fullPrecision)
  2113. {
  2114. auto module = mCeMachine->mCeModule;
  2115. String retVal;
  2116. if (typedValue.IsNoValueType())
  2117. {
  2118. retVal += "\n";
  2119. retVal += module->TypeToString(typedValue.mType);
  2120. retVal += "\n";
  2121. retVal += GetMemberList(typedValue.mType, 0, 0, true);
  2122. return retVal;
  2123. }
  2124. auto constant = module->mBfIRBuilder->GetConstant(typedValue.mValue);
  2125. auto ceContext = mCeMachine->mCurContext;
  2126. if (constant == NULL)
  2127. {
  2128. return "!Invalid expression";
  2129. }
  2130. bool didAlloc = false;
  2131. addr_ce addr = 0;
  2132. defer(
  2133. {
  2134. if (didAlloc)
  2135. mCurDbgState->mCeContext->CeFree(addr);
  2136. }
  2137. );
  2138. if (constant->mConstType == BfConstType_AggCE)
  2139. {
  2140. auto aggCE = (BfConstantAggCE*)constant;
  2141. addr = aggCE->mCEAddr;
  2142. }
  2143. else if ((typedValue.IsAddr()) || (typedValue.mType->IsObjectOrInterface()) || (typedValue.mType->IsPointer()))
  2144. {
  2145. CeTypedValue typedVal = GetAddr(constant);
  2146. addr = typedVal.mAddr;
  2147. if (!typedVal)
  2148. {
  2149. return "!Invalid addr type";
  2150. }
  2151. }
  2152. else
  2153. {
  2154. int allocSize = typedValue.mType->mSize;
  2155. auto typeInst = typedValue.mType->ToTypeInstance();
  2156. if (typeInst != NULL)
  2157. allocSize = typeInst->mInstSize;
  2158. if (allocSize < 0)
  2159. return "!Invalid size";
  2160. addr = (addr_ce)(mCurDbgState->mCeContext->CeMalloc(allocSize) - mCurDbgState->mCeContext->mMemory.mVals);
  2161. didAlloc = true;
  2162. if (!mCurDbgState->mCeContext->WriteConstant(mCeMachine->mCeModule, addr, constant, typedValue.mType))
  2163. {
  2164. return StrFormat("!Failed to encode value");
  2165. }
  2166. }
  2167. DwDisplayInfo* displayInfo = GetDisplayInfo(formatInfo.mReferenceId);
  2168. char str[32];
  2169. String result;
  2170. auto memStart = mCurDbgState->mCeContext->mMemory.mVals;
  2171. int checkMemSize = typedValue.mType->mSize;
  2172. if (typedValue.mType->IsPointer())
  2173. checkMemSize = typedValue.mType->GetUnderlyingType()->mSize;
  2174. uint8* data = ceContext->GetMemoryPtr(addr, checkMemSize);
  2175. if ((addr != 0) && (data == NULL))
  2176. return "!Invalid address";
  2177. addr_ce dataAddr = addr;
  2178. if ((typedValue.IsAddr()) && (typedValue.mType->IsObjectOrInterface()))
  2179. dataAddr = *(addr_ce*)data;
  2180. if (formatInfo.mRawString)
  2181. {
  2182. //if ((dwValueType->mTypeCode != DbgType_Struct) && (dwValueType->mTypeCode != DbgType_Class) && (dwValueType->mTypeCode != DbgType_Ptr) && (dwValueType->mTypeCode != DbgType_SizedArray))
  2183. if ((!typedValue.mType->IsPointer()) && (!typedValue.mType->IsObjectOrStruct()) && (!typedValue.mType->IsStruct()) && (!typedValue.mType->IsSizedArray()))
  2184. return "";
  2185. }
  2186. auto _ShowArraySummary = [&](String& retVal, addr_ce ptrVal, int64 arraySize, BfType* innerType)
  2187. {
  2188. auto ptrType = module->CreatePointerType(innerType);
  2189. String displayString;
  2190. displayString += "{";
  2191. for (int idx = 0; idx < arraySize; idx++)
  2192. {
  2193. if (formatInfo.mTotalSummaryLength + retVal.length() + displayString.length() > 255)
  2194. {
  2195. displayString += "...";
  2196. break;
  2197. }
  2198. if ((idx != 0) && (!displayString.EndsWith('{')))
  2199. displayString += ", ";
  2200. CeFormatInfo displayStrFormatInfo = formatInfo;
  2201. displayStrFormatInfo.mExpandItemDepth = 1;
  2202. displayStrFormatInfo.mTotalSummaryLength = formatInfo.mTotalSummaryLength + (int)retVal.length() + (int)displayString.length();
  2203. displayStrFormatInfo.mHidePointers = false;
  2204. displayStrFormatInfo.mArrayLength = -1;
  2205. // Why did we have this "na" on here? It made "void*[3]" type things show up as "{,,}"
  2206. //String evalStr = "((" + innerType->ToStringRaw(language) + "*)" + EncodeDataPtr(ptrVal, true) + StrFormat(")[%d], na", idx);
  2207. String evalStr = StrFormat("((comptype(%d))(void*)", ptrType->mTypeId) + EncodeDataPtr(ptrVal, true) + StrFormat(")[%lld]", idx);
  2208. BfTypedValue evalResult = EvaluateInContext(typedValue, evalStr, &displayStrFormatInfo);
  2209. String result;
  2210. if (evalResult)
  2211. {
  2212. result = TypedValueToString(evalResult, evalStr, displayStrFormatInfo, NULL);
  2213. int crPos = (int)result.IndexOf('\n');
  2214. if (crPos != -1)
  2215. result.RemoveToEnd(crPos);
  2216. }
  2217. else
  2218. result = "???";
  2219. displayString += result;
  2220. }
  2221. displayString += "}";
  2222. retVal += displayString;
  2223. };
  2224. if (formatInfo.mArrayLength != -1)
  2225. {
  2226. if (formatInfo.mRawString)
  2227. return "";
  2228. if (typedValue.mType->IsPointer())
  2229. {
  2230. auto elementType = typedValue.mType->GetUnderlyingType();
  2231. String retVal;
  2232. addr_ce ptrVal = addr;
  2233. if (!formatInfo.mHidePointers)
  2234. {
  2235. retVal = EncodeDataPtr(ptrVal, true) + " ";
  2236. retVal += module->TypeToString(elementType);
  2237. retVal += StrFormat("[%lld] ", (int64)formatInfo.mArrayLength);
  2238. }
  2239. _ShowArraySummary(retVal, ptrVal, formatInfo.mArrayLength, elementType);
  2240. String idxStr = "[{0}]";
  2241. retVal += "\n" + module->TypeToString(typedValue.mType);
  2242. String evalStr = StrFormat("((comptype(%d))(void*)", typedValue.mType->mTypeId) + EncodeDataPtr(ptrVal, true) + ")[{0}]";
  2243. retVal += "\n:repeat" + StrFormat("\t%d\t%lld\t%d", 0, (int)BF_MAX(formatInfo.mArrayLength, 0), 10000) +
  2244. "\t" + idxStr + "\t" + evalStr;
  2245. return retVal;
  2246. }
  2247. else
  2248. {
  2249. CeFormatInfo newFormatInfo = formatInfo;
  2250. newFormatInfo.mArrayLength = -1;
  2251. String retVal = TypedValueToString(typedValue, expr, newFormatInfo);
  2252. int crPos = (int)retVal.IndexOf('\n');
  2253. if (crPos != -1)
  2254. retVal = "!Array length flag not valid with this type" + retVal.Substring(crPos);
  2255. return retVal;
  2256. }
  2257. }
  2258. if (typedValue.mType->IsPrimitiveType())
  2259. {
  2260. auto primType = (BfPrimitiveType*)typedValue.mType;
  2261. BfTypeCode typeCode = primType->mTypeDef->mTypeCode;
  2262. if (typeCode == BfTypeCode_IntPtr)
  2263. typeCode = (primType->mSize == 8) ? BfTypeCode_Int64 : BfTypeCode_Int32;
  2264. if (typeCode == BfTypeCode_UIntPtr)
  2265. typeCode = (primType->mSize == 8) ? BfTypeCode_UInt64 : BfTypeCode_UInt32;
  2266. switch (typeCode)
  2267. {
  2268. case BfTypeCode_Boolean:
  2269. {
  2270. auto val = *(uint8*)(data);
  2271. if (val == 0)
  2272. return "false\nbool";
  2273. else if (val == 1)
  2274. return "true\nbool";
  2275. else
  2276. return StrFormat("true (%d)\nbool", val);
  2277. }
  2278. break;
  2279. case BfTypeCode_Char8:
  2280. {
  2281. auto val = *(uint8*)(data);
  2282. if (val != 0)
  2283. {
  2284. char str[2] = { (char)val };
  2285. result = SlashString(str, formatInfo.mDisplayType == DwDisplayType_Utf8, true);
  2286. if (!IsNormalChar(val))
  2287. result = StrFormat("'%s' (0x%02X)\n", result.c_str(), val);
  2288. else
  2289. result = StrFormat("'%s'\n", result.c_str());
  2290. }
  2291. else
  2292. result = "'\\0'\n";
  2293. return result + "char";
  2294. }
  2295. break;
  2296. case BfTypeCode_Char16:
  2297. {
  2298. auto val = *(uint16*)(data);
  2299. if (val != 0)
  2300. {
  2301. u8_toutf8(str, 8, val);
  2302. result = SlashString(str, true, true);
  2303. if (!IsNormalChar(val))
  2304. result = StrFormat("'%s' (0x%02X)\n", result.c_str(), val);
  2305. else
  2306. result = StrFormat("'%s'\n", result.c_str());
  2307. }
  2308. else
  2309. result = "'\\0'\n";
  2310. return result + "char16";
  2311. }
  2312. break;
  2313. case BfTypeCode_Char32:
  2314. {
  2315. auto val = *(uint32*)(data);
  2316. if (val != 0)
  2317. {
  2318. u8_toutf8(str, 8, val);
  2319. result = SlashString(str, true, true);
  2320. if (!IsNormalChar(val))
  2321. result = StrFormat("'%s' (0x%02X)\n", result.c_str(), val);
  2322. else
  2323. result = StrFormat("'%s'\n", result.c_str());
  2324. }
  2325. else
  2326. result = "'\\0'\n";
  2327. return result + "char32";
  2328. }
  2329. break;
  2330. case BfTypeCode_Int8:
  2331. return IntTypeToString<int8>(*(int8*)(data), "int8", displayInfo, formatInfo);
  2332. case BfTypeCode_UInt8:
  2333. return IntTypeToString<uint8>(*(uint8*)(data), "uint8", displayInfo, formatInfo);
  2334. case BfTypeCode_Int16:
  2335. return IntTypeToString<int16>(*(int16*)(data), "int16", displayInfo, formatInfo);
  2336. case BfTypeCode_UInt16:
  2337. return IntTypeToString<uint16>(*(uint16*)(data), "uint16", displayInfo, formatInfo);
  2338. case BfTypeCode_Int32:
  2339. return IntTypeToString<int32>(*(int32*)(data), "int32", displayInfo, formatInfo);
  2340. case BfTypeCode_UInt32:
  2341. return IntTypeToString<uint32>(*(uint32*)(data), "uint32", displayInfo, formatInfo);
  2342. case BfTypeCode_Int64:
  2343. return IntTypeToString<int64>(*(int64*)(data), "int64", displayInfo, formatInfo);
  2344. case BfTypeCode_UInt64:
  2345. return IntTypeToString<uint64>(*(uint64*)(data), "uint64", displayInfo, formatInfo);
  2346. case BfTypeCode_Float:
  2347. {
  2348. DwFloatDisplayType floatDisplayType = displayInfo->mFloatDisplayType;
  2349. if (floatDisplayType == DwFloatDisplayType_Default)
  2350. floatDisplayType = DwFloatDisplayType_Minimal;
  2351. if (floatDisplayType == DwFloatDisplayType_Minimal)
  2352. ExactMinimalFloatToStr(*(float*)data, str);
  2353. else if (floatDisplayType == DwFloatDisplayType_Full)
  2354. sprintf(str, "%1.9g", *(float*)data);
  2355. else if (floatDisplayType == DwFloatDisplayType_HexUpper)
  2356. sprintf(str, "0x%04X", *(uint32*)data);
  2357. else //if (floatDisplayType == DwFloatDisplayType_HexLower)
  2358. sprintf(str, "0x%04x", *(uint32*)data);
  2359. return StrFormat("%s\n%s", str, "float");
  2360. }
  2361. case BfTypeCode_Double:
  2362. {
  2363. DwFloatDisplayType floatDisplayType = displayInfo->mFloatDisplayType;
  2364. if (floatDisplayType == DwFloatDisplayType_Default)
  2365. floatDisplayType = DwFloatDisplayType_Minimal;
  2366. if (floatDisplayType == DwFloatDisplayType_Minimal)
  2367. ExactMinimalDoubleToStr(*(double*)data, str);
  2368. else if (floatDisplayType == DwFloatDisplayType_Full)
  2369. sprintf(str, "%1.17g", *(double*)data);
  2370. else if (floatDisplayType == DwFloatDisplayType_HexUpper)
  2371. sprintf(str, "0x%08llX", *(uint64*)data);
  2372. else //if (floatDisplayType == DwFloatDisplayType_HexLower)
  2373. sprintf(str, "0x%08llx", *(uint64*)data);
  2374. return StrFormat("%s\n%s", str, "double");
  2375. }
  2376. }
  2377. }
  2378. if (typedValue.mType->IsPointer())
  2379. {
  2380. //ceContext->
  2381. addr_ce ptrVal = addr;
  2382. String retVal;
  2383. BfType* innerType = typedValue.mType->GetUnderlyingType();
  2384. if (innerType == NULL)
  2385. return EncodeDataPtr((uint32)ptrVal, true) + "\nvoid*";
  2386. bool isChar = false;
  2387. if (innerType->IsChar())
  2388. isChar = true;
  2389. if ((isChar) && (formatInfo.mArrayLength == -1))
  2390. {
  2391. auto primType = (BfPrimitiveType*)innerType;
  2392. if (!formatInfo.mHidePointers)
  2393. retVal = EncodeDataPtr(ptrVal, true);
  2394. int strLen = (int)formatInfo.mOverrideCount;
  2395. // if (typedValue.mIsLiteral)
  2396. // {
  2397. // if (strLen == -1)
  2398. // strLen = 0x7FFFFFFF;
  2399. // if (typedValue.mDataLen > 0)
  2400. // strLen = BF_MIN(strLen, typedValue.mDataLen);
  2401. // else
  2402. // strLen = BF_MIN(strLen, strlen(typedValue.mCharPtr));
  2403. // }
  2404. SetAndRestoreValue<intptr> prevOverrideLen(formatInfo.mOverrideCount, strLen);
  2405. String strResult = ReadString(primType->mTypeDef->mTypeCode, ptrVal, strLen, formatInfo);
  2406. if (formatInfo.mRawString)
  2407. return strResult;
  2408. if (!strResult.IsEmpty())
  2409. {
  2410. if (!retVal.IsEmpty())
  2411. retVal += " ";
  2412. retVal += strResult;
  2413. }
  2414. retVal += "\n" + module->TypeToString(typedValue.mType);
  2415. return retVal;
  2416. }
  2417. // else if ((unmodInnerType != NULL) &&
  2418. // ((unmodInnerType->mTypeCode == DbgType_Class) || (unmodInnerType->mTypeCode == DbgType_Struct) || (unmodInnerType->mTypeCode == DbgType_Union)))
  2419. // {
  2420. // isCompositeType = true;
  2421. // }
  2422. // else if ((unmodInnerType != NULL) && (unmodInnerType->mTypeCode == DbgType_SizedArray))
  2423. // {
  2424. // isSizedArray = true;
  2425. // }
  2426. // else if (unmodInnerType->mTypeCode == DbgType_Subroutine)
  2427. // {
  2428. // if (formatInfo.mRawString)
  2429. // return "";
  2430. // addr_ce funcPtr = (addr_ce)typedValue.mPtr;
  2431. // String retVal;
  2432. // if ((!typedValue.mIsLiteral) && (!formatInfo.mHidePointers))
  2433. // retVal = EncodeDataPtr(funcPtr, true);
  2434. //
  2435. // String symbolName;
  2436. // addr_ce offset;
  2437. // DbgModule* dwarf;
  2438. // static String demangledName;
  2439. // auto subProgram = mDebugTarget->FindSubProgram(funcPtr);
  2440. // if (subProgram != NULL)
  2441. // {
  2442. // demangledName = subProgram->ToString();
  2443. // }
  2444. // else if (mDebugTarget->FindSymbolAt(funcPtr, &symbolName, &offset, &dwarf))
  2445. // {
  2446. // demangledName = BfDemangler::Demangle(symbolName, language);
  2447. //
  2448. // if (offset != 0)
  2449. // demangledName += StrFormat("+%d", offset);
  2450. // }
  2451. // else
  2452. // {
  2453. // auto dbgModule = mDebugTarget->FindDbgModuleForAddress(funcPtr);
  2454. // if (dbgModule != NULL)
  2455. // demangledName += dbgModule->GetLinkedModule()->mDisplayName + "!";
  2456. // demangledName += StrFormat("0x%@", funcPtr);
  2457. // }
  2458. //
  2459. // retVal += " {";
  2460. // retVal += demangledName;
  2461. // retVal += "}";
  2462. // retVal += "\n" + origValueType->ToString(language);
  2463. //
  2464. // return retVal;
  2465. // }
  2466. // else if (unmodInnerType->mTypeCode == DbgType_Void)
  2467. // {
  2468. // if (formatInfo.mRawString)
  2469. // return "";
  2470. // addr_ce ptr = (addr_ce)typedValue.mPtr;
  2471. // String symbolName;
  2472. // addr_ce offset;
  2473. // DbgModule* dwarf;
  2474. // String demangledName;
  2475. //
  2476. // retVal += demangledName = StrFormat("0x%@", ptr);
  2477. //
  2478. // if (mDebugTarget->FindSymbolAt(ptr, &symbolName, &offset, &dwarf))
  2479. // {
  2480. // if (offset == 0)
  2481. // {
  2482. // retVal += " {";
  2483. // retVal += BfDemangler::Demangle(symbolName, language);
  2484. // retVal += "}";
  2485. // }
  2486. // }
  2487. //
  2488. // retVal += "\n" + origValueType->ToString(language);
  2489. //
  2490. // return retVal;
  2491. // }
  2492. // else
  2493. {
  2494. if (formatInfo.mRawString)
  2495. return "";
  2496. String retVal;
  2497. if (!formatInfo.mHidePointers)
  2498. retVal = EncodeDataPtr((uint32)ptrVal, true);
  2499. if (ptrVal != 0)
  2500. {
  2501. BfTypedValue innerTypedVal = BfTypedValue(module->mBfIRBuilder->CreateConstAggCE(module->mBfIRBuilder->MapType(innerType), (addr_ce)ptrVal), innerType, true);
  2502. innerTypedVal.mType = innerType;
  2503. if (innerTypedVal)
  2504. {
  2505. CeFormatInfo defaultFormatInfo;
  2506. defaultFormatInfo.mTotalSummaryLength = formatInfo.mTotalSummaryLength + 2; // Take into accout the necessary {}'s
  2507. defaultFormatInfo.mExpandItemDepth++;
  2508. defaultFormatInfo.mCallStackIdx = formatInfo.mCallStackIdx;
  2509. String innerStr = TypedValueToString(innerTypedVal, "", defaultFormatInfo);
  2510. int crIdx = (int)innerStr.IndexOf('\n');
  2511. if (crIdx != -1)
  2512. {
  2513. String innerDataStr = innerStr.Substring(0, crIdx);
  2514. if (!innerDataStr.empty())
  2515. {
  2516. if (!retVal.empty())
  2517. retVal += " ";
  2518. retVal += "{" + innerDataStr + "}";
  2519. }
  2520. }
  2521. else
  2522. {
  2523. retVal += " { ??? }";
  2524. }
  2525. }
  2526. }
  2527. retVal += "\n" + module->TypeToString(typedValue.mType);
  2528. module->PopulateType(innerType);
  2529. if (ptrVal != 0)
  2530. {
  2531. //String ptrDataStr = StrFormat("(%s)", dwValueType->ToStringRaw(language).c_str()) + EncodeDataPtr(typedValue.mPtr, true);
  2532. retVal += "\n*\t";
  2533. // Why did we have this? It messed up a pointer to sized array
  2534. /*if (language == DbgLanguage_Beef)
  2535. retVal += "this";
  2536. else*/
  2537. retVal += "this";
  2538. if (!formatInfo.mReferenceId.empty())
  2539. retVal += ", refid=" + MaybeQuoteFormatInfoParam(formatInfo.mReferenceId);
  2540. retVal += StrFormat(", this=%d@0x%X", innerType->mTypeId, ptrVal);
  2541. }
  2542. retVal += "\n:editVal\t" + EncodeDataPtr((uint32)addr, true);
  2543. return retVal;
  2544. }
  2545. }
  2546. if (typedValue.mType->IsSizedArray())
  2547. {
  2548. auto arrayType = (BfSizedArrayType*)typedValue.mType;
  2549. auto innerType = arrayType->mElementType;
  2550. String retVal;
  2551. addr_ce ptrVal = addr;
  2552. intptr arraySize = arrayType->mElementCount;
  2553. intptr innerSize = innerType->GetStride();
  2554. String idxStr = "[{0}]";
  2555. if (innerType->IsChar())
  2556. {
  2557. auto primType = (BfPrimitiveType*)innerType;
  2558. String strVal = ReadString(primType->mTypeDef->mTypeCode, ptrVal, arraySize, formatInfo);
  2559. if (formatInfo.mRawString)
  2560. return strVal;
  2561. retVal += strVal;
  2562. }
  2563. else
  2564. {
  2565. if (formatInfo.mRawString)
  2566. return "";
  2567. _ShowArraySummary(retVal, ptrVal, arraySize, innerType);
  2568. }
  2569. retVal += "\n" + module->TypeToString(typedValue.mType);
  2570. String referenceId = module->TypeToString(typedValue.mType);
  2571. String evalStr;
  2572. // Why did we have the "na"? Do we not want to show addresses for all members?
  2573. auto ptrType = module->CreatePointerType(innerType);
  2574. evalStr = StrFormat("((comptype(%d))(void*)", ptrType->mTypeId) + EncodeDataPtr(ptrVal, true) + ")[{0}], refid=" + MaybeQuoteFormatInfoParam(referenceId + ".[]");
  2575. if (typedValue.IsReadOnly())
  2576. evalStr += ", ne";
  2577. retVal += "\n:repeat" + StrFormat("\t%d\t%lld\t%d", 0, (int)BF_MAX(arraySize, 0), 10000) +
  2578. "\t" + idxStr + "\t" + evalStr;
  2579. return retVal;
  2580. }
  2581. if (typedValue.mType->IsEnum())
  2582. {
  2583. String retVal;
  2584. int64 bitsLeft = ValueToInt(typedValue);
  2585. int valueCount = 0;
  2586. String editVal;
  2587. auto typeInst = typedValue.mType->ToTypeInstance();
  2588. auto dbgTypeInfo = GetDbgTypeInfo(typedValue.mType->mTypeId);
  2589. while ((dbgTypeInfo != NULL) && ((bitsLeft != 0) || (valueCount == 0)))
  2590. {
  2591. CeDbgTypeInfo::ConstIntEntry* bestMatch = NULL;
  2592. for (auto& constIntEntry : dbgTypeInfo->mConstIntEntries)
  2593. {
  2594. if (constIntEntry.mVal == bitsLeft)
  2595. {
  2596. bestMatch = &constIntEntry;
  2597. break;
  2598. }
  2599. }
  2600. if (bestMatch == NULL)
  2601. {
  2602. for (auto& constIntEntry : dbgTypeInfo->mConstIntEntries)
  2603. {
  2604. if ((constIntEntry.mVal != 0) &&
  2605. ((constIntEntry.mVal & bitsLeft) == constIntEntry.mVal))
  2606. {
  2607. bestMatch = &constIntEntry;
  2608. break;
  2609. }
  2610. }
  2611. }
  2612. if (bestMatch == NULL)
  2613. break;
  2614. if (valueCount > 0)
  2615. {
  2616. retVal += " | ";
  2617. }
  2618. auto bestFieldInstance = &typeInst->mFieldInstances[bestMatch->mFieldIdx];
  2619. retVal += ".";
  2620. retVal += bestFieldInstance->GetFieldDef()->mName;
  2621. valueCount++;
  2622. bitsLeft &= ~bestMatch->mVal;
  2623. }
  2624. if ((valueCount == 0) || (bitsLeft != 0))
  2625. {
  2626. if (valueCount > 0)
  2627. retVal += " | ";
  2628. retVal += StrFormat("%lld", bitsLeft);
  2629. }
  2630. retVal += "\n" + module->TypeToString(typedValue.mType);
  2631. retVal += "\n:canEdit";
  2632. return retVal;
  2633. }
  2634. if (typedValue.mType->IsTypedPrimitive())
  2635. {
  2636. auto innerType = typedValue.mType->GetUnderlyingType();
  2637. BfTypedValue innerTypedVal = typedValue;
  2638. innerTypedVal.mType = innerType;
  2639. auto innerReturn = TypedValueToString(innerTypedVal, expr, formatInfo, fullPrecision);
  2640. if (innerReturn.StartsWith("!"))
  2641. return innerReturn;
  2642. int crPos = (int)innerReturn.IndexOf('\n');
  2643. if (crPos == -1)
  2644. return innerReturn;
  2645. retVal += "{ ";
  2646. retVal += innerReturn.Substring(0, crPos);
  2647. retVal += " }";
  2648. retVal += "\n" + module->TypeToString(typedValue.mType);
  2649. return retVal;
  2650. }
  2651. bool isCompositeType = typedValue.mType->IsStruct() || typedValue.mType->IsObject();
  2652. if (isCompositeType)
  2653. {
  2654. BfTypeInstance* displayType = typedValue.mType->ToTypeInstance();
  2655. bool isMemoryValid = true;
  2656. if ((dataAddr == 0) && (addr != 0))
  2657. dataAddr = *(addr_ce*)data;
  2658. if (((typedValue.mType->IsObjectOrInterface()) &&
  2659. (!formatInfo.mHidePointers) || (dataAddr == 0)))
  2660. {
  2661. retVal = EncodeDataPtr((uint32)dataAddr, true);
  2662. retVal += " ";
  2663. if (!ceContext->CheckMemory(dataAddr, displayType->mInstSize))
  2664. isMemoryValid = false;
  2665. }
  2666. bool isBadSrc = false;
  2667. bool isNull = dataAddr == 0;
  2668. bool hadCustomDisplayString = false;
  2669. BfTypeInstance* actualType = displayType;
  2670. bool useActualRawType = false;
  2671. bool isTuple = typedValue.mType->IsTuple();
  2672. String ptrDataStr;
  2673. if (!formatInfo.mIgnoreDerivedClassInfo)
  2674. {
  2675. if (actualType->IsObject())
  2676. {
  2677. if (dataAddr != 0)
  2678. {
  2679. uint8* dataPtr = ceContext->GetMemoryPtr(dataAddr, 4);
  2680. if (dataPtr == 0)
  2681. return "!Invalid object address";
  2682. int actualTypeid = *(int32*)dataPtr;
  2683. auto checkType = mCompiler->mContext->FindTypeById(actualTypeid);
  2684. if (checkType != NULL)
  2685. actualType = checkType->ToTypeInstance();
  2686. }
  2687. }
  2688. }
  2689. DebugVisualizerEntry* debugVis = NULL;
  2690. Array<String> dbgVisWildcardCaptures;
  2691. if ((!formatInfo.mNoVisualizers) && (!isNull) && (!isBadSrc))
  2692. {
  2693. debugVis = FindVisualizerForType(displayType, &dbgVisWildcardCaptures);
  2694. }
  2695. bool wantsCustomExpandedItems = false;
  2696. String displayString;
  2697. if (debugVis != NULL)
  2698. {
  2699. auto& displayStringList = formatInfo.mRawString ? debugVis->mStringViews : debugVis->mDisplayStrings;
  2700. for (auto displayEntry : displayStringList)
  2701. {
  2702. if (!displayEntry->mCondition.empty())
  2703. {
  2704. if (!EvalCondition(debugVis, typedValue, formatInfo, displayEntry->mCondition, dbgVisWildcardCaptures, displayString))
  2705. continue;
  2706. }
  2707. hadCustomDisplayString = true;
  2708. String displayStr = mDebugManager->mDebugVisualizers->DoStringReplace(displayEntry->mString, dbgVisWildcardCaptures);
  2709. if (displayString.length() > 0)
  2710. displayString += " ";
  2711. ProcessEvalString(typedValue, displayStr, displayString, formatInfo, debugVis, true);
  2712. if (formatInfo.mRawString)
  2713. return displayString;
  2714. break;
  2715. }
  2716. if ((!debugVis->mExpandItems.empty()) || (debugVis->mCollectionType != DebugVisualizerEntry::CollectionType_None))
  2717. {
  2718. wantsCustomExpandedItems = true;
  2719. }
  2720. }
  2721. if (formatInfo.mRawString)
  2722. return "";
  2723. if ((!isNull) && (!formatInfo.mNoVisualizers) && (!hadCustomDisplayString))
  2724. {
  2725. // Create our own custom display
  2726. String firstRet;
  2727. String bigRet = isTuple ? "(" : "{ ";
  2728. int memberIdx = 0;
  2729. BfType* summaryType = typedValue.mType;
  2730. bool summaryDone = false;
  2731. bool truncatedMemberList = false;
  2732. BfTypedValue summaryTypedValue = typedValue;
  2733. String summaryDataStr = ptrDataStr;
  2734. String splatStr;
  2735. if (dataAddr == -1)
  2736. splatStr = expr;
  2737. while ((summaryType != NULL) && (isMemoryValid))
  2738. {
  2739. if ((summaryType->IsTypedPrimitive())
  2740. //&& ((summaryType->mBaseTypes.IsEmpty()) || (!summaryType->mBaseTypes.front()->mBaseType->IsTypedPrimitive())))
  2741. )
  2742. {
  2743. if (formatInfo.mTotalSummaryLength + (int)displayString.length() > 255)
  2744. {
  2745. truncatedMemberList = true;
  2746. summaryDone = true;
  2747. bigRet += "...";
  2748. }
  2749. else
  2750. {
  2751. CeFormatInfo displayStrFormatInfo = formatInfo;
  2752. displayStrFormatInfo.mExpandItemDepth = 1;
  2753. displayStrFormatInfo.mTotalSummaryLength += (int)displayString.length();
  2754. displayStrFormatInfo.mHidePointers = false;
  2755. BfType* primType = summaryType->GetUnderlyingType();
  2756. String result;
  2757. if (primType->IsInteger())
  2758. formatInfo.mTypeKindFlags = (DbgTypeKindFlags)(formatInfo.mTypeKindFlags | DbgTypeKindFlag_Int);
  2759. if ((dataAddr != 0) && (dataAddr != -1))
  2760. {
  2761. //String evalString = "(" + primType->ToString() + ")" + ptrDataStr;
  2762. // BfTypedValue evalResult = EvaluateInContext(dbgCompileUnit, origTypedValue, evalString, &displayStrFormatInfo);
  2763. // if (evalResult)
  2764. // result = TypedValueToString(evalResult, evalString, displayStrFormatInfo, NULL);
  2765. }
  2766. else
  2767. {
  2768. // BfTypedValue evalResult = origTypedValue;
  2769. // evalResult.mType = primType;
  2770. // String evalString = "(" + primType->ToString() + ")" + expr;
  2771. // result = TypedValueToString(evalResult, evalString, displayStrFormatInfo, NULL);
  2772. }
  2773. if (formatInfo.mRawString)
  2774. return result;
  2775. int crPos = (int)result.IndexOf('\n');
  2776. if (crPos != -1)
  2777. result.RemoveToEnd(crPos);
  2778. if (memberIdx == 0)
  2779. firstRet = result;
  2780. bigRet += result;
  2781. memberIdx++;
  2782. }
  2783. }
  2784. auto summaryTypeInst = summaryType->ToTypeInstance();
  2785. if (summaryTypeInst == NULL)
  2786. break;
  2787. module->PopulateType(summaryTypeInst);
  2788. for (auto& fieldInst : summaryTypeInst->mFieldInstances)
  2789. {
  2790. auto fieldDef = fieldInst.GetFieldDef();
  2791. if (!fieldDef->mIsStatic)
  2792. {
  2793. if (formatInfo.mTotalSummaryLength + retVal.length() + bigRet.length() > 255)
  2794. {
  2795. truncatedMemberList = true;
  2796. summaryDone = true;
  2797. bigRet += "...";
  2798. break;
  2799. }
  2800. //if (fieldDef->mName != NULL)
  2801. {
  2802. // if (member->mName[0] == '$')
  2803. // continue;
  2804. if (!isdigit(fieldDef->mName[0]))
  2805. {
  2806. if (memberIdx != 0)
  2807. bigRet += isTuple ? ", " : " ";
  2808. if ((!isTuple) || (fieldDef->mName[0] != '_'))
  2809. {
  2810. bigRet += String(fieldDef->mName);
  2811. bigRet += isTuple ? ":" : "=";
  2812. }
  2813. }
  2814. else
  2815. {
  2816. if (memberIdx != 0)
  2817. bigRet += ", ";
  2818. }
  2819. CeFormatInfo displayStrFormatInfo = formatInfo;
  2820. displayStrFormatInfo.mExpandItemDepth = 1;
  2821. displayStrFormatInfo.mHidePointers = false;
  2822. displayStrFormatInfo.mTotalSummaryLength = (int)(formatInfo.mTotalSummaryLength + retVal.length() + bigRet.length());
  2823. // String evalString;
  2824. // if (dataPtr != -1)
  2825. // {
  2826. // if ((fieldDef->mName[0] >= '0') && (fieldDef->mName[0] <= '9'))
  2827. // evalString += "this.";
  2828. // evalString += String(member->mName); // +", this=" + summaryDataStr;
  2829. // }
  2830. // else
  2831. // {
  2832. // evalString = "(";
  2833. // evalString += splatStr;
  2834. // evalString += ").";
  2835. // evalString += fieldDef->mName;
  2836. // }
  2837. String referenceId;
  2838. String result;
  2839. if (!fieldInst.mResolvedType->IsValuelessType())
  2840. {
  2841. auto addrVal = dataAddr + fieldInst.mDataOffset;
  2842. BfTypedValue evalResult;
  2843. if (fieldInst.mResolvedType->IsObjectOrInterface())
  2844. {
  2845. auto typeInst = fieldInst.mResolvedType->ToTypeInstance();
  2846. evalResult = BfTypedValue(module->mBfIRBuilder->CreateConstAggCE(module->mBfIRBuilder->MapTypeInst(typeInst), (addr_ce)addrVal), typeInst, true);
  2847. }
  2848. else
  2849. {
  2850. evalResult = BfTypedValue(module->mBfIRBuilder->CreateConstAggCE(module->mBfIRBuilder->MapType(fieldInst.mResolvedType), (addr_ce)addrVal), fieldInst.mResolvedType, true);
  2851. }
  2852. //BfTypedValue evalResult = EvaluateInContext(dbgCompileUnit, summaryTypedValue, evalString, &displayStrFormatInfo, &referenceId);
  2853. if (evalResult)
  2854. {
  2855. displayStrFormatInfo.mReferenceId = referenceId;
  2856. result = TypedValueToString(evalResult, "", displayStrFormatInfo, NULL);
  2857. int crPos = (int)result.IndexOf('\n');
  2858. if (crPos != -1)
  2859. result.RemoveToEnd(crPos);
  2860. }
  2861. else
  2862. result = "???";
  2863. }
  2864. if (fieldInst.mResolvedType->IsInteger())
  2865. formatInfo.mTypeKindFlags = (DbgTypeKindFlags)(formatInfo.mTypeKindFlags | DbgTypeKindFlag_Int);
  2866. if (formatInfo.mRawString)
  2867. return result;
  2868. if (memberIdx == 0)
  2869. firstRet = result;
  2870. bigRet += result;
  2871. //formatInfo.mEmbeddedDisplayCount = displayStrFormatInfo.mEmbeddedDisplayCount;
  2872. memberIdx++;
  2873. }
  2874. }
  2875. }
  2876. if (truncatedMemberList)
  2877. break;
  2878. // Find first base class with members
  2879. BfType* nextSummaryType = summaryTypeInst->mBaseType;
  2880. summaryType = nextSummaryType;
  2881. if ((summaryType == NULL) || (summaryType == module->mContext->mBfObjectType))
  2882. break;
  2883. // If we don't have many members then find a base class with some members to show
  2884. if ((memberIdx != 0) && (displayString.length() >= 255))
  2885. {
  2886. truncatedMemberList = true;
  2887. bigRet += "...";
  2888. break;
  2889. }
  2890. }
  2891. bigRet += isTuple ? ")" : " }";
  2892. if (displayString.length() > 0)
  2893. displayString += " ";
  2894. if ((memberIdx == 1) && (!truncatedMemberList) && (firstRet.IndexOf('{') == -1) && (!isTuple))
  2895. displayString += "{ " + firstRet + " }";
  2896. else
  2897. displayString += bigRet;
  2898. }
  2899. retVal += displayString;
  2900. retVal += "\n" + module->TypeToString(displayType);
  2901. if ((actualType != NULL) && (actualType != displayType))
  2902. {
  2903. String actualTypeName = module->TypeToString(actualType);
  2904. retVal += StrFormat(" {%s}\n[%s]\tthis,this=%d@0x%X", actualTypeName.c_str(), actualTypeName.c_str(), actualType->mTypeId, addr);
  2905. }
  2906. if (formatInfo.mNoMembers)
  2907. {
  2908. //
  2909. }
  2910. else if (wantsCustomExpandedItems)
  2911. {
  2912. HandleCustomExpandedItems(retVal, debugVis, typedValue, addr, dataAddr, dbgVisWildcardCaptures, formatInfo);
  2913. }
  2914. else if ((!isNull) && (!isBadSrc))
  2915. {
  2916. retVal += "\n" + GetMemberList(displayType, addr, dataAddr, false);
  2917. }
  2918. if (typedValue.mType->IsObjectOrInterface())
  2919. {
  2920. retVal += "\n:editVal\t" + EncodeDataPtr((uint32)dataAddr, true);
  2921. }
  2922. return retVal;
  2923. }
  2924. return "!unknown type";
  2925. }
  2926. void CeDebugger::HandleCustomExpandedItems(String& retVal, DebugVisualizerEntry* debugVis, BfTypedValue typedValue, addr_ce addr, addr_ce addrInst, Array<String>& dbgVisWildcardCaptures, CeFormatInfo& formatInfo)
  2927. {
  2928. auto debugVisualizers = mDebugManager->mDebugVisualizers;
  2929. auto ceModule = mCeMachine->mCeModule;
  2930. if (formatInfo.mExpandItemDepth > 10) // Avoid crashing on circular ExpandItems
  2931. return;
  2932. bool isReadOnly = false;
  2933. // if (useTypedValue.mIsReadOnly)
  2934. // isReadOnly = true;
  2935. String ptrUseDataStr = StrFormat("%d@0x%X", typedValue.mType->mTypeId, addrInst);
  2936. for (auto entry : debugVis->mExpandItems)
  2937. {
  2938. if (!entry->mCondition.empty())
  2939. {
  2940. String error;
  2941. if (!EvalCondition(debugVis, typedValue, formatInfo, entry->mCondition, dbgVisWildcardCaptures, error))
  2942. {
  2943. if (!error.empty())
  2944. retVal += "\n" + entry->mName + "\t@!<DbgVis Failed>@!";
  2945. continue;
  2946. }
  2947. }
  2948. String replacedStr = debugVisualizers->DoStringReplace(entry->mValue, dbgVisWildcardCaptures);
  2949. retVal += "\n" + entry->mName + "\t" + replacedStr + ", this=" + ptrUseDataStr;
  2950. }
  2951. String referenceId = ceModule->TypeToString(typedValue.mType);
  2952. if (debugVis->mCollectionType == DebugVisualizerEntry::CollectionType_ExpandedItem)
  2953. {
  2954. BfTypedValue itemValue = EvaluateInContext(typedValue, debugVisualizers->DoStringReplace(debugVis->mValuePointer, dbgVisWildcardCaptures), &formatInfo);
  2955. if (itemValue)
  2956. {
  2957. CeFormatInfo itemFormatInfo = formatInfo;
  2958. itemFormatInfo.mExpandItemDepth++;
  2959. String itemRetVal = TypedValueToString(itemValue, "", itemFormatInfo, NULL);
  2960. int crIdx = (int)itemRetVal.IndexOf('\n');
  2961. if (crIdx != -1)
  2962. {
  2963. crIdx = (int)itemRetVal.IndexOf('\n', crIdx + 1);
  2964. if (crIdx != -1)
  2965. retVal += itemRetVal.Substring(crIdx);
  2966. }
  2967. }
  2968. }
  2969. else if (debugVis->mCollectionType == DebugVisualizerEntry::CollectionType_Array)
  2970. {
  2971. BfTypedValue sizeValue = EvaluateInContext(typedValue, debugVisualizers->DoStringReplace(debugVis->mSize, dbgVisWildcardCaptures), &formatInfo);
  2972. Array<int> lowerDimSizes;
  2973. for (auto lowerDim : debugVis->mLowerDimSizes)
  2974. {
  2975. BfTypedValue lowerDimValue = EvaluateInContext(typedValue, debugVisualizers->DoStringReplace(lowerDim, dbgVisWildcardCaptures), &formatInfo);
  2976. int dimSize = 0;
  2977. if ((lowerDimValue) && (lowerDimValue.mType->IsInteger()))
  2978. dimSize = (int)ValueToInt(lowerDimValue);
  2979. dimSize = BF_MAX(dimSize, 1);
  2980. lowerDimSizes.push_back(dimSize);
  2981. }
  2982. if ((sizeValue) && (sizeValue.mType->IsInteger()) && (ValueToInt(sizeValue) > 0))
  2983. {
  2984. if (!debugVis->mCondition.IsEmpty())
  2985. {
  2986. int size = (int)ValueToInt(sizeValue);
  2987. BfTypedValue headPointer = EvaluateInContext(typedValue, debugVisualizers->DoStringReplace(debugVis->mValuePointer, dbgVisWildcardCaptures), &formatInfo);
  2988. BfTypedValue curNode = headPointer;
  2989. Array<addr_ce> parentList;
  2990. String continuationData;
  2991. int totalSize = 2;
  2992. auto valueType = headPointer.mType;
  2993. String addrs = GetArrayItems(debugVis, valueType, headPointer, totalSize, &continuationData);
  2994. String firstAddr;
  2995. String secondAddr;
  2996. bool hasSecondAddr = valueType == NULL;
  2997. if (addrs.length() > 0)
  2998. {
  2999. const char* addrsPtr = addrs.c_str();
  3000. firstAddr = addrs.Substring(0, sizeof(addr_ce) * 2);
  3001. if (hasSecondAddr)
  3002. secondAddr = addrs.Substring(sizeof(addr_ce) * 2, sizeof(addr_ce) * 2);
  3003. }
  3004. String evalStr;
  3005. if (valueType != NULL)
  3006. {
  3007. auto ptrType = valueType;
  3008. if (!valueType->IsPointer())
  3009. ptrType = ceModule->CreatePointerType(valueType);
  3010. evalStr = StrFormat("(comptype(%d)", ptrType->mTypeId);
  3011. evalStr += ")(void*)0x{1}";
  3012. }
  3013. else
  3014. {
  3015. evalStr += "({1})(void*)0x{2}";
  3016. }
  3017. if (!debugVis->mShowElementAddrs)
  3018. evalStr.Insert(0, "*");
  3019. if (addrs.length() > 0)
  3020. {
  3021. evalStr += ", refid=\"" + referenceId + ".[]\"";
  3022. if (isReadOnly)
  3023. evalStr += ", ne";
  3024. retVal += "\n:repeat" + StrFormat("\t%d\t%d\t%d", 0, BF_MAX(size, 0), 10000) +
  3025. "\t[{0}]\t" + evalStr + "\t" + firstAddr;
  3026. if (hasSecondAddr)
  3027. retVal += "\t" + secondAddr;
  3028. if (size != 0)
  3029. {
  3030. retVal += "\n:addrs\t" + addrs;
  3031. if (valueType == NULL)
  3032. retVal += "\n:addrsEntrySize\t2";
  3033. if (continuationData.length() > 0)
  3034. retVal += "\n:continuation\t" + continuationData;
  3035. }
  3036. }
  3037. }
  3038. else if (lowerDimSizes.size() == 1)
  3039. {
  3040. int dimSize1 = lowerDimSizes[0];
  3041. String evalStr = "(" + debugVisualizers->DoStringReplace(debugVis->mValuePointer, dbgVisWildcardCaptures) +
  3042. StrFormat(" + {0} * %d), arraysize=%d, na, this=", dimSize1, dimSize1) + ptrUseDataStr;
  3043. evalStr += ", refid=\"" + referenceId + ".[]\"";
  3044. if (isReadOnly)
  3045. evalStr += ", ne";
  3046. retVal += "\n:repeat" + StrFormat("\t%d\t%lld\t%d", 0, ValueToInt(sizeValue) / dimSize1, 50000) +
  3047. "\t[{0}]\t" + evalStr;
  3048. }
  3049. else if (lowerDimSizes.size() == 2)
  3050. {
  3051. int dimSize1 = lowerDimSizes[0];
  3052. int dimSize2 = lowerDimSizes[1];
  3053. BfTypedValue headPointer = EvaluateInContext(typedValue, debugVisualizers->DoStringReplace(debugVis->mValuePointer, dbgVisWildcardCaptures), &formatInfo);
  3054. if ((headPointer.mType != NULL) && (headPointer.mType->IsPointer()))
  3055. {
  3056. String evalStr = StrFormat("((%s[%d]*)", ceModule->TypeToString(headPointer.mType->GetUnderlyingType()).c_str(), dimSize2) + debugVisualizers->DoStringReplace(debugVis->mValuePointer, dbgVisWildcardCaptures) +
  3057. StrFormat(" + {0} * %d), arraysize=%d, na, this=", dimSize1, dimSize1) + ptrUseDataStr;
  3058. evalStr += ", refid=\"" + referenceId + ".[]\"";
  3059. if (isReadOnly)
  3060. evalStr += ", ne";
  3061. retVal += "\n:repeat" + StrFormat("\t%d\t%lld\t%d", 0, ValueToInt(sizeValue) / dimSize1 / dimSize2, 50000) +
  3062. "\t[{0}]\t" + evalStr;
  3063. }
  3064. }
  3065. else if (lowerDimSizes.size() == 3)
  3066. {
  3067. int dimSize1 = lowerDimSizes[0];
  3068. int dimSize2 = lowerDimSizes[1];
  3069. int dimSize3 = lowerDimSizes[2];
  3070. BfTypedValue headPointer = EvaluateInContext(typedValue, debugVisualizers->DoStringReplace(debugVis->mValuePointer, dbgVisWildcardCaptures), &formatInfo);
  3071. if ((headPointer.mType != NULL) && (headPointer.mType->IsPointer()))
  3072. {
  3073. String evalStr = StrFormat("((%s[%d][%d]*)", ceModule->TypeToString(headPointer.mType->GetUnderlyingType()).c_str(), dimSize2, dimSize3) + debugVisualizers->DoStringReplace(debugVis->mValuePointer, dbgVisWildcardCaptures) +
  3074. StrFormat(" + {0} * %d), arraysize=%d, na, this=", dimSize1, dimSize1) + ptrUseDataStr;
  3075. evalStr += ", refid=\"" + referenceId + ".[]\"";
  3076. if (isReadOnly)
  3077. evalStr += ", ne";
  3078. retVal += "\n:repeat" + StrFormat("\t%d\t%lld\t%d", 0, ValueToInt(sizeValue) / dimSize1 / dimSize2 / dimSize3, 50000) +
  3079. "\t[{0}]\t" + evalStr;
  3080. }
  3081. }
  3082. else
  3083. {
  3084. String evalStr = "*(" + debugVisualizers->DoStringReplace(debugVis->mValuePointer, dbgVisWildcardCaptures) + " + {0}), this=" + ptrUseDataStr;
  3085. evalStr += ", refid=\"" + referenceId + ".[]\"";
  3086. if (isReadOnly)
  3087. evalStr += ", ne";
  3088. retVal += "\n:repeat" + StrFormat("\t%d\t%lld\t%d", 0, ValueToInt(sizeValue), 50000) +
  3089. "\t[{0}]\t" + evalStr;
  3090. }
  3091. }
  3092. }
  3093. else if (debugVis->mCollectionType == DebugVisualizerEntry::CollectionType_IndexItems)
  3094. {
  3095. BfTypedValue sizeValue = EvaluateInContext(typedValue, debugVisualizers->DoStringReplace(debugVis->mSize, dbgVisWildcardCaptures), &formatInfo);
  3096. if ((sizeValue) && (sizeValue.mType->IsInteger()) && (ValueToInt(sizeValue) > 0))
  3097. {
  3098. String evalStr = debugVis->mValuePointer + ", this=" + ptrUseDataStr;
  3099. evalStr.Replace("$i", "{0}");
  3100. evalStr += ", refid=\"" + referenceId + ".[]\"";
  3101. if (isReadOnly)
  3102. evalStr += ", ne";
  3103. retVal += "\n:repeat" + StrFormat("\t%d\t%lld\t%d", 0, ValueToInt(sizeValue), 50000) +
  3104. "\t[{0}]\t" + evalStr;
  3105. }
  3106. }
  3107. else if (debugVis->mCollectionType == DebugVisualizerEntry::CollectionType_LinkedList)
  3108. {
  3109. BfType* valueType = NULL;
  3110. if (!debugVis->mValueType.empty())
  3111. {
  3112. valueType = FindType(debugVisualizers->DoStringReplace(debugVis->mValueType, dbgVisWildcardCaptures));
  3113. }
  3114. BfTypedValue headPointer = EvaluateInContext(typedValue, debugVisualizers->DoStringReplace(debugVis->mHeadPointer, dbgVisWildcardCaptures), &formatInfo);
  3115. if (headPointer)
  3116. {
  3117. BfTypedValue endPointer;
  3118. if (!debugVis->mEndPointer.empty())
  3119. endPointer = EvaluateInContext(typedValue, debugVisualizers->DoStringReplace(debugVis->mEndPointer, dbgVisWildcardCaptures), &formatInfo);
  3120. BfTypedValue nextPointer = EvaluateInContext(headPointer, debugVisualizers->DoStringReplace(debugVis->mNextPointer, dbgVisWildcardCaptures), &formatInfo);
  3121. int size = -1;
  3122. if (!debugVis->mSize.empty())
  3123. {
  3124. auto sizeValue = EvaluateInContext(typedValue, debugVisualizers->DoStringReplace(debugVis->mSize, dbgVisWildcardCaptures), &formatInfo);
  3125. if (sizeValue)
  3126. size = (int)ValueToInt(sizeValue);
  3127. }
  3128. BfTypedValue curNode = headPointer;
  3129. Array<addr_ce> parentList;
  3130. String continuationData;
  3131. int totalSize = 2;
  3132. String addrs; //TODO: = GetLinkedListItems(debugVis, endPointer.mPtr, valueType, curNode, totalSize, &continuationData);
  3133. String firstAddr;
  3134. String secondAddr;
  3135. bool hasSecondAddr = valueType == NULL;
  3136. if (addrs.length() > 0)
  3137. {
  3138. const char* addrsPtr = addrs.c_str();
  3139. firstAddr = addrs.Substring(0, sizeof(addr_ce) * 2);
  3140. if (hasSecondAddr)
  3141. secondAddr = addrs.Substring(sizeof(addr_ce) * 2, sizeof(addr_ce) * 2);
  3142. }
  3143. String evalStr;
  3144. if (valueType != NULL)
  3145. {
  3146. auto ptrType = valueType;
  3147. if (!valueType->IsPointer())
  3148. ptrType = ceModule->CreatePointerType(valueType);
  3149. evalStr = StrFormat("(comptype(%d)", ptrType->mTypeId);
  3150. evalStr += ")0x{1}";
  3151. }
  3152. else
  3153. {
  3154. evalStr += "({1})0x{2}";
  3155. }
  3156. if (!debugVis->mShowElementAddrs)
  3157. evalStr.Insert(0, "*");
  3158. if (addrs.length() > 0)
  3159. {
  3160. evalStr += ", refid=\"" + referenceId + ".[]\"";
  3161. if (isReadOnly)
  3162. evalStr += ", ne";
  3163. retVal += "\n:repeat" + StrFormat("\t%d\t%d\t%d", 0, size, 10000) +
  3164. "\t[{0}]\t" + evalStr + "\t" + firstAddr;
  3165. if (hasSecondAddr)
  3166. retVal += "\t" + secondAddr;
  3167. if (size != 0)
  3168. {
  3169. retVal += "\n:addrs\t" + addrs;
  3170. if (valueType == NULL)
  3171. retVal += "\n:addrsEntrySize\t2";
  3172. if (continuationData.length() > 0)
  3173. retVal += "\n:continuation\t" + continuationData;
  3174. }
  3175. }
  3176. }
  3177. }
  3178. else if (debugVis->mCollectionType == DebugVisualizerEntry::CollectionType_TreeItems)
  3179. {
  3180. BfType* valueType = NULL;
  3181. if (!debugVis->mValueType.empty())
  3182. {
  3183. valueType = FindType(debugVisualizers->DoStringReplace(debugVis->mValueType, dbgVisWildcardCaptures));
  3184. }
  3185. BfTypedValue sizeValue = EvaluateInContext(typedValue, debugVisualizers->DoStringReplace(debugVis->mSize, dbgVisWildcardCaptures), &formatInfo);
  3186. BfTypedValue headPointer = EvaluateInContext(typedValue, debugVisualizers->DoStringReplace(debugVis->mHeadPointer, dbgVisWildcardCaptures), &formatInfo);
  3187. if ((sizeValue) && (headPointer) && (sizeValue.mType->IsInteger()) && (ValueToInt(sizeValue) > 0))
  3188. {
  3189. BfTypedValue curNode = headPointer;
  3190. Array<addr_ce> parentList;
  3191. String continuationData;
  3192. int getItemCount = (int)BF_MIN(ValueToInt(sizeValue), 32LL);
  3193. String addrs; //TODO: = GetTreeItems(dbgCompileUnit, debugVis, parentList, valueType, curNode, getItemCount, &continuationData);
  3194. addr_ce firstAddr = 0;
  3195. addr_ce secondAddr = 0;
  3196. bool hasSecondAddr = valueType == NULL;
  3197. if (addrs.length() > 0)
  3198. {
  3199. const char* addrsPtr = addrs.c_str();
  3200. firstAddr = DecodeTargetDataPtr(addrsPtr);
  3201. if (hasSecondAddr)
  3202. secondAddr = DecodeTargetDataPtr(addrsPtr);
  3203. }
  3204. String evalStr;
  3205. if (valueType != NULL)
  3206. {
  3207. auto ptrType = valueType;
  3208. if (!valueType->IsPointer())
  3209. ptrType = ceModule->CreatePointerType(valueType);
  3210. evalStr = StrFormat("(comptype(%d)", ptrType->mTypeId);
  3211. evalStr += ")0x{1}";;
  3212. }
  3213. else
  3214. {
  3215. evalStr += "*(_T_{1}*)0x{2}";
  3216. }
  3217. int size = (int)ValueToInt(sizeValue);
  3218. if (addrs.length() == 0)
  3219. {
  3220. evalStr = ""; // Failed
  3221. }
  3222. evalStr += ", refid=\"" + referenceId + ".[]\"";
  3223. if (isReadOnly)
  3224. evalStr += ", ne";
  3225. retVal += "\n:repeat" + StrFormat("\t%d\t%d\t%d", 0, size, 10000) +
  3226. "\t[{0}]\t" + evalStr + "\t" + EncodeDataPtr(firstAddr, false);
  3227. if (hasSecondAddr)
  3228. retVal += "\t" + EncodeDataPtr(secondAddr, false);
  3229. if (addrs.length() > 0)
  3230. {
  3231. retVal += "\n:addrs\t" + addrs;
  3232. if (continuationData.length() > 0)
  3233. retVal += "\n:continuation\t" + continuationData;
  3234. }
  3235. }
  3236. }
  3237. else if (debugVis->mCollectionType == DebugVisualizerEntry::CollectionType_Dictionary)
  3238. {
  3239. BfTypedValue sizeValue = EvaluateInContext(typedValue, debugVisualizers->DoStringReplace(debugVis->mSize, dbgVisWildcardCaptures), &formatInfo);
  3240. BfTypedValue entriesPtrValue = EvaluateInContext(typedValue, debugVisualizers->DoStringReplace(debugVis->mEntries, dbgVisWildcardCaptures), &formatInfo);
  3241. if ((sizeValue) && (entriesPtrValue) && (sizeValue.mType->IsInteger()) && (ValueToInt(sizeValue) > 0))
  3242. {
  3243. String continuationData;
  3244. BfType* valueType = entriesPtrValue.mType;
  3245. int getItemCount = (int)BF_MIN(ValueToInt(sizeValue), 2LL);
  3246. BfType* useTypedValType = typedValue.mType;
  3247. String addrs; //TODO: = GetDictionaryItems(debugVis, useTypedValue, 0, -1, getItemCount, &continuationData);
  3248. addr_ce firstAddr = 0;
  3249. if (addrs.length() > 0)
  3250. {
  3251. const char* addrsPtr = addrs.c_str();
  3252. firstAddr = DecodeTargetDataPtr(addrsPtr);
  3253. }
  3254. String evalStr = "((comptype(" + StrFormat("%d", valueType->mTypeId) + "))0x{1}), na";
  3255. evalStr += ", refid=\"" + referenceId + ".[]\"";
  3256. if (isReadOnly)
  3257. evalStr += ", ne";
  3258. retVal += "\n:repeat" + StrFormat("\t%d\t%d\t%d", 0, (int)ValueToInt(sizeValue), 10000) +
  3259. "\t[{0}]\t" + evalStr + "\t" + EncodeDataPtr(firstAddr, false);
  3260. if (addrs.length() > 0)
  3261. {
  3262. retVal += "\n:addrs\t" + addrs;
  3263. if (continuationData.length() > 0)
  3264. retVal += "\n:continuation\t" + continuationData;
  3265. }
  3266. }
  3267. }
  3268. if (formatInfo.mExpandItemDepth == 0)
  3269. {
  3270. retVal += "\n[Raw View]\tthis,this=" + ptrUseDataStr + ", nv";
  3271. }
  3272. }
  3273. String CeDebugger::Evaluate(const StringImpl& expr, int callStackIdx, int cursorPos, int language, DwEvalExpressionFlags expressionFlags)
  3274. {
  3275. CeFormatInfo formatInfo;
  3276. return Evaluate(expr, formatInfo, callStackIdx, cursorPos, language, expressionFlags);
  3277. }
  3278. String CeDebugger::EvaluateContinue()
  3279. {
  3280. return String();
  3281. }
  3282. void CeDebugger::EvaluateContinueKeep()
  3283. {
  3284. }
  3285. String CeDebugger::EvaluateToAddress(const StringImpl& expr, int callStackIdx, int cursorPos)
  3286. {
  3287. return String();
  3288. }
  3289. String CeDebugger::EvaluateAtAddress(const StringImpl& expr, intptr atAddr, int cursorPos)
  3290. {
  3291. return String();
  3292. }
  3293. String CeDebugger::GetAutoExpressions(int callStackIdx, uint64 memoryRangeStart, uint64 memoryRangeLen)
  3294. {
  3295. return String();
  3296. }
  3297. String CeDebugger::GetAutoLocals(int callStackIdx, bool showRegs)
  3298. {
  3299. String result;
  3300. auto ceFrame = GetFrame(callStackIdx);
  3301. if (ceFrame != NULL)
  3302. {
  3303. if (ceFrame->mFunction->mDbgInfo != NULL)
  3304. {
  3305. for (auto& dbgVar : ceFrame->mFunction->mDbgInfo->mVariables)
  3306. {
  3307. result += dbgVar.mName;
  3308. result += "\n";
  3309. }
  3310. }
  3311. }
  3312. return result;
  3313. }
  3314. String CeDebugger::CompactChildExpression(const StringImpl& expr, const StringImpl& parentExpr, int callStackIdx)
  3315. {
  3316. return String();
  3317. }
  3318. String CeDebugger::GetProcessInfo()
  3319. {
  3320. return String();
  3321. }
  3322. DebugVisualizerEntry* CeDebugger::FindVisualizerForType(BfType* dbgType, Array<String>* wildcardCaptures)
  3323. {
  3324. auto ceModule = mCeMachine->mCeModule;
  3325. ceModule->PopulateType(dbgType);
  3326. auto entry = mDebugManager->mDebugVisualizers->FindEntryForType(ceModule->TypeToString(dbgType), DbgFlavor_Unknown, wildcardCaptures);
  3327. if (entry == NULL)
  3328. {
  3329. auto typeInst = dbgType->ToTypeInstance();
  3330. if ((typeInst != NULL) && (typeInst->mBaseType != NULL))
  3331. entry = FindVisualizerForType(typeInst->mBaseType, wildcardCaptures);
  3332. }
  3333. return entry;
  3334. }
  3335. String CeDebugger::GetThreadInfo()
  3336. {
  3337. return String();
  3338. }
  3339. void CeDebugger::SetActiveThread(int threadId)
  3340. {
  3341. }
  3342. int CeDebugger::GetActiveThread()
  3343. {
  3344. return 0;
  3345. }
  3346. void CeDebugger::FreezeThread(int threadId)
  3347. {
  3348. }
  3349. void CeDebugger::ThawThread(int threadId)
  3350. {
  3351. }
  3352. bool CeDebugger::IsActiveThreadWaiting()
  3353. {
  3354. return false;
  3355. }
  3356. void CeDebugger::ClearCallStack()
  3357. {
  3358. }
  3359. void CeDebugger::UpdateCallStack(bool slowEarlyOut)
  3360. {
  3361. }
  3362. int CeDebugger::GetCallStackCount()
  3363. {
  3364. auto ceContext = mCeMachine->mCurContext;
  3365. if (ceContext == NULL)
  3366. return 0;
  3367. return ceContext->mCallStack.mSize;
  3368. }
  3369. int CeDebugger::GetRequestedStackFrameIdx()
  3370. {
  3371. return 0;
  3372. }
  3373. int CeDebugger::GetBreakStackFrameIdx()
  3374. {
  3375. return 0;
  3376. }
  3377. bool CeDebugger::ReadMemory(intptr address, uint64 length, void* dest, bool local)
  3378. {
  3379. auto ceContext = mCeMachine->mCurContext;
  3380. if (ceContext == NULL)
  3381. return false;
  3382. auto ptr = ceContext->GetMemoryPtr((addr_ce)address, (int32)length);
  3383. if (ptr == NULL)
  3384. return false;
  3385. memcpy(dest, ptr, length);
  3386. return true;
  3387. }
  3388. bool CeDebugger::WriteMemory(intptr address, void* src, uint64 length)
  3389. {
  3390. auto ceContext = mCeMachine->mCurContext;
  3391. if (ceContext == NULL)
  3392. return false;
  3393. auto ptr = ceContext->GetMemoryPtr((addr_ce)address, (int32)length);
  3394. if (ptr == NULL)
  3395. return false;
  3396. memcpy(ptr, src, length);
  3397. return true;
  3398. }
  3399. DbgMemoryFlags CeDebugger::GetMemoryFlags(intptr address)
  3400. {
  3401. return (DbgMemoryFlags)(DbgMemoryFlags_Read | DbgMemoryFlags_Write);
  3402. }
  3403. void CeDebugger::UpdateRegisterUsage(int stackFrameIdx)
  3404. {
  3405. }
  3406. void CeDebugger::UpdateCallStackMethod(int stackFrameIdx)
  3407. {
  3408. }
  3409. void CeDebugger::GetCodeAddrInfo(intptr addr, String* outFile, int* outHotIdx, int* outDefLineStart, int* outDefLineEnd, int* outLine, int* outColumn)
  3410. {
  3411. }
  3412. void CeDebugger::GetStackAllocInfo(intptr addr, int* outThreadId, int* outStackIdx)
  3413. {
  3414. *outThreadId = 0;
  3415. if (outStackIdx != NULL)
  3416. *outStackIdx = -1;
  3417. auto ceContext = mCeMachine->mCurContext;
  3418. for (int i = 0; i < (int)ceContext->mCallStack.mSize; i++)
  3419. {
  3420. auto ceFrame = &ceContext->mCallStack[i];
  3421. if ((addr_ce)addr > ceFrame->mFrameAddr)
  3422. {
  3423. if (outStackIdx != NULL)
  3424. *outStackIdx = (int)ceContext->mCallStack.mSize - i - 1;
  3425. }
  3426. }
  3427. }
  3428. String CeDebugger::GetStackFrameInfo(int stackFrameIdx, intptr* addr, String* outFile, int32* outHotIdx, int32* outDefLineStart, int32* outDefLineEnd, int32* outLine, int32* outColumn, int32* outLanguage, int32* outStackSize, int8* outFlags)
  3429. {
  3430. enum FrameFlags
  3431. {
  3432. FrameFlags_Optimized = 1,
  3433. FrameFlags_HasPendingDebugInfo = 2,
  3434. FrameFlags_CanGetOldSource = 4,
  3435. FrameFlags_WasHotReplaced = 8,
  3436. FrameFlags_HadError = 0x10
  3437. };
  3438. auto ceContext = mCeMachine->mCurContext;
  3439. *addr = 0;
  3440. *outFile = "";
  3441. *outHotIdx = 0;
  3442. *outDefLineStart = -1;
  3443. *outDefLineEnd = -1;
  3444. *outLine = -1;
  3445. *outColumn = 0;
  3446. *outLanguage = DbgLanguage_Beef;
  3447. *outStackSize = 0;
  3448. *outFlags = 0;
  3449. if (stackFrameIdx < ceContext->mCallStack.mSize)
  3450. {
  3451. int stackIdx = ceContext->mCallStack.mSize - stackFrameIdx - 1;
  3452. auto ceFrame = &ceContext->mCallStack[stackIdx];
  3453. auto ceFunction = ceFrame->mFunction;
  3454. if (ceFunction->mFailed)
  3455. *outFlags |= FrameFlags_HadError;
  3456. int instIdx = (int)(ceFrame->mInstPtr - &ceFunction->mCode[0] - 2);
  3457. BF_ASSERT(ceFunction->mId != -1);
  3458. *addr = ((intptr)ceFunction->mId << 32) | instIdx;
  3459. CeEmitEntry* emitEntry = ceFunction->FindEmitEntry(instIdx);
  3460. if (stackIdx > 0)
  3461. {
  3462. auto prevFrame = &ceContext->mCallStack[stackIdx - 1];
  3463. *outStackSize = prevFrame->mStackAddr - ceFrame->mStackAddr;
  3464. }
  3465. else
  3466. {
  3467. *outStackSize = ceContext->mStackSize - ceFrame->mStackAddr;
  3468. }
  3469. if (emitEntry != NULL)
  3470. {
  3471. if (emitEntry->mScope != -1)
  3472. *outFile = ceFunction->mDbgScopes[emitEntry->mScope].mFilePath;
  3473. *outLine = emitEntry->mLine;
  3474. *outColumn = emitEntry->mColumn;
  3475. }
  3476. return ceContext->mCurModule->MethodToString(ceFrame->mFunction->mMethodInstance);
  3477. }
  3478. return "?";
  3479. }
  3480. BfType* CeDebugger::FindType(const StringImpl& name)
  3481. {
  3482. //TODO:
  3483. return NULL;
  3484. }
  3485. String CeDebugger::Callstack_GetStackFrameOldFileInfo(int stackFrameIdx)
  3486. {
  3487. return String();
  3488. }
  3489. #define CE_GET(T) *((T*)(ptr += sizeof(T)) - 1)
  3490. int CeDebugger::GetJmpState(int stackFrameIdx)
  3491. {
  3492. if (stackFrameIdx != 0)
  3493. return -1;
  3494. auto ceFrame = GetFrame(stackFrameIdx);
  3495. if (ceFrame == NULL)
  3496. return -1;
  3497. int instIdx = ceFrame->GetInstIdx();
  3498. auto ptr = &ceFrame->mFunction->mCode[instIdx];
  3499. auto op = CE_GET(CeOp);
  3500. switch (op)
  3501. {
  3502. case CeOp_Jmp:
  3503. return 1;
  3504. case CeOp_JmpIf:
  3505. case CeOp_JmpIfNot:
  3506. {
  3507. CE_GET(int32);
  3508. int frameOfs = CE_GET(int32);
  3509. bool willJump = *(bool*)(mCeMachine->mCurContext->mMemory.mVals + ceFrame->mFrameAddr + frameOfs);
  3510. if (op == CeOp_JmpIfNot)
  3511. willJump = !willJump;
  3512. return willJump ? 1 : 0;
  3513. }
  3514. }
  3515. return -1;
  3516. }
  3517. intptr CeDebugger::GetStackFrameCalleeAddr(int stackFrameIdx)
  3518. {
  3519. return intptr();
  3520. }
  3521. String CeDebugger::GetStackMethodOwner(int stackFrameIdx, int& language)
  3522. {
  3523. return String();
  3524. }
  3525. String CeDebugger::FindCodeAddresses(const StringImpl& fileName, int line, int column, bool allowAutoResolve)
  3526. {
  3527. return String();
  3528. }
  3529. String CeDebugger::GetAddressSourceLocation(intptr address)
  3530. {
  3531. return String();
  3532. }
  3533. String CeDebugger::GetAddressSymbolName(intptr address, bool demangle)
  3534. {
  3535. return String();
  3536. }
  3537. String CeDebugger::DisassembleAtRaw(intptr address)
  3538. {
  3539. return String();
  3540. }
  3541. String CeDebugger::DisassembleAt(intptr address)
  3542. {
  3543. auto ceContext = mCeMachine->mCurContext;
  3544. mCurDisasmFuncId = (int)(address >> 32);
  3545. UpdateBreakpointAddrs();
  3546. CeFunction* ceFunction = NULL;
  3547. if (!mCeMachine->mFunctionIdMap.TryGetValue(mCurDisasmFuncId, &ceFunction))
  3548. return "";
  3549. CeDumpContext dumpCtx;
  3550. dumpCtx.mCeFunction = ceFunction;
  3551. dumpCtx.mStart = &ceFunction->mCode[0];
  3552. dumpCtx.mPtr = dumpCtx.mStart;
  3553. dumpCtx.mEnd = dumpCtx.mPtr + ceFunction->mCode.mSize;
  3554. uint8* start = dumpCtx.mStart;
  3555. dumpCtx.mStr += StrFormat("T Frame Size: %d\n", ceFunction->mFrameSize);
  3556. dumpCtx.mStr += StrFormat("A %llX\n", (intptr)mCurDisasmFuncId << 32);
  3557. int curEmitIdx = 0;
  3558. CeEmitEntry* prevEmitEntry = NULL;
  3559. CeEmitEntry* curEmitEntry = NULL;
  3560. while (dumpCtx.mPtr < dumpCtx.mEnd)
  3561. {
  3562. int ofs = (int)(dumpCtx.mPtr - start);
  3563. while ((curEmitIdx < ceFunction->mEmitTable.mSize - 1) && (ofs >= ceFunction->mEmitTable[curEmitIdx + 1].mCodePos))
  3564. curEmitIdx++;
  3565. if (curEmitIdx < ceFunction->mEmitTable.mSize)
  3566. curEmitEntry = &ceFunction->mEmitTable[curEmitIdx];
  3567. if (prevEmitEntry != curEmitEntry)
  3568. {
  3569. if ((curEmitEntry != NULL) && (curEmitEntry->mLine != -1))
  3570. {
  3571. if ((prevEmitEntry == NULL) || (curEmitEntry->mScope != prevEmitEntry->mScope))
  3572. {
  3573. dumpCtx.mStr += StrFormat("S %s\n", ceFunction->mDbgScopes[curEmitEntry->mScope].mFilePath.c_str());
  3574. }
  3575. if ((prevEmitEntry != NULL) && (curEmitEntry->mScope == prevEmitEntry->mScope))
  3576. {
  3577. dumpCtx.mStr += StrFormat("L %d %d\n", prevEmitEntry->mLine + 1, curEmitEntry->mLine - prevEmitEntry->mLine);
  3578. }
  3579. else
  3580. {
  3581. int startLine = BF_MAX(0, curEmitEntry->mLine - 5);
  3582. dumpCtx.mStr += StrFormat("L %d %d\n", startLine, curEmitEntry->mLine - startLine + 1);
  3583. }
  3584. prevEmitEntry = curEmitEntry;
  3585. }
  3586. }
  3587. dumpCtx.mStr += StrFormat("D %04X: ", ofs);
  3588. dumpCtx.Next();
  3589. dumpCtx.mStr += "\n";
  3590. if (dumpCtx.mJmp != -1)
  3591. {
  3592. dumpCtx.mStr += StrFormat("J %X\n", dumpCtx.mJmp);
  3593. dumpCtx.mJmp = -1;
  3594. }
  3595. }
  3596. return dumpCtx.mStr;
  3597. }
  3598. String CeDebugger::FindLineCallAddresses(intptr address)
  3599. {
  3600. return String();
  3601. }
  3602. String CeDebugger::GetCurrentException()
  3603. {
  3604. return String();
  3605. }
  3606. String CeDebugger::GetModulesInfo()
  3607. {
  3608. return String();
  3609. }
  3610. void CeDebugger::SetAliasPath(const StringImpl& origPath, const StringImpl& localPath)
  3611. {
  3612. }
  3613. void CeDebugger::CancelSymSrv()
  3614. {
  3615. }
  3616. bool CeDebugger::HasPendingDebugLoads()
  3617. {
  3618. return false;
  3619. }
  3620. int CeDebugger::LoadImageForModule(const StringImpl& moduleName, const StringImpl& debugFileName)
  3621. {
  3622. return 0;
  3623. }
  3624. int CeDebugger::LoadDebugInfoForModule(const StringImpl& moduleName)
  3625. {
  3626. return 0;
  3627. }
  3628. int CeDebugger::LoadDebugInfoForModule(const StringImpl& moduleName, const StringImpl& debugFileName)
  3629. {
  3630. return 0;
  3631. }
  3632. void CeDebugger::StopDebugging()
  3633. {
  3634. mRunState = RunState_Terminating;
  3635. mCeMachine->mDebugEvent.Set(true);
  3636. }
  3637. void CeDebugger::Terminate()
  3638. {
  3639. }
  3640. void CeDebugger::Detach()
  3641. {
  3642. mRunState = RunState_Terminated;
  3643. }
  3644. Profiler* CeDebugger::StartProfiling()
  3645. {
  3646. return nullptr;
  3647. }
  3648. Profiler* CeDebugger::PopProfiler()
  3649. {
  3650. return nullptr;
  3651. }
  3652. void CeDebugger::ReportMemory(MemReporter* memReporter)
  3653. {
  3654. }
  3655. bool CeDebugger::IsOnDemandDebugger()
  3656. {
  3657. return true;
  3658. }