DebugTarget.cpp 71 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589
  1. #include "DebugTarget.h"
  2. #include "WinDebugger.h"
  3. #include "DWARFInfo.h"
  4. #include "BeefySysLib/FileStream.h"
  5. #include "BeefySysLib/MemStream.h"
  6. #include "BeefySysLib/Util/BeefPerf.h"
  7. #include "DebugManager.h"
  8. #include "HotHeap.h"
  9. //#include <Winternl.h>
  10. #include "BeefySysLib/util/AllocDebug.h"
  11. USING_NS_BF_DBG;
  12. #define GET(T) *((T*)(data += sizeof(T)) - 1)
  13. #define GET_FROM(ptr, T) *((T*)(ptr += sizeof(T)) - 1)
  14. DebugTarget::DebugTarget(WinDebugger* debugger)
  15. {
  16. mCheckedCompilerSettings = false;
  17. mBfObjectHasFlags = false;
  18. mBfObjectHasVDataExtender = false;
  19. mBfObjectVDataIntefaceSlotCount = -1;
  20. mBfObjectSize = -1;
  21. mDebugger = debugger;
  22. mTargetBinary = NULL;
  23. mCapturedNamesPtr = NULL;
  24. mCapturedTypesPtr = NULL;
  25. mHotHeap = NULL;
  26. mLastHotHeapCleanIdx = 0;
  27. mIsEmpty = false;
  28. mWasLocallyBuilt = false;
  29. /*dbgType = new DbgType();
  30. dbgType->mName = "int";
  31. dbgType->mTypeCode = DbgType_i32;
  32. dbgType->mSize = 4;
  33. mPrimitiveTypes[DbgType_i32] = dbgType;*/
  34. }
  35. DebugTarget::~DebugTarget()
  36. {
  37. for (auto dwarf : mDbgModules)
  38. delete dwarf;
  39. for (auto& dwSrcFilePair : mSrcFiles)
  40. delete dwSrcFilePair.mValue;
  41. delete mHotHeap;
  42. mHotHeap = NULL;
  43. }
  44. DbgModule* DebugTarget::Init(const StringImpl& fileName, intptr imageBase)
  45. {
  46. BP_ZONE("DebugTarget::Init");
  47. AutoDbgTime dbgTime("DebugTarget::Init " + fileName);
  48. FileStream fileStream;
  49. fileStream.mFP = _wfopen(UTF8Decode(fileName).c_str(), L"rb");
  50. if (fileStream.mFP == NULL)
  51. {
  52. mDebugger->OutputMessage(StrFormat("Debugger failed to open binary: %s\n", fileName.c_str()));
  53. return NULL;
  54. }
  55. DbgModule* dwarf = new COFF(this);
  56. mTargetBinary = dwarf;
  57. dwarf->mDisplayName = GetFileName(fileName);
  58. dwarf->mFilePath = fileName;
  59. dwarf->mImageBase = (intptr)imageBase;
  60. if (!dwarf->ReadCOFF(&fileStream, false))
  61. {
  62. mDebugger->OutputMessage(StrFormat("Debugger failed to read binary: %s\n", fileName.c_str()));
  63. delete dwarf;
  64. return NULL;
  65. }
  66. mDbgModules.push_back(dwarf);
  67. return dwarf;
  68. }
  69. void DebugTarget::CreateEmptyTarget()
  70. {
  71. auto emptyTarget = new DbgModule(this);
  72. mDbgModules.push_back(emptyTarget);
  73. mTargetBinary = emptyTarget;
  74. }
  75. DbgModule* DebugTarget::HotLoad(const StringImpl& fileName, int hotIdx)
  76. {
  77. BP_ZONE("DebugTarget::HotLoad");
  78. AutoDbgTime dbgTime("DebugTarget::HotLoad " + fileName);
  79. FileStream fileStream;
  80. fileStream.mFP = _wfopen(UTF8Decode(fileName).c_str(), L"rb");
  81. if (fileStream.mFP == NULL)
  82. {
  83. mDebugger->OutputMessage(StrFormat("Debugger failed to open binary: %s\n", fileName.c_str()));
  84. return NULL;
  85. }
  86. DbgModule* dwarf = new COFF(this);
  87. dwarf->mHotIdx = hotIdx;
  88. dwarf->mDisplayName = GetFileName(fileName);
  89. dwarf->mFilePath = fileName;
  90. if (!dwarf->ReadCOFF(&fileStream, true))
  91. {
  92. mDebugger->OutputMessage(StrFormat("Debugger failed to read binary: %s\n", fileName.c_str()));
  93. delete dwarf;
  94. return NULL;
  95. }
  96. mDbgModules.push_back(dwarf);
  97. return dwarf;
  98. }
  99. DbgModule* DebugTarget::SetupDyn(const StringImpl& filePath, DataStream* stream, intptr imageBase)
  100. {
  101. BP_ZONE("DebugTarget::SetupDyn");
  102. AutoDbgTime dbgTime("DebugTarget::SetupDyn " + filePath);
  103. DbgModule* dwarf = new COFF(this);
  104. dwarf->mFilePath = filePath;
  105. dwarf->mImageBase = (intptr)imageBase;
  106. if (!dwarf->ReadCOFF(stream, false))
  107. {
  108. //mDebugger->OutputMessage(StrFormat("Debugger failed to read binary: %s", fileName.c_str()));
  109. delete dwarf;
  110. return NULL;
  111. }
  112. mDbgModules.push_back(dwarf);
  113. dwarf->mDisplayName = GetFileName(filePath);
  114. dwarf->mOrigImageData = new DbgModuleMemoryCache(dwarf->mImageBase, dwarf->mImageSize);
  115. /*dbgModule->mOrigImageData = new uint8[dbgModule->mImageSize];
  116. memset(dbgModule->mOrigImageData, 0xCC, dbgModule->mImageSize);
  117. for (auto& section : dbgModule->mSections)
  118. {
  119. bool couldRead = mDebugger->ReadMemory((intptr)imageBase + section.mAddrStart, section.mAddrLength, dbgModule->mOrigImageData + section.mAddrStart);
  120. BF_ASSERT(couldRead);
  121. }
  122. dbgModule->GotImageData();*/
  123. return dwarf;
  124. }
  125. String DebugTarget::UnloadDyn(addr_target imageBase)
  126. {
  127. String filePath;
  128. AutoDbgTime dbgTime("DebugTarget::UnloadDyn");
  129. for (int i = 0; i < (int)mDbgModules.size(); i++)
  130. {
  131. DbgModule* dwarf = mDbgModules[i];
  132. if (dwarf->mImageBase == imageBase)
  133. {
  134. dwarf->mDeleting = true;
  135. dwarf->RemoveTargetData();
  136. RemoveTargetData();
  137. filePath = dwarf->mFilePath;
  138. delete dwarf;
  139. mDbgModules.erase(mDbgModules.begin() + i);
  140. return filePath;
  141. }
  142. }
  143. return "";
  144. }
  145. void DebugTarget::CleanupHotHeap()
  146. {
  147. //TODO: We have more work to do before this catches all the required cases
  148. return;
  149. bool hadRemovals = false;
  150. for (int dwarfIdx = 0; dwarfIdx < (int)mDbgModules.size(); dwarfIdx++)
  151. {
  152. DbgModule* dbgModule = mDbgModules[dwarfIdx];
  153. if (dbgModule->mIsHotObjectFile)
  154. {
  155. if (!mHotHeap->IsReferenced(dbgModule->mImageBase, dbgModule->mImageSize))
  156. {
  157. Beefy::OutputDebugStrF("Clearing hot module %p data from %@ to %@\n", dbgModule, dbgModule->mImageBase, dbgModule->mImageBase + dbgModule->mImageSize);
  158. BfLogDbg("Unloading hot idx: %s@%d\n", dbgModule->mFilePath.c_str(), dbgModule->mHotIdx);
  159. dbgModule->mDeleting = true;
  160. dbgModule->RemoveTargetData();
  161. hadRemovals = true;
  162. }
  163. }
  164. }
  165. if (hadRemovals)
  166. {
  167. RemoveTargetData();
  168. for (int dwarfIdx = 0; dwarfIdx < (int)mDbgModules.size(); dwarfIdx++)
  169. {
  170. DbgModule* dbgModule = mDbgModules[dwarfIdx];
  171. if (dbgModule->mDeleting)
  172. {
  173. delete dbgModule;
  174. mDbgModules.erase(mDbgModules.begin() + dwarfIdx);
  175. dwarfIdx--;
  176. }
  177. }
  178. }
  179. }
  180. void DebugTarget::RehupSrcFiles()
  181. {
  182. for (auto srcFile : mPendingSrcFileRehup)
  183. srcFile->RehupLineData();
  184. mPendingSrcFileRehup.Clear();
  185. }
  186. DbgSrcFile* DebugTarget::AddSrcFile(const String& srcFilePath)
  187. {
  188. String filePath = FixPathAndCase(srcFilePath);
  189. DbgSrcFile* dwSrcFile = NULL;
  190. DbgSrcFile** dwSrcFilePtr = NULL;
  191. if (mSrcFiles.TryAdd(filePath, NULL, &dwSrcFilePtr))
  192. {
  193. dwSrcFile = new DbgSrcFile();
  194. dwSrcFile->mFilePath = FixPath(srcFilePath);
  195. *dwSrcFilePtr = dwSrcFile;
  196. }
  197. else
  198. {
  199. dwSrcFile = *dwSrcFilePtr;
  200. }
  201. return dwSrcFile;
  202. }
  203. DbgSrcFile* DebugTarget::GetSrcFile(const String& srcFilePath)
  204. {
  205. String filePath = FixPathAndCase(srcFilePath);
  206. DbgSrcFile* srcFile = NULL;
  207. if (!mSrcFiles.TryGetValue(filePath, &srcFile))
  208. {
  209. String* origSrcPath;
  210. if (mLocalToOrigSrcMap.TryGetValue(filePath, &origSrcPath))
  211. {
  212. mSrcFiles.TryGetValue(*origSrcPath, &srcFile);
  213. }
  214. }
  215. return srcFile;
  216. }
  217. bool DebugTarget::FindSymbolAt(addr_target addr, String* outSymbol, addr_target* outOffset, DbgModule** outDWARF)
  218. {
  219. //TODO: First search for symbol, then determine if the addr is within the defining DbgModule
  220. DbgModule* insideDWARF = NULL;
  221. /*for (auto dbgModule : mDbgModules)
  222. {
  223. for (int i = 0; i < (int)dbgModule->mSections.size(); i++)
  224. {
  225. auto section = &dbgModule->mSections[i];
  226. if ((addr >= section->mAddrStart + dbgModule->mImageBase) && (addr < section->mAddrStart + dbgModule->mImageBase + section->mAddrLength))
  227. {
  228. insideDWARF = dbgModule;
  229. }
  230. }
  231. }*/
  232. //mDebugger->ReadMemory(addr, )
  233. auto dbgModule = FindDbgModuleForAddress(addr);
  234. if (dbgModule != NULL)
  235. dbgModule->ParseSymbolData();
  236. auto dwSymbol = mSymbolMap.Get(addr, 16*1024*1024);
  237. if (dwSymbol != NULL)
  238. {
  239. dbgModule = dwSymbol->mDbgModule;
  240. }
  241. if (dbgModule == NULL)
  242. return false;
  243. if (outDWARF != NULL)
  244. *outDWARF = dbgModule;
  245. bool isExecutable = false;
  246. bool isInsideSomeSegment = false;
  247. for (int i = 0; i < (int)dbgModule->mSections.size(); i++)
  248. {
  249. auto section = &dbgModule->mSections[i];
  250. if ((addr >= section->mAddrStart + dbgModule->mImageBase) && (addr < section->mAddrStart + dbgModule->mImageBase + section->mAddrLength))
  251. {
  252. if (dbgModule->HasPendingDebugInfo())
  253. {
  254. if ((dbgModule->WantsAutoLoadDebugInfo()) && (!mDebugger->mPendingDebugInfoLoad.Contains(dbgModule)))
  255. {
  256. mDebugger->mPendingDebugInfoLoad.Add(dbgModule);
  257. }
  258. //mDebugger->LoadDebugInfoForModule(dbgModule);
  259. }
  260. isInsideSomeSegment = true;
  261. if (section->mIsExecutable)
  262. isExecutable = true;
  263. }
  264. }
  265. if (!isInsideSomeSegment)
  266. return false;
  267. //if ((addr < dwSymbol->mDbgModule->mImageBase) || (addr >= dwSymbol->mDbgModule->mImageBase + dwSymbol->mDbgModule->mImageSize))
  268. //return false;
  269. if (dwSymbol == NULL)
  270. return false;
  271. if (isExecutable)
  272. {
  273. addr_target thunkAddr = mDebugger->mCPU->DecodeThunk(addr, dwSymbol->mDbgModule->mOrigImageData);
  274. if (thunkAddr != 0)
  275. {
  276. if (FindSymbolAt(thunkAddr, outSymbol, outOffset, outDWARF))
  277. return true;
  278. }
  279. }
  280. if (outSymbol != NULL)
  281. {
  282. *outSymbol = dwSymbol->mName;
  283. }
  284. if (outOffset != NULL)
  285. *outOffset = addr - dwSymbol->mAddress;
  286. else if (addr != dwSymbol->mAddress)
  287. return false;
  288. return true;
  289. }
  290. addr_target DebugTarget::FindSymbolAddr(const StringImpl& name)
  291. {
  292. //TODO: Search through all modules?
  293. auto dbgModule = GetMainDbgModule();
  294. if (dbgModule != NULL)
  295. {
  296. auto entry = dbgModule->mSymbolNameMap.Find(name.c_str());
  297. if (entry!= NULL)
  298. {
  299. DbgSymbol* dwSymbol = entry->mValue;
  300. return dwSymbol->mAddress;
  301. }
  302. }
  303. return (addr_target)-1;
  304. }
  305. bool DebugTarget::GetValueByName(DbgSubprogram* subProgram, const StringImpl& name, WdStackFrame* stackFrame, intptr* outAddr, DbgType** outType, DbgAddrType* outAddrType)
  306. {
  307. BP_ZONE("DebugTarget::GetValueByName");
  308. //BF_ASSERT(*outAddrType == DbgAddrType_None);
  309. String checkName = name;
  310. if (subProgram != NULL)
  311. {
  312. subProgram->PopulateSubprogram();
  313. if (GetValueByNameInBlock(subProgram, &subProgram->mBlock, checkName, stackFrame, outAddr, outType, outAddrType))
  314. return true;
  315. }
  316. for (int dwarfIdx = mDbgModules.size() - 1; dwarfIdx >= 0; dwarfIdx--)
  317. {
  318. DbgModule* dwarf = mDbgModules[dwarfIdx];
  319. for (auto compileUnit : dwarf->mCompileUnits)
  320. {
  321. if (GetValueByNameInBlock(NULL, compileUnit->mGlobalBlock, checkName, stackFrame, outAddr, outType, outAddrType))
  322. return true;
  323. }
  324. }
  325. return false;
  326. }
  327. static const uint64 kAutoStaticBucketPageSize = 1024ull;
  328. void DebugTarget::AddAutoStaticEntry(const DbgAutoStaticEntry& entry)
  329. {
  330. uint64 remainingSize = entry.mAddrLen;
  331. uint64 offset = entry.mAddrStart % kAutoStaticBucketPageSize;
  332. uint64 curPage = entry.mAddrStart / kAutoStaticBucketPageSize;
  333. while (remainingSize > 0)
  334. {
  335. int bucketIndex = -1;
  336. /*auto map_iter = mAutoStaticEntryBucketMap.find((addr_target)curPage);
  337. if (map_iter != mAutoStaticEntryBucketMap.end())*/
  338. int* bucketIndexPtr = NULL;
  339. if (!mAutoStaticEntryBucketMap.TryAddRaw((addr_target)curPage, NULL, &bucketIndexPtr))
  340. {
  341. bucketIndex = *bucketIndexPtr;
  342. }
  343. else
  344. {
  345. bucketIndex = (int)mAutoStaticEntryBuckets.size();
  346. *bucketIndexPtr = bucketIndex;
  347. mAutoStaticEntryBuckets.push_back(Array<DbgAutoStaticEntry>());
  348. //mAutoStaticEntryBucketMap[(addr_target)curPage] = bucketIndex;
  349. }
  350. mAutoStaticEntryBuckets[bucketIndex].push_back(entry);
  351. uint64 adjSize = BF_MIN(kAutoStaticBucketPageSize - offset, remainingSize);
  352. remainingSize -= adjSize;
  353. offset = 0;
  354. ++curPage;
  355. }
  356. }
  357. void DebugTarget::IterateAutoStaticEntries(uint64 memoryRangeStart, uint64 memoryRangeLen, std::function<void(DbgAutoStaticEntry const&)>& func)
  358. {
  359. uint64 remainingSize = memoryRangeLen;
  360. uint64 offset = memoryRangeStart % kAutoStaticBucketPageSize;
  361. uint64 curPage = memoryRangeStart / kAutoStaticBucketPageSize;
  362. HashSet<DbgVariable*> foundVariables;
  363. while (remainingSize > 0)
  364. {
  365. //int bucketIndex = -1;
  366. /*auto map_iter = mAutoStaticEntryBucketMap.find((addr_target)curPage);
  367. if (map_iter != mAutoStaticEntryBucketMap.end())*/
  368. int* bucketIndexPtr = NULL;
  369. if (mAutoStaticEntryBucketMap.TryGetValue((addr_target)curPage, &bucketIndexPtr))
  370. {
  371. auto const & bucket = mAutoStaticEntryBuckets[*bucketIndexPtr];
  372. for (auto const & entry : bucket)
  373. {
  374. uint64 rangeMin = BF_MAX((uint64)entry.mAddrStart, memoryRangeStart);
  375. uint64 rangeMax = BF_MIN((uint64)entry.mAddrStart + entry.mAddrLen, memoryRangeStart + memoryRangeLen);
  376. if (rangeMin > rangeMax)
  377. continue;
  378. if (foundVariables.Contains(entry.mVariable))
  379. continue;
  380. func(entry);
  381. foundVariables.Add(entry.mVariable);
  382. }
  383. }
  384. uint64 adjSize = std::min(kAutoStaticBucketPageSize - offset, remainingSize);
  385. remainingSize -= adjSize;
  386. offset = 0;
  387. ++curPage;
  388. }
  389. }
  390. void DebugTarget::EvaluateAutoStaticVariable(DbgVariable* variable, const StringImpl& fullName)
  391. {
  392. BF_ASSERT(variable->mIsStatic && !variable->mIsConst); // why are you calling this if you haven't checked these yet
  393. BF_ASSERT(!variable->mInAutoStaticMap);
  394. if ((variable->mLocationData != NULL) && (variable->mLocationLen > 0))
  395. {
  396. DbgAddrType addrType = DbgAddrType_Local;
  397. addr_target variableAddr = variable->mStaticCachedAddr;
  398. if (variableAddr == 0)
  399. {
  400. addrType = DbgAddrType_Target;
  401. variableAddr = variable->mCompileUnit->mDbgModule->EvaluateLocation(NULL, variable->mLocationData, variable->mLocationLen, NULL/*registers*/, &addrType);
  402. }
  403. //BF_ASSERT((addrType == DbgAddrType_Value) || (variableAddr > 0));
  404. if ((addrType == DbgAddrType_Local) && (variableAddr != 0))
  405. {
  406. DbgAutoStaticEntry entry;
  407. entry.mFullName = fullName;
  408. entry.mVariable = variable;
  409. entry.mAddrStart = variableAddr;
  410. entry.mAddrLen = variable->mType->mSize;
  411. AddAutoStaticEntry(entry);
  412. variable->mInAutoStaticMap = true;
  413. }
  414. }
  415. }
  416. void DebugTarget::GetAutoValueNames(DbgAutoValueMapType& outAutos, WdStackFrame* stackFrame, uint64 memoryRangeStart, uint64 memoryRangeLen)
  417. {
  418. BP_ZONE("DebugTarget::GetAutoValueNames");
  419. for (auto dbgModule : mDbgModules)
  420. {
  421. // one-time iteration of mTypeMap
  422. if (mAutoStaticEntryBuckets.empty())
  423. {
  424. if (dbgModule->mTypeMap.IsEmpty())
  425. continue;
  426. for (auto typeEntry : dbgModule->mTypeMap)
  427. {
  428. for (auto variable : typeEntry.mValue->mMemberList)
  429. {
  430. if (variable->mIsConst)
  431. continue;
  432. if (variable->mIsStatic)
  433. {
  434. String fullName = variable->mName;
  435. for (DbgType* scope = typeEntry.mValue; scope && scope->mTypeName; scope = scope->mParent)
  436. fullName = String(scope->mTypeName) + "." + fullName;
  437. EvaluateAutoStaticVariable(variable, fullName);
  438. }
  439. }
  440. }
  441. }
  442. for (int subProgramIdx = (int)dbgModule->mSubprograms.size() - 1; subProgramIdx >= 0; subProgramIdx--)
  443. {
  444. auto subProgram = dbgModule->mSubprograms[subProgramIdx];
  445. GetAutoValueNamesInBlock(outAutos, subProgram, &subProgram->mBlock, stackFrame, memoryRangeStart, memoryRangeLen);
  446. }
  447. for (auto compileUnit : dbgModule->mCompileUnits)
  448. {
  449. GetAutoValueNamesInBlock(outAutos, NULL, compileUnit->mGlobalBlock, stackFrame, memoryRangeStart, memoryRangeLen);
  450. }
  451. }
  452. std::function<void(const DbgAutoStaticEntry&)> iterFunc = [this, &outAutos](const DbgAutoStaticEntry& entry)
  453. {
  454. //outAutos.insert(DbgAutoValueMapType::value_type(entry.mFullName, DbgAutoValueMapType::value_type::second_type(entry.mAddrStart, entry.mAddrLen)));
  455. outAutos.TryAdd(entry.mFullName, std::make_pair(entry.mAddrStart, entry.mAddrLen));
  456. };
  457. IterateAutoStaticEntries(memoryRangeStart, memoryRangeLen, iterFunc);
  458. }
  459. void DebugTarget::GetAutoValueNamesInBlock(DbgAutoValueMapType& outAutos, DbgSubprogram* dwSubprogram, DbgBlock* dwBlock, WdStackFrame* stackFrame, uint64 memoryRangeStart, uint64 memoryRangeLen)
  460. {
  461. addr_target pc = stackFrame->GetSourcePC();
  462. if (dwSubprogram != NULL)
  463. {
  464. auto dwarf = dwSubprogram->mCompileUnit->mDbgModule;
  465. if (dwBlock->mLowPC == -1)
  466. {
  467. //Debug ranges
  468. addr_target* rangeData = (addr_target*)(dwarf->mDebugRangesData + dwBlock->mHighPC);
  469. while (true)
  470. {
  471. addr_target lowPC = *(rangeData++);
  472. if (lowPC == 0)
  473. return;
  474. addr_target highPC = *(rangeData++);
  475. // Matches?
  476. if ((pc >= lowPC) && (pc < highPC))
  477. break;
  478. }
  479. }
  480. else if ((pc < dwBlock->mLowPC) || (pc >= dwBlock->mHighPC))
  481. return;
  482. }
  483. for (auto subBlocks : dwBlock->mSubBlocks)
  484. {
  485. GetAutoValueNamesInBlock(outAutos, dwSubprogram, subBlocks, stackFrame, memoryRangeStart, memoryRangeLen);
  486. }
  487. auto evalFunc = [this, &outAutos, stackFrame, dwSubprogram, memoryRangeStart, memoryRangeLen, dwBlock](Beefy::SLIList<DbgVariable*>& varList)
  488. {
  489. for (auto variable : varList)
  490. {
  491. if (variable->mIsConst)
  492. continue;
  493. if (variable->mRangeStart != 0)
  494. {
  495. auto curPC = stackFrame->mRegisters.GetPC();
  496. if ((curPC < variable->mRangeStart) || (curPC >= variable->mRangeStart + variable->mRangeLen))
  497. continue;
  498. }
  499. if (variable->mIsStatic)
  500. {
  501. if (!variable->mInAutoStaticMap && !dwBlock->mAutoStaticVariablesProcessed)
  502. EvaluateAutoStaticVariable(variable, variable->mName);
  503. if (variable->mInAutoStaticMap)
  504. continue; // we'll pick it up in IterateAutoStaticEntries if it's in range
  505. }
  506. if (variable->mName == NULL)
  507. continue;
  508. if (variable->mType == NULL)
  509. continue;
  510. uint64 variableAddr = 0;
  511. outAutos.TryAdd(variable->mName, std::make_pair(variableAddr, variable->mType->mSize));
  512. }
  513. };
  514. if (dwBlock == &dwSubprogram->mBlock)
  515. {
  516. evalFunc(dwSubprogram->mParams);
  517. }
  518. evalFunc(dwBlock->mVariables);
  519. dwBlock->mAutoStaticVariablesProcessed = true;
  520. }
  521. bool DebugTarget::GetAutoLocalsInBlock(Array<String>& outLocals, DbgSubprogram* dwSubprogram, DbgBlock* dwBlock, WdStackFrame* stackFrame, DbgLineData* dwLineData)
  522. {
  523. std::function<void(const StringImpl& localName)> _AddLocal = [&](const StringImpl& localName)
  524. {
  525. if (!outLocals.Contains(localName))
  526. outLocals.Add(localName);
  527. else
  528. _AddLocal(String("@") + localName);
  529. };
  530. addr_target pc = stackFrame->GetSourcePC();
  531. if (dwSubprogram != NULL)
  532. {
  533. auto dwarf = dwSubprogram->mCompileUnit->mDbgModule;
  534. if (dwBlock->mLowPC == -1)
  535. {
  536. //Debug ranges
  537. addr_target* rangeData = (addr_target*)(dwarf->mDebugRangesData + dwBlock->mHighPC);
  538. while (true)
  539. {
  540. addr_target lowPC = *(rangeData++);
  541. if (lowPC == 0)
  542. return false;
  543. addr_target highPC = *(rangeData++);
  544. // Matches?
  545. if ((pc >= lowPC) && (pc < highPC))
  546. break;
  547. }
  548. }
  549. else if ((pc < dwBlock->mLowPC) || (pc >= dwBlock->mHighPC))
  550. return false;
  551. }
  552. for (auto subBlock : dwBlock->mSubBlocks)
  553. {
  554. GetAutoLocalsInBlock(outLocals, dwSubprogram, subBlock, stackFrame, dwLineData);
  555. }
  556. if (dwBlock == &dwSubprogram->mBlock)
  557. {
  558. for (auto variable : dwSubprogram->mParams)
  559. {
  560. if ((variable->mName != NULL) &&
  561. (variable->mName[0] != '$') &&
  562. ((variable->mLocationData != NULL) || (variable->mIsConst)))
  563. _AddLocal(variable->mName);
  564. }
  565. }
  566. for (auto variable : dwBlock->mVariables)
  567. {
  568. if (variable->mRangeStart != 0)
  569. {
  570. auto curPC = stackFrame->GetSourcePC();
  571. if ((curPC < variable->mRangeStart) || (curPC >= variable->mRangeStart + variable->mRangeLen))
  572. continue;
  573. }
  574. if (//(dwLineData->mLine >= variable->mDeclLine) &&
  575. (variable->mName[0] != '$'))
  576. _AddLocal(variable->mName);
  577. }
  578. return true;
  579. }
  580. DbgSubprogram* DebugTarget::FindSubProgram(addr_target pc, DbgOnDemandKind onDemandKind)
  581. {
  582. BP_ZONE("WinDebugger::FindSubProgram");
  583. for (int pass = 0; pass < 2; pass++)
  584. {
  585. int mapBlockSize = 1 << DbgRadixMap<DbgSubprogramMapEntry*>::BLOCK_SHIFT;
  586. DbgSubprogram* foundSubprogram = NULL;
  587. // Even though the radix map is LIFO, we might find an inline parent in an earlier block
  588. // so we can't terminate the search until we exhaust the lookup
  589. addr_target bestStart = 0;
  590. for (int offset = 0; offset < DBG_MAX_LOOKBACK; offset += mapBlockSize)
  591. {
  592. DbgSubprogramMapEntry* subprogramMapEntry = mSubprogramMap.FindFirstLeafAt(pc - offset);
  593. while (subprogramMapEntry != NULL)
  594. {
  595. auto dwSubprogram = subprogramMapEntry->mEntry;
  596. if ((pc >= dwSubprogram->mBlock.mLowPC) && (pc < dwSubprogram->mBlock.mHighPC) && (dwSubprogram->mBlock.mLowPC > bestStart))
  597. {
  598. if ((dwSubprogram->mLineInfo != NULL) && (dwSubprogram->mLineInfo->mHasInlinees))
  599. {
  600. if (dwSubprogram->mNeedLineDataFixup)
  601. mDebugger->FixupLineDataForSubprogram(dwSubprogram);
  602. DbgSubprogram* inlinedSubprogram = NULL;
  603. if (dwSubprogram->FindClosestLine(pc, &inlinedSubprogram) != NULL)
  604. {
  605. return inlinedSubprogram;
  606. }
  607. }
  608. /*bool inGap = false;
  609. if (dwSubprogram->mHasLineGaps)
  610. {
  611. mDebugger->FixupLineDataForSubprogram(dwSubprogram);
  612. auto lineData = dwSubprogram->FindClosestLine(pc, 0, true);
  613. inGap == (lineData == NULL) || (lineData->mLine == -1);
  614. }
  615. if (!inGap)
  616. {
  617. foundSubprogram = dwSubprogram;
  618. bestStart = dwSubprogram->mBlock.mLowPC;
  619. }
  620. else
  621. {
  622. }*/
  623. return dwSubprogram;
  624. //foundSubprogram = dwSubprogram;
  625. //bestStart = dwSubprogram->mBlock.mLowPC;
  626. }
  627. subprogramMapEntry = subprogramMapEntry->mNext;
  628. }
  629. }
  630. if (foundSubprogram != NULL)
  631. return foundSubprogram;
  632. if (pass != 0)
  633. return NULL;
  634. DbgCompileUnitContrib* contrib = mContribMap.Get(pc, DBG_MAX_LOOKBACK);
  635. if ((contrib != NULL) && (pc >= contrib->mAddress) && (pc < contrib->mAddress + contrib->mLength))
  636. {
  637. contrib->mDbgModule->ParseCompileUnit(contrib->mCompileUnitId);
  638. }
  639. else if (onDemandKind != DbgOnDemandKind_None)
  640. {
  641. bool found = false;
  642. for (auto module : mDbgModules)
  643. {
  644. if ((pc >= module->mImageBase) && (pc < module->mImageBase + module->mImageSize))
  645. {
  646. if ((module->mFilePath.EndsWith("ntdll.dll", String::CompareKind_OrdinalIgnoreCase)) ||
  647. (module->mFilePath.EndsWith("kernel32.dll", String::CompareKind_OrdinalIgnoreCase)) ||
  648. (module->mFilePath.EndsWith("kernelbase.dll", String::CompareKind_OrdinalIgnoreCase)))
  649. {
  650. String symName;
  651. addr_target addrOfs = 0;
  652. if (FindSymbolAt(pc, &symName, &addrOfs))
  653. {
  654. // We don't need any symbols for the loader
  655. if ((symName == "LdrInitShimEngineDynamic") ||
  656. (symName == "DebugBreak"))
  657. continue;
  658. }
  659. }
  660. if (module->RequestDebugInfo(onDemandKind == DbgOnDemandKind_AllowRemote))
  661. {
  662. // Give another chance to ParseCompileUnit and then match again
  663. found = true;
  664. pass = -1;
  665. }
  666. }
  667. }
  668. // No contribution found
  669. if (!found)
  670. break;
  671. }
  672. }
  673. //BF_ASSERT(slowFoundSubprogram == foundSubprogram);
  674. return NULL;
  675. }
  676. void DebugTarget::GetCompilerSettings()
  677. {
  678. if (!mCheckedCompilerSettings)
  679. {
  680. DbgType* bfObjectType = GetMainDbgModule()->FindType("System.CompilerSettings", NULL, DbgLanguage_Beef);
  681. if (bfObjectType != NULL)
  682. {
  683. bfObjectType->PopulateType();
  684. if (bfObjectType->IsBfObjectPtr())
  685. bfObjectType = bfObjectType->mTypeParam;
  686. for (auto member : bfObjectType->mMemberList)
  687. {
  688. if (strcmp(member->mName, "cHasDebugFlags") == 0)
  689. mBfObjectHasFlags = member->mConstValue != 0;
  690. if (strcmp(member->mName, "cHasVDataExtender") == 0)
  691. mBfObjectHasVDataExtender = member->mConstValue != 0;
  692. if (strcmp(member->mName, "cVDataIntefaceSlotCount") == 0)
  693. mBfObjectVDataIntefaceSlotCount = (int)member->mConstValue;
  694. }
  695. auto objectRoot = bfObjectType->GetBaseType();
  696. BF_ASSERT(strcmp(objectRoot->mTypeName, "Object") == 0);
  697. mBfObjectSize = objectRoot->GetByteCount();
  698. }
  699. mCheckedCompilerSettings = true;
  700. }
  701. }
  702. #if 1
  703. bool DebugTarget::RollBackStackFrame_ExceptionDirectory(addr_target findPC, CPURegisters* registers, addr_target* outReturnAddressLoc, bool& alreadyRolledBackPC)
  704. {
  705. addr_target pcAddress = registers->GetPC();
  706. auto exceptionDirectoryEntry = mExceptionDirectoryMap.Get(findPC, DBG_MAX_LOOKBACK);
  707. if ((exceptionDirectoryEntry != NULL) && (findPC >= exceptionDirectoryEntry->mAddress) &&
  708. (findPC < exceptionDirectoryEntry->mAddress + exceptionDirectoryEntry->mAddressLength))
  709. {
  710. auto dbgModule = exceptionDirectoryEntry->mDbgModule;
  711. //const uint8* data = dbgModule->mExceptionData + exceptionDirectoryEntry->mExceptionPos;
  712. uint32 exceptionPos = exceptionDirectoryEntry->mExceptionPos;
  713. if (dbgModule->mIsHotObjectFile)
  714. {
  715. exceptionPos -= dbgModule->mImageBase - dbgModule->GetLinkedModule()->mImageBase;
  716. }
  717. while ((exceptionPos & 1) != 0)
  718. {
  719. // It's a reference to another entry -- directly reference the 'exceptionPos' from that other entry
  720. dbgModule->mOrigImageData->Read(dbgModule->mImageBase + (exceptionPos & ~1) + 8, (uint8*)&exceptionPos, 4);
  721. }
  722. struct EntryHeader
  723. {
  724. uint8 mVersion;
  725. uint8 mPrologSize;
  726. uint8 mNumUnwindCodes;
  727. uint8 mFrameRegister;
  728. };
  729. EntryHeader entryHeader;
  730. dbgModule->mOrigImageData->Read(dbgModule->mImageBase + exceptionPos, (uint8*)&entryHeader, sizeof(EntryHeader));
  731. uint8 version = entryHeader.mVersion;
  732. uint8 flags = (version >> 3);
  733. version &= 7;
  734. //TODO: Sometimes we get a 'version 2'. Not sure how to parse that yet.
  735. //BF_ASSERT(version == 1);
  736. //uint8 prologSize = GET(uint8);
  737. //uint8 numUnwindCodes = GET(uint8);
  738. int dataSize = entryHeader.mNumUnwindCodes * 2;
  739. if (flags & 4) // UNW_FLAG_CHAININFO
  740. {
  741. if ((entryHeader.mNumUnwindCodes % 2) == 1)
  742. dataSize += 2; // Align
  743. dataSize += sizeof(uint32)*3;
  744. }
  745. uint8 dataBuf[512];
  746. dbgModule->mOrigImageData->Read(dbgModule->mImageBase + exceptionPos + sizeof(EntryHeader), dataBuf, dataSize);
  747. const uint8* data = dataBuf;
  748. if (flags & 1) // UNW_FLAG_EHANDLER
  749. {
  750. }
  751. else if (flags & 4) // UNW_FLAG_CHAININFO
  752. {
  753. }
  754. /*if (pcAddress < exceptionDirectoryEntry->mAddress + prologSize)
  755. {
  756. // We're in the prolog so just do a standard leaf 'ret'
  757. return false;
  758. }*/
  759. addr_target* regSP = registers->GetSPRegisterRef();
  760. int regFPOffset = 0;
  761. uint8 frameRegister = entryHeader.mFrameRegister;
  762. uint8 frameRegisterOffset = frameRegister >> 4;
  763. frameRegister &= 15;
  764. intptr_target newSP = 0;
  765. const uint8* paramAreaStart = data;
  766. const uint8* dataEnd = data + entryHeader.mNumUnwindCodes * 2;
  767. while (data < dataEnd)
  768. {
  769. uint8 offsetInProlog = GET(uint8);
  770. uint8 unwindOpCode = GET(uint8);
  771. uint8 opInfo = unwindOpCode >> 4;
  772. unwindOpCode &= 15;
  773. bool executeOp = pcAddress >= exceptionDirectoryEntry->mAddress - exceptionDirectoryEntry->mOrigAddressOffset + offsetInProlog;
  774. if ((unwindOpCode == 0) && (executeOp))
  775. {
  776. // UWOP_PUSH_NONVOL
  777. intptr_target* regRef = registers->GetExceptionRegisterRef(opInfo);
  778. if (!gDebugger->ReadMemory(*regSP, sizeof(intptr_target), regRef))
  779. return false;
  780. *regSP += sizeof(intptr_target);
  781. }
  782. else if (unwindOpCode == 1)
  783. {
  784. // UWOP_ALLOC_LARGE
  785. int allocSize = 0;
  786. if (opInfo == 0)
  787. allocSize = (int)GET(uint16) * 8;
  788. else if (opInfo == 1)
  789. allocSize = (int)GET(int32);
  790. if (executeOp)
  791. *regSP += allocSize;
  792. }
  793. else if ((unwindOpCode == 2) && (executeOp))
  794. {
  795. // UWOP_ALLOC_SMALL
  796. int allocSize = (int)opInfo * 8 + 8;
  797. *regSP += allocSize;
  798. }
  799. else if ((unwindOpCode == 3) && (executeOp))
  800. {
  801. // UWOP_SET_FPREG
  802. intptr_target* regRef = registers->GetExceptionRegisterRef(frameRegister);
  803. *regSP = *regRef - (16 * frameRegisterOffset);
  804. }
  805. else if (unwindOpCode == 4)
  806. {
  807. // UWOP_SAVE_NONVOL
  808. int offset = (int)GET(uint16) * 8;
  809. if (executeOp)
  810. {
  811. intptr_target* regRef = registers->GetExceptionRegisterRef(opInfo);
  812. if (!gDebugger->ReadMemory(*regSP + offset, sizeof(intptr_target), regRef))
  813. return false;
  814. }
  815. }
  816. else if (unwindOpCode == 5)
  817. {
  818. // UWOP_SAVE_NONVOL_FAR
  819. int offset = GET(int32);
  820. if (executeOp)
  821. {
  822. intptr_target* regRef = registers->GetExceptionRegisterRef(opInfo);
  823. if (!gDebugger->ReadMemory(*regSP + offset, sizeof(intptr_target), regRef))
  824. return false;
  825. }
  826. }
  827. else if (unwindOpCode == 8)
  828. {
  829. // UWOP_SAVE_XMM128
  830. int offset = (int)GET(uint16) * 16;
  831. if (executeOp)
  832. {
  833. auto* regRef = registers->GetXMMRegRef(opInfo);
  834. if (!gDebugger->ReadMemory(*regSP + offset, sizeof(*regRef), regRef))
  835. return false;
  836. }
  837. }
  838. else if (unwindOpCode == 9)
  839. {
  840. // UWOP_SAVE_XMM128_FAR
  841. int offset = GET(int32);
  842. if (executeOp)
  843. {
  844. auto* regRef = registers->GetXMMRegRef(opInfo);
  845. if (!gDebugger->ReadMemory(*regSP + offset, sizeof(*regRef), regRef))
  846. return false;
  847. }
  848. }
  849. else if (unwindOpCode == 10)
  850. {
  851. // UWOP_PUSH_MACHFRAME
  852. if (executeOp)
  853. {
  854. alreadyRolledBackPC = true;
  855. if (opInfo == 0)
  856. {
  857. addr_target regRIP;
  858. gDebugger->ReadMemory(*regSP, sizeof(intptr_target), &regRIP); // RIP (correct back trace)
  859. *regSP += sizeof(intptr_target);
  860. addr_target reg;
  861. gDebugger->ReadMemory(*regSP, sizeof(intptr_target), &reg); // CS
  862. *regSP += sizeof(intptr_target);
  863. gDebugger->ReadMemory(*regSP, sizeof(intptr_target), &reg); // EFLAGS
  864. *regSP += sizeof(intptr_target);
  865. addr_target oldRSP;
  866. gDebugger->ReadMemory(*regSP, sizeof(intptr_target), &oldRSP); // Old RSP
  867. *regSP += sizeof(intptr_target);
  868. gDebugger->ReadMemory(*regSP, sizeof(intptr_target), &reg); //SS
  869. *regSP += sizeof(intptr_target);
  870. addr_target* regPC = registers->GetPCRegisterRef();
  871. *regSP = oldRSP;
  872. *regPC = regRIP;
  873. }
  874. else
  875. {
  876. *regSP += 6 * sizeof(intptr_target);
  877. }
  878. }
  879. }
  880. // Note: RCX/RDX are reversed
  881. }
  882. if (flags & 4) // UNW_FLAG_CHAININFO
  883. {
  884. if (((intptr)data & 3) != 0)
  885. {
  886. // Align
  887. data = (const uint8*)(((intptr)data + 3) & ~3);
  888. }
  889. uint32 chainedRVAStart = GET(uint32);
  890. uint32 chainedRVAEnd = GET(uint32);
  891. uint32 chainedUnwindRVA = GET(uint32);
  892. return RollBackStackFrame_ExceptionDirectory(dbgModule->mImageBase + chainedRVAStart, registers, outReturnAddressLoc, alreadyRolledBackPC);
  893. }
  894. return true;
  895. }
  896. return false;
  897. }
  898. // We write the modified callerRegisters into the saved memory locations in the callee's stack frame --
  899. // this is needed for modifying variables tied to non-volatile registers on non-topmost stack frames
  900. bool DebugTarget::PropogateRegisterUpCallStack_ExceptionDirectory(addr_target findPC, CPURegisters* callerRegisters, CPURegisters* calleeRegisters, void* regPtr, bool& wasSaved)
  901. {
  902. addr_target pcAddress = calleeRegisters->GetPC();
  903. auto exceptionDirectoryEntry = mExceptionDirectoryMap.Get(findPC, DBG_MAX_LOOKBACK);
  904. if ((exceptionDirectoryEntry != NULL) && (findPC >= exceptionDirectoryEntry->mAddress) &&
  905. (findPC < exceptionDirectoryEntry->mAddress + exceptionDirectoryEntry->mAddressLength))
  906. {
  907. auto dbgModule = exceptionDirectoryEntry->mDbgModule;
  908. //const uint8* data = dbgModule->mExceptionData + exceptionDirectoryEntry->mExceptionPos;
  909. uint32 exceptionPos = exceptionDirectoryEntry->mExceptionPos;
  910. while ((exceptionPos & 1) != 0)
  911. {
  912. // It's a reference to another entry -- directly reference the 'exceptionPos' from that other entry
  913. dbgModule->mOrigImageData->Read(dbgModule->mImageBase + (exceptionPos & ~1) + 8, (uint8*)&exceptionPos, 4);
  914. }
  915. struct EntryHeader
  916. {
  917. uint8 mVersion;
  918. uint8 mPrologSize;
  919. uint8 mNumUnwindCodes;
  920. uint8 mFrameRegister;
  921. };
  922. EntryHeader entryHeader;
  923. dbgModule->mOrigImageData->Read(dbgModule->mImageBase + exceptionPos, (uint8*)&entryHeader, sizeof(EntryHeader));
  924. uint8 version = entryHeader.mVersion;
  925. uint8 flags = (version >> 3);
  926. version &= 7;
  927. int dataSize = entryHeader.mNumUnwindCodes * 2;
  928. if (flags & 4) // UNW_FLAG_CHAININFO
  929. {
  930. if ((entryHeader.mNumUnwindCodes % 2) == 1)
  931. dataSize += 2; // Align
  932. dataSize += sizeof(uint32)*3;
  933. }
  934. uint8 dataBuf[512];
  935. dbgModule->mOrigImageData->Read(dbgModule->mImageBase + exceptionPos + sizeof(EntryHeader), dataBuf, dataSize);
  936. const uint8* data = dataBuf;
  937. if (flags & 1) // UNW_FLAG_EHANDLER
  938. {
  939. }
  940. else if (flags & 4) // UNW_FLAG_CHAININFO
  941. {
  942. }
  943. /*if (pcAddress < exceptionDirectoryEntry->mAddress + prologSize)
  944. {
  945. // We're in the prolog so just do a standard leaf 'ret'
  946. return false;
  947. }*/
  948. addr_target regSP = calleeRegisters->GetSP();
  949. int regFPOffset = 0;
  950. uint8 frameRegister = entryHeader.mFrameRegister;
  951. uint8 frameRegisterOffset = frameRegister >> 4;
  952. frameRegister &= 15;
  953. intptr_target newSP = 0;
  954. const uint8* paramAreaStart = data;
  955. const uint8* dataEnd = data + entryHeader.mNumUnwindCodes * 2;
  956. while (data < dataEnd)
  957. {
  958. uint8 offsetInProlog = GET(uint8);
  959. uint8 unwindOpCode = GET(uint8);
  960. uint8 opInfo = unwindOpCode >> 4;
  961. unwindOpCode &= 15;
  962. bool executeOp = pcAddress >= exceptionDirectoryEntry->mAddress - exceptionDirectoryEntry->mOrigAddressOffset + offsetInProlog;
  963. if ((unwindOpCode == 0) && (executeOp))
  964. {
  965. // UWOP_PUSH_NONVOL
  966. intptr_target* regRef = callerRegisters->GetExceptionRegisterRef(opInfo);
  967. if (regRef == regPtr)
  968. {
  969. mDebugger->WriteMemory(regSP, regRef, sizeof(intptr_target));
  970. wasSaved = true;
  971. }
  972. regSP += sizeof(intptr_target);
  973. }
  974. else if (unwindOpCode == 1)
  975. {
  976. // UWOP_ALLOC_LARGE
  977. int allocSize = 0;
  978. if (opInfo == 0)
  979. allocSize = (int)GET(uint16) * 8;
  980. else if (opInfo == 1)
  981. allocSize = (int)GET(int32);
  982. if (executeOp)
  983. regSP += allocSize;
  984. }
  985. else if ((unwindOpCode == 2) && (executeOp))
  986. {
  987. // UWOP_ALLOC_SMALL
  988. int allocSize = (int)opInfo * 8 + 8;
  989. regSP += allocSize;
  990. }
  991. else if ((unwindOpCode == 3) && (executeOp))
  992. {
  993. // UWOP_SET_FPREG
  994. intptr_target* regRef = callerRegisters->GetExceptionRegisterRef(frameRegister);
  995. regSP = *regRef - (16 * frameRegisterOffset);
  996. }
  997. else if (unwindOpCode == 4)
  998. {
  999. // UWOP_SAVE_NONVOL
  1000. int offset = (int)GET(uint16) * 8;
  1001. if (executeOp)
  1002. {
  1003. intptr_target* regRef = callerRegisters->GetExceptionRegisterRef(opInfo);
  1004. if (regRef == regPtr)
  1005. {
  1006. if (!gDebugger->WriteMemory(regSP + offset, regRef, sizeof(intptr_target)))
  1007. return false;
  1008. wasSaved = true;
  1009. }
  1010. }
  1011. }
  1012. else if (unwindOpCode == 5)
  1013. {
  1014. // UWOP_SAVE_NONVOL_FAR
  1015. int offset = GET(int32);
  1016. if (executeOp)
  1017. {
  1018. intptr_target* regRef = callerRegisters->GetExceptionRegisterRef(opInfo);
  1019. if (regRef == regPtr)
  1020. {
  1021. if (!gDebugger->WriteMemory(regSP + offset, regRef, sizeof(intptr_target)))
  1022. return false;
  1023. wasSaved = true;
  1024. }
  1025. }
  1026. }
  1027. else if (unwindOpCode == 8)
  1028. {
  1029. // UWOP_SAVE_XMM128
  1030. int offset = (int)GET(uint16) * 16;
  1031. if (executeOp)
  1032. {
  1033. auto* regRef = callerRegisters->GetXMMRegRef(opInfo);
  1034. if (regRef == regPtr)
  1035. {
  1036. if (!gDebugger->WriteMemory(regSP + offset, regRef, sizeof(*regRef)))
  1037. return false;
  1038. wasSaved = true;
  1039. }
  1040. }
  1041. }
  1042. else if (unwindOpCode == 9)
  1043. {
  1044. // UWOP_SAVE_XMM128_FAR
  1045. int offset = GET(int32);
  1046. if (executeOp)
  1047. {
  1048. auto* regRef = callerRegisters->GetXMMRegRef(opInfo);
  1049. if (regRef == regPtr)
  1050. {
  1051. if (!gDebugger->WriteMemory(regSP + offset, regRef, sizeof(*regRef)))
  1052. return false;
  1053. wasSaved = true;
  1054. }
  1055. }
  1056. }
  1057. else if (unwindOpCode == 10)
  1058. {
  1059. // UWOP_PUSH_MACHFRAME
  1060. if (executeOp)
  1061. {
  1062. if (opInfo == 0)
  1063. {
  1064. //addr_target regRIP;
  1065. //gDebugger->ReadMemory(*regSP, sizeof(intptr_target), &regRIP); // RIP (correct back trace)
  1066. regSP += sizeof(intptr_target);
  1067. //addr_target reg;
  1068. //gDebugger->ReadMemory(*regSP, sizeof(intptr_target), &reg); // CS
  1069. regSP += sizeof(intptr_target);
  1070. //gDebugger->ReadMemory(*regSP, sizeof(intptr_target), &reg); // EFLAGS
  1071. regSP += sizeof(intptr_target);
  1072. //addr_target oldRSP;
  1073. //gDebugger->ReadMemory(*regSP, sizeof(intptr_target), &oldRSP); // Old RSP
  1074. regSP += sizeof(intptr_target);
  1075. //gDebugger->ReadMemory(*regSP, sizeof(intptr_target), &reg); //SS
  1076. regSP += sizeof(intptr_target);
  1077. addr_target* regPC = calleeRegisters->GetPCRegisterRef();
  1078. //*regSP = oldRSP;
  1079. //*regPC = regRIP;
  1080. }
  1081. else
  1082. {
  1083. regSP += 6 * sizeof(intptr_target);
  1084. }
  1085. }
  1086. }
  1087. // Note: RCX/RDX are reversed
  1088. }
  1089. if (flags & 4) // UNW_FLAG_CHAININFO
  1090. {
  1091. if (((intptr)data & 3) != 0)
  1092. {
  1093. // Align
  1094. data = (const uint8*)(((intptr)data + 3) & ~3);
  1095. }
  1096. uint32 chainedRVAStart = GET(uint32);
  1097. uint32 chainedRVAEnd = GET(uint32);
  1098. uint32 chainedUnwindRVA = GET(uint32);
  1099. return PropogateRegisterUpCallStack_ExceptionDirectory(dbgModule->mImageBase + chainedRVAStart, callerRegisters, calleeRegisters, regPtr, wasSaved);
  1100. }
  1101. return true;
  1102. }
  1103. return false;
  1104. }
  1105. #endif
  1106. #if 0
  1107. bool DebugTarget::RollBackStackFrame_ExceptionDirectory(addr_target findPC, CPURegisters* registers, addr_target* outReturnAddressLoc)
  1108. {
  1109. addr_target pcAddress = registers->GetPC();
  1110. auto exceptionDirectoryEntry = mExceptionDirectoryMap.Get(findPC, DBG_MAX_LOOKBACK);
  1111. if ((exceptionDirectoryEntry != NULL) && (findPC >= exceptionDirectoryEntry->mAddress) &&
  1112. (findPC < exceptionDirectoryEntry->mAddress + exceptionDirectoryEntry->mAddressLength))
  1113. {
  1114. auto dbgModule = exceptionDirectoryEntry->mDbgModule;
  1115. const uint8* data = dbgModule->mExceptionData + (exceptionDirectoryEntry->mExceptionPos - dbgModule->mExceptionDataRVA);
  1116. uint8 version = GET(uint8);
  1117. uint8 flags = (version >> 3);
  1118. version &= 7;
  1119. uint8 prologSize = GET(uint8);
  1120. uint8 numUnwindCodes = GET(uint8);
  1121. if (exceptionDirectoryEntry->mAddress - dbgModule->mImageBase == 0x0000000000048efc)
  1122. {
  1123. }
  1124. if (flags & 1) // UNW_FLAG_EHANDLER
  1125. {
  1126. }
  1127. else if (flags & 4) // UNW_FLAG_CHAININFO
  1128. {
  1129. }
  1130. /*if (pcAddress < exceptionDirectoryEntry->mAddress + prologSize)
  1131. {
  1132. // We're in the prolog so just do a standard leaf 'ret'
  1133. return false;
  1134. }*/
  1135. addr_target* regSP = registers->GetSPRegisterRef();
  1136. int regFPOffset = 0;
  1137. uint8 frameRegister = GET(uint8);
  1138. uint8 frameRegisterOffset = frameRegister >> 4;
  1139. frameRegister &= 15;
  1140. intptr_target newSP = 0;
  1141. const uint8* paramAreaStart = data;
  1142. const uint8* dataEnd = data + numUnwindCodes * 2;
  1143. while (data < dataEnd)
  1144. {
  1145. uint8 offsetInProlog = GET(uint8);
  1146. uint8 unwindOpCode = GET(uint8);
  1147. uint8 opInfo = unwindOpCode >> 4;
  1148. unwindOpCode &= 15;
  1149. bool executeOp = pcAddress >= exceptionDirectoryEntry->mAddress - exceptionDirectoryEntry->mOrigAddressOffset + offsetInProlog;
  1150. if ((unwindOpCode == 0) && (executeOp))
  1151. {
  1152. // UWOP_PUSH_NONVOL
  1153. intptr_target* regRef = registers->GetExceptionRegisterRef(opInfo);
  1154. gDebugger->ReadMemory(*regSP, sizeof(intptr_target), regRef);
  1155. *regSP += sizeof(intptr_target);
  1156. }
  1157. else if (unwindOpCode == 1)
  1158. {
  1159. // UWOP_ALLOC_LARGE
  1160. int allocSize = 0;
  1161. if (opInfo == 0)
  1162. allocSize = (int)GET(uint16) * 8;
  1163. else if (opInfo == 1)
  1164. allocSize = (int)GET(int32);
  1165. if (executeOp)
  1166. *regSP += allocSize;
  1167. }
  1168. else if ((unwindOpCode == 2) && (executeOp))
  1169. {
  1170. // UWOP_ALLOC_SMALL
  1171. int allocSize = (int)opInfo * 8 + 8;
  1172. *regSP += allocSize;
  1173. }
  1174. else if ((unwindOpCode == 3) && (executeOp))
  1175. {
  1176. // UWOP_SET_FPREG
  1177. intptr_target* regRef = registers->GetExceptionRegisterRef(frameRegister);
  1178. *regSP = *regRef - (16 * frameRegisterOffset);
  1179. }
  1180. else if (unwindOpCode == 4)
  1181. {
  1182. // UWOP_SAVE_NONVOL
  1183. int offset = (int)GET(uint16) * 8;
  1184. if (executeOp)
  1185. {
  1186. intptr_target* regRef = registers->GetExceptionRegisterRef(opInfo);
  1187. gDebugger->ReadMemory(*regSP - offset, sizeof(intptr_target), regRef);
  1188. }
  1189. }
  1190. else if (unwindOpCode == 5)
  1191. {
  1192. // UWOP_SAVE_NONVOL_FAR
  1193. int offset = GET(int32);
  1194. if (executeOp)
  1195. {
  1196. intptr_target* regRef = registers->GetExceptionRegisterRef(opInfo);
  1197. gDebugger->ReadMemory(*regSP - offset, sizeof(intptr_target), regRef);
  1198. }
  1199. }
  1200. else if (unwindOpCode == 8)
  1201. {
  1202. // UWOP_SAVE_XMM128
  1203. int offset = (int)GET(uint16) * 16;
  1204. if (executeOp)
  1205. {
  1206. auto* regRef = registers->GetXMMRegRef(opInfo);
  1207. gDebugger->ReadMemory(*regSP - offset, sizeof(*regRef), regRef);
  1208. }
  1209. }
  1210. else if (unwindOpCode == 9)
  1211. {
  1212. // UWOP_SAVE_XMM128_FAR
  1213. int offset = GET(int32);
  1214. if (executeOp)
  1215. {
  1216. auto* regRef = registers->GetXMMRegRef(opInfo);
  1217. gDebugger->ReadMemory(*regSP - offset, sizeof(*regRef), regRef);
  1218. }
  1219. }
  1220. else if (unwindOpCode == 10)
  1221. {
  1222. // UWOP_PUSH_MACHFRAME
  1223. BF_ASSERT(0 == "Not supported");
  1224. }
  1225. // Note: RCX/RDX are reversed
  1226. }
  1227. if (flags & 4) // UNW_FLAG_CHAININFO
  1228. {
  1229. if (((intptr)data & 3) != 0)
  1230. {
  1231. // Align
  1232. data = (const uint8*)(((intptr)data + 3) & ~3);
  1233. }
  1234. uint32 chainedRVAStart = GET(uint32);
  1235. uint32 chainedRVAEnd = GET(uint32);
  1236. uint32 chainedUnwindRVA = GET(uint32);
  1237. return RollBackStackFrame_ExceptionDirectory(dbgModule->mImageBase + chainedRVAStart, registers, outReturnAddressLoc);
  1238. }
  1239. return true;
  1240. }
  1241. return false;
  1242. }
  1243. #endif
  1244. bool DebugTarget::RollBackStackFrame_ExceptionDirectory(CPURegisters* registers, addr_target* outReturnAddressLoc, bool& alreadyRolledBackPC)
  1245. {
  1246. addr_target pcAddress = (addr_target)registers->GetPC();
  1247. return RollBackStackFrame_ExceptionDirectory(registers->GetPC(), registers, outReturnAddressLoc, alreadyRolledBackPC);
  1248. }
  1249. bool DebugTarget::RollBackStackFrame_DwFrameDescriptor(CPURegisters* registers, addr_target* outReturnAddressLoc)
  1250. {
  1251. addr_target pcAddress = (addr_target)registers->GetPC();
  1252. //TODO: Verify we replaced this correctly
  1253. /*auto stackFrameItr = mFrameDescriptorMap.upper_bound(pcAddress);
  1254. if (stackFrameItr != mFrameDescriptorMap.end())
  1255. stackFrameItr--;
  1256. if (stackFrameItr == mFrameDescriptorMap.end())
  1257. return false;*/
  1258. if (mDwFrameDescriptorMap.empty())
  1259. return false;
  1260. auto stackFrameItr = mDwFrameDescriptorMap.upper_bound(pcAddress);
  1261. if (stackFrameItr == mDwFrameDescriptorMap.begin())
  1262. return false;
  1263. stackFrameItr--;
  1264. auto dwFrameDescriptor = &stackFrameItr->second;
  1265. if (pcAddress > dwFrameDescriptor->mHighPC)
  1266. return false;
  1267. struct RegisterRuleData
  1268. {
  1269. public:
  1270. int mRegisterRule;
  1271. int mParamOffset;
  1272. const uint8* mParamData;
  1273. public:
  1274. RegisterRuleData()
  1275. {
  1276. mRegisterRule = DW_CFA_undefined;
  1277. mParamOffset = 0;
  1278. mParamData = NULL;
  1279. }
  1280. };
  1281. struct State
  1282. {
  1283. State* mPrevState;
  1284. RegisterRuleData mRegisterRuleDataArray[CPURegisters::kNumIntRegs];
  1285. int mRegisterRuleDataIdx;
  1286. addr_target mCFA = 0;
  1287. int mCFAOffset = 0;
  1288. State()
  1289. {
  1290. mPrevState = NULL;
  1291. mCFA = 0;
  1292. mCFAOffset = 0;
  1293. mRegisterRuleDataIdx = -1;
  1294. }
  1295. };
  1296. State initialState;
  1297. State rootState;
  1298. rootState.mRegisterRuleDataIdx = DwarfReg_SP;
  1299. State* state = &rootState;
  1300. // Set up default rule to restore stack pointer
  1301. state->mRegisterRuleDataArray[state->mRegisterRuleDataIdx].mRegisterRule = DW_CFA_val_offset;
  1302. state->mRegisterRuleDataArray[state->mRegisterRuleDataIdx].mParamOffset = 0;
  1303. for (int pass = 0; pass < 2; pass++)
  1304. {
  1305. /*if ((pass == 0) && (dwFrameDescriptor->mCommonFrameDescriptor == NULL))
  1306. continue;*/
  1307. addr_target curLoc = dwFrameDescriptor->mLowPC;
  1308. const uint8* data = (pass == 0) ? dwFrameDescriptor->mCommonFrameDescriptor->mInstData : dwFrameDescriptor->mInstData;
  1309. const uint8* dataEnd = data + ((pass == 0) ? dwFrameDescriptor->mCommonFrameDescriptor->mInstLen : dwFrameDescriptor->mInstLen);
  1310. if (pass == 1)
  1311. initialState = rootState;
  1312. while ((data < dataEnd) && (pcAddress >= curLoc))
  1313. {
  1314. uint8 opCode = GET(uint8);
  1315. if ((opCode >= DW_CFA_advance_loc) && (opCode < DW_CFA_offset0))
  1316. {
  1317. int advance = opCode - DW_CFA_advance_loc;
  1318. curLoc += advance * dwFrameDescriptor->mCommonFrameDescriptor->mCodeAlignmentFactor;
  1319. }
  1320. else if (opCode >= DW_CFA_restore)
  1321. {
  1322. int regNum = opCode - DW_CFA_restore;
  1323. state->mRegisterRuleDataArray[regNum] = initialState.mRegisterRuleDataArray[regNum];
  1324. }
  1325. else
  1326. {
  1327. switch (opCode)
  1328. {
  1329. case DW_CFA_advance_loc1:
  1330. curLoc += GET(uint8) * dwFrameDescriptor->mCommonFrameDescriptor->mCodeAlignmentFactor;
  1331. break;
  1332. case DW_CFA_advance_loc2:
  1333. curLoc += GET(uint16) * dwFrameDescriptor->mCommonFrameDescriptor->mCodeAlignmentFactor;
  1334. break;
  1335. case DW_CFA_advance_loc4:
  1336. curLoc += GET(uint32) * dwFrameDescriptor->mCommonFrameDescriptor->mCodeAlignmentFactor;
  1337. break;
  1338. case DW_CFA_def_cfa:
  1339. {
  1340. int regNum = (int)DecodeULEB128(data);
  1341. state->mCFAOffset = (int)DecodeULEB128(data);
  1342. BF_ASSERT(regNum < CPURegisters::kNumIntRegs);
  1343. state->mCFA = registers->mIntRegsArray[regNum] + state->mCFAOffset;
  1344. }
  1345. break;
  1346. case DW_CFA_def_cfa_offset:
  1347. state->mCFA -= state->mCFAOffset;
  1348. state->mCFAOffset = DecodeULEB128(data);
  1349. state->mCFA += state->mCFAOffset;
  1350. case DW_CFA_nop:
  1351. break;
  1352. case DW_CFA_offset0:
  1353. case DW_CFA_offset1:
  1354. case DW_CFA_offset2:
  1355. case DW_CFA_offset3:
  1356. case DW_CFA_offset4:
  1357. case DW_CFA_offset5:
  1358. case DW_CFA_offset6:
  1359. case DW_CFA_offset7:
  1360. case DW_CFA_offset8:
  1361. {
  1362. int regNum = opCode - DW_CFA_offset0;
  1363. BF_ASSERT(regNum < CPURegisters::kNumIntRegs);
  1364. int offset = (int)DecodeULEB128(data) * dwFrameDescriptor->mCommonFrameDescriptor->mDataAlignmentFactor;
  1365. auto registerRuleData = &state->mRegisterRuleDataArray[regNum];
  1366. registerRuleData->mRegisterRule = DW_CFA_offset;
  1367. registerRuleData->mParamOffset = offset;
  1368. //int registerSize = 4;//TODO
  1369. //gDebugger->ReadMemory(state_mCFA + offset, registerSize, &registers->mIntRegsArray[regNum]);
  1370. }
  1371. break;
  1372. case DW_CFA_def_cfa_register:
  1373. {
  1374. int regNum = (int)DecodeULEB128(data);
  1375. BF_ASSERT(regNum < CPURegisters::kNumIntRegs);
  1376. state->mCFA = registers->mIntRegsArray[regNum] + state->mCFAOffset;
  1377. }
  1378. break;
  1379. case DW_CFA_def_cfa_expression:
  1380. {
  1381. int blockLen = (int)DecodeULEB128(data);
  1382. DbgAddrType addrType;
  1383. state->mCFA = dwFrameDescriptor->mCommonFrameDescriptor->mDbgModule->ExecuteOps(NULL, data, blockLen , NULL, registers, &addrType, true, &state->mCFA);
  1384. }
  1385. break;
  1386. case DW_CFA_expression:
  1387. {
  1388. int regNum = (int)DecodeULEB128(data);
  1389. BF_ASSERT(regNum < CPURegisters::kNumIntRegs);
  1390. int blockLen = (int)DecodeULEB128(data);
  1391. auto registerRuleData = &state->mRegisterRuleDataArray[regNum];
  1392. registerRuleData->mRegisterRule = DW_CFA_expression;
  1393. registerRuleData->mParamOffset = blockLen;
  1394. registerRuleData->mParamData = data;
  1395. data += blockLen;
  1396. }
  1397. break;
  1398. case DW_CFA_remember_state:
  1399. {
  1400. auto nextState = new State();
  1401. *nextState = *state;
  1402. nextState->mPrevState = state;
  1403. state = nextState;
  1404. }
  1405. break;
  1406. case DW_CFA_restore_state:
  1407. {
  1408. auto prevState = state->mPrevState;
  1409. BF_ASSERT(prevState != NULL);
  1410. delete state;
  1411. state = prevState;
  1412. }
  1413. break;
  1414. case DW_CFA_restore_extended:
  1415. {
  1416. int regNum = (int)DecodeULEB128(data);
  1417. state->mRegisterRuleDataArray[regNum] = initialState.mRegisterRuleDataArray[regNum];
  1418. }
  1419. break;
  1420. default:
  1421. BF_FATAL("Unknown DW_CFA");
  1422. break;
  1423. }
  1424. }
  1425. }
  1426. }
  1427. for (int registerNum = 0; registerNum < CPURegisters::kNumIntRegs; registerNum++)
  1428. {
  1429. auto registerRuleData = &state->mRegisterRuleDataArray[registerNum];
  1430. switch (registerRuleData->mRegisterRule)
  1431. {
  1432. case DW_CFA_offset:
  1433. {
  1434. if (outReturnAddressLoc != 0)
  1435. *outReturnAddressLoc = state->mCFA + registerRuleData->mParamOffset;
  1436. int registerSize = sizeof(addr_target);
  1437. gDebugger->ReadMemory(state->mCFA + registerRuleData->mParamOffset, registerSize, &registers->mIntRegsArray[registerNum]);
  1438. }
  1439. break;
  1440. case DW_CFA_val_offset:
  1441. registers->mIntRegsArray[registerNum] = state->mCFA + registerRuleData->mParamOffset;
  1442. break;
  1443. case DW_CFA_remember_state:
  1444. case DW_CFA_undefined:
  1445. break;
  1446. case DW_CFA_expression:
  1447. {
  1448. DbgAddrType addrType;
  1449. registers->mIntRegsArray[registerNum] = dwFrameDescriptor->mCommonFrameDescriptor->mDbgModule->ExecuteOps(NULL, registerRuleData->mParamData, registerRuleData->mParamOffset, NULL, registers, &addrType, true, &state->mCFA);
  1450. }
  1451. break;
  1452. default:
  1453. BF_FATAL("Unknown DW_CFA");
  1454. break;
  1455. }
  1456. }
  1457. while (state->mPrevState != NULL)
  1458. {
  1459. auto prev = state->mPrevState;
  1460. delete state;
  1461. state = prev;
  1462. }
  1463. return true;
  1464. }
  1465. bool DebugTarget::RollBackStackFrame_COFFFrameDescriptor(CPURegisters* registers, addr_target* outReturnAddressLoc, bool isStackStart)
  1466. {
  1467. #ifdef BF_DBG_32
  1468. addr_target pcAddress = (addr_target)registers->GetPC();
  1469. if (mCOFFFrameDescriptorMap.empty())
  1470. return false;
  1471. auto stackFrameItr = mCOFFFrameDescriptorMap.upper_bound(pcAddress);
  1472. if (stackFrameItr == mCOFFFrameDescriptorMap.begin())
  1473. return false;
  1474. stackFrameItr--;
  1475. auto frameEntry = &stackFrameItr->second;
  1476. addr_target startAddress = stackFrameItr->first;
  1477. if (pcAddress > startAddress + frameEntry->mFrameDescriptor->mCodeSize)
  1478. return false;
  1479. struct _StackEntry
  1480. {
  1481. COFFFrameProgram::Command mCmd;
  1482. addr_target mValue;
  1483. };
  1484. //SizedArray<_StackEntry, 8> stack;
  1485. int stackPos = 0;
  1486. COFFFrameProgram::Command stackCmds[8];
  1487. addr_target stackValues[8];
  1488. addr_target temps[4];
  1489. auto _GetValue = [&](int stackPos)
  1490. {
  1491. addr_target val = 0;
  1492. switch (stackCmds[stackPos])
  1493. {
  1494. case COFFFrameProgram::Command_EIP:
  1495. return (addr_target)registers->mIntRegs.eip;
  1496. case COFFFrameProgram::Command_ESP:
  1497. return (addr_target)registers->mIntRegs.esp;
  1498. case COFFFrameProgram::Command_EBP:
  1499. return (addr_target)registers->mIntRegs.ebp;
  1500. case COFFFrameProgram::Command_EAX:
  1501. return (addr_target)registers->mIntRegs.eax;
  1502. case COFFFrameProgram::Command_EBX:
  1503. return (addr_target)registers->mIntRegs.ebx;
  1504. case COFFFrameProgram::Command_ECX:
  1505. return (addr_target)registers->mIntRegs.ecx;
  1506. case COFFFrameProgram::Command_EDX:
  1507. return (addr_target)registers->mIntRegs.edx;
  1508. case COFFFrameProgram::Command_ESI:
  1509. return (addr_target)registers->mIntRegs.esi;
  1510. case COFFFrameProgram::Command_EDI:
  1511. return (addr_target)registers->mIntRegs.edi;
  1512. case COFFFrameProgram::Command_T0:
  1513. return (addr_target)temps[0];
  1514. case COFFFrameProgram::Command_T1:
  1515. return (addr_target)temps[1];
  1516. case COFFFrameProgram::Command_T2:
  1517. return (addr_target)temps[2];
  1518. case COFFFrameProgram::Command_T3:
  1519. return (addr_target)temps[3];
  1520. case COFFFrameProgram::Command_RASearch:
  1521. {
  1522. addr_target raSearch = (addr_target)(registers->GetSP() + frameEntry->mFrameDescriptor->mLocalSize + frameEntry->mFrameDescriptor->mSavedRegsSize);
  1523. // If we are directly on a "sub esp, <X>", this can occur when stepping out of a function, where the caller needs to adjust the stack after the call.
  1524. // There is generally not a unique frame descriptor to handle this condition, so we need to manually handle it here
  1525. if ((isStackStart) && (pcAddress != startAddress))
  1526. {
  1527. uint8 ops[2];
  1528. if (ReadOrigImageData(pcAddress, ops, 2) != DbgMemoryFlags_None)
  1529. {
  1530. if ((ops[0] == 0x83) && (ops[1] == 0xEC))
  1531. {
  1532. // SUB ESP, <UINT8>
  1533. uint8 rhs = 0;
  1534. ReadOrigImageData(pcAddress + 2, &rhs, 1);
  1535. raSearch -= rhs;
  1536. }
  1537. else if ((ops[0] == 0x81) && (ops[1] == 0xEC))
  1538. {
  1539. // SUB ESP, <UINT32>
  1540. uint32 rhs = 0;
  1541. ReadOrigImageData(pcAddress + 2, (uint8*)&rhs, 4);
  1542. raSearch -= rhs;
  1543. }
  1544. }
  1545. }
  1546. return raSearch;
  1547. }
  1548. case COFFFrameProgram::Command_Value:
  1549. return stackValues[stackPos];
  1550. }
  1551. return val;
  1552. };
  1553. COFFFrameProgram::Command* cmdPtr = frameEntry->mProgram.mCommands;
  1554. while (true)
  1555. {
  1556. COFFFrameProgram::Command cmd = *(cmdPtr++);
  1557. if (cmd == COFFFrameProgram::Command_None)
  1558. break;
  1559. switch (cmd)
  1560. {
  1561. case COFFFrameProgram::Command_EIP:
  1562. case COFFFrameProgram::Command_ESP:
  1563. case COFFFrameProgram::Command_EBP:
  1564. case COFFFrameProgram::Command_EAX:
  1565. case COFFFrameProgram::Command_EBX:
  1566. case COFFFrameProgram::Command_ECX:
  1567. case COFFFrameProgram::Command_EDX:
  1568. case COFFFrameProgram::Command_ESI:
  1569. case COFFFrameProgram::Command_EDI:
  1570. case COFFFrameProgram::Command_T0:
  1571. case COFFFrameProgram::Command_T1:
  1572. case COFFFrameProgram::Command_RASearch:
  1573. BF_ASSERT(stackPos < 8);
  1574. stackCmds[stackPos++] = cmd;
  1575. break;
  1576. case COFFFrameProgram::Command_Add:
  1577. {
  1578. BF_ASSERT(stackPos >= 2);
  1579. addr_target lhs = _GetValue(stackPos - 2);
  1580. addr_target rhs = _GetValue(stackPos - 1);
  1581. stackPos -= 2;
  1582. stackValues[stackPos] = lhs + rhs;
  1583. stackCmds[stackPos++] = COFFFrameProgram::Command_Value;
  1584. }
  1585. break;
  1586. case COFFFrameProgram::Command_Subtract:
  1587. {
  1588. BF_ASSERT(stackPos >= 2);
  1589. addr_target lhs = _GetValue(stackPos - 2);
  1590. addr_target rhs = _GetValue(stackPos - 1);
  1591. stackPos -= 2;
  1592. stackValues[stackPos] = lhs - rhs;
  1593. stackCmds[stackPos++] = COFFFrameProgram::Command_Value;
  1594. }
  1595. break;
  1596. case COFFFrameProgram::Command_Align:
  1597. {
  1598. BF_ASSERT(stackPos >= 2);
  1599. addr_target lhs = _GetValue(stackPos - 2);
  1600. addr_target rhs = _GetValue(stackPos - 1);
  1601. stackPos -= 2;
  1602. stackValues[stackPos] = BF_ALIGN(lhs, rhs);
  1603. stackCmds[stackPos++] = COFFFrameProgram::Command_Value;
  1604. }
  1605. break;
  1606. case COFFFrameProgram::Command_Set:
  1607. {
  1608. BF_ASSERT(stackPos >= 2);
  1609. addr_target rhs = _GetValue(stackPos - 1);
  1610. switch (stackCmds[stackPos - 2])
  1611. {
  1612. case COFFFrameProgram::Command_EIP:
  1613. registers->mIntRegs.eip = rhs;
  1614. break;
  1615. case COFFFrameProgram::Command_ESP:
  1616. registers->mIntRegs.esp = rhs;
  1617. break;
  1618. case COFFFrameProgram::Command_EBP:
  1619. registers->mIntRegs.ebp = rhs;
  1620. break;
  1621. case COFFFrameProgram::Command_EAX:
  1622. registers->mIntRegs.eax = rhs;
  1623. break;
  1624. case COFFFrameProgram::Command_EBX:
  1625. registers->mIntRegs.ebx = rhs;
  1626. break;
  1627. case COFFFrameProgram::Command_ECX:
  1628. registers->mIntRegs.ecx = rhs;
  1629. break;
  1630. case COFFFrameProgram::Command_EDX:
  1631. registers->mIntRegs.edx = rhs;
  1632. break;
  1633. case COFFFrameProgram::Command_ESI:
  1634. registers->mIntRegs.esi = rhs;
  1635. break;
  1636. case COFFFrameProgram::Command_EDI:
  1637. registers->mIntRegs.edi = rhs;
  1638. break;
  1639. case COFFFrameProgram::Command_T0:
  1640. temps[0] = rhs;
  1641. break;
  1642. case COFFFrameProgram::Command_T1:
  1643. temps[1] = rhs;
  1644. break;
  1645. case COFFFrameProgram::Command_T2:
  1646. temps[2] = rhs;
  1647. break;
  1648. case COFFFrameProgram::Command_T3:
  1649. temps[3] = rhs;
  1650. break;
  1651. }
  1652. stackPos -= 2;
  1653. }
  1654. break;
  1655. case COFFFrameProgram::Command_Deref:
  1656. {
  1657. BF_ASSERT(stackPos >= 1);
  1658. addr_target addr = _GetValue(stackPos - 1);
  1659. stackPos--;
  1660. stackValues[stackPos] = mDebugger->ReadMemory<addr_target>(addr);
  1661. stackCmds[stackPos++] = COFFFrameProgram::Command_Value;
  1662. }
  1663. break;
  1664. case COFFFrameProgram::Command_Value:
  1665. {
  1666. addr_target val = *(addr_target*)cmdPtr;
  1667. cmdPtr += 4;
  1668. stackValues[stackPos] = val;
  1669. stackCmds[stackPos++] = COFFFrameProgram::Command_Value;
  1670. }
  1671. break;
  1672. case COFFFrameProgram::Command_Value8:
  1673. {
  1674. addr_target val = (uint8)*(cmdPtr++);
  1675. stackValues[stackPos] = val;
  1676. stackCmds[stackPos++] = COFFFrameProgram::Command_Value;
  1677. }
  1678. break;
  1679. }
  1680. }
  1681. return true;
  1682. #endif
  1683. return false;
  1684. }
  1685. bool DebugTarget::RollBackStackFrame(CPURegisters* registers, addr_target* outReturnAddressLoc, bool isStackStart)
  1686. {
  1687. if (outReturnAddressLoc != NULL)
  1688. *outReturnAddressLoc = 0;
  1689. CPUInst inst;
  1690. if (DecodeInstruction(registers->GetPC(), &inst))
  1691. {
  1692. if (inst.IsReturn())
  1693. {
  1694. // If we are literally just a return then often the frame descriptor is wrong,
  1695. // but we know this is ACTUALLY just a simple rollback
  1696. int regSize = sizeof(addr_target);
  1697. addr_target* regPC = registers->GetPCRegisterRef();
  1698. addr_target* regSP = registers->GetSPRegisterRef();
  1699. addr_target newPC = 0;
  1700. gDebugger->ReadMemory(*regSP, sizeof(addr_target), &newPC);
  1701. *regSP += regSize;
  1702. *regPC = newPC;
  1703. return true;
  1704. }
  1705. }
  1706. #ifdef BF_DBG_32
  1707. if (RollBackStackFrame_DwFrameDescriptor(registers, outReturnAddressLoc))
  1708. return true;
  1709. if (RollBackStackFrame_COFFFrameDescriptor(registers, outReturnAddressLoc, isStackStart))
  1710. return true;
  1711. auto pc = registers->GetPC();
  1712. DbgSubprogram* dbgSubprogram = FindSubProgram(pc);
  1713. if (dbgSubprogram != NULL)
  1714. {
  1715. auto dbgModule = dbgSubprogram->mCompileUnit->mDbgModule;
  1716. if ((dbgModule != NULL) && (!dbgModule->mParsedFrameDescriptors))
  1717. {
  1718. dbgModule->ParseFrameDescriptors();
  1719. if (RollBackStackFrame_COFFFrameDescriptor(registers, outReturnAddressLoc, isStackStart))
  1720. return true;
  1721. }
  1722. }
  1723. #endif
  1724. // Fall through after this, we need to process a 'return'
  1725. bool alreadyRolledBackPC = false;
  1726. bool success = RollBackStackFrame_ExceptionDirectory(registers, outReturnAddressLoc, alreadyRolledBackPC);
  1727. if (!success)
  1728. {
  1729. if (mDebugger->IsMiniDumpDebugger())
  1730. {
  1731. return false;
  1732. }
  1733. }
  1734. if (alreadyRolledBackPC)
  1735. return true;
  1736. #ifdef BF_DBG_32
  1737. // Try rollback assuming a frame pointer
  1738. addr_target newPC = 0;
  1739. addr_target stackFrame = registers->GetBP();
  1740. int regSize = sizeof(addr_target);
  1741. addr_target* regPC = registers->GetPCRegisterRef();
  1742. addr_target* regSP = registers->GetSPRegisterRef();
  1743. addr_target* regBP = registers->GetBPRegisterRef();
  1744. // Using stack frame
  1745. *regSP = *regBP;
  1746. //*regBP = gDebugger->ReadMemory<addr_target>(*regSP);
  1747. gDebugger->ReadMemory(*regSP, sizeof(addr_target), regBP);
  1748. *regSP += regSize;
  1749. //newPC = gDebugger->ReadMemory<addr_target>(*regSP);
  1750. gDebugger->ReadMemory(*regSP, sizeof(addr_target), &newPC);
  1751. *regSP += regSize;
  1752. *regPC = newPC;
  1753. #else
  1754. // Do a 'leaf' rollback - assume no frame pointer
  1755. addr_target newPC = 0;
  1756. addr_target stackFrame = registers->GetBP();
  1757. int regSize = sizeof(addr_target);
  1758. addr_target* regPC = registers->GetPCRegisterRef();
  1759. addr_target* regSP = registers->GetSPRegisterRef();
  1760. if (!gDebugger->ReadMemory(*regSP, sizeof(addr_target), &newPC))
  1761. return false;
  1762. *regSP += regSize;
  1763. *regPC = newPC;
  1764. #endif
  1765. /*MEMORY_BASIC_INFORMATION memInfo;
  1766. if (VirtualQueryEx(mProcessInfo.hProcess, (void*)(intptr)(*regPC), &memInfo, sizeof(memInfo)) == 0)
  1767. return false;
  1768. if ((memInfo.Protect != PAGE_EXECUTE) && (memInfo.Protect != PAGE_EXECUTE_READ) &&
  1769. (memInfo.Protect != PAGE_EXECUTE_READWRITE) && (memInfo.Protect != PAGE_EXECUTE_WRITECOPY))
  1770. return false;*/
  1771. return true;
  1772. }
  1773. bool DebugTarget::PropogateRegisterUpCallStack(CPURegisters* callerRegisters, CPURegisters* calleeRegisters, void* regPtr, bool& wasSaved)
  1774. {
  1775. //TODO: Implement for X86
  1776. return PropogateRegisterUpCallStack_ExceptionDirectory(calleeRegisters->GetPC(), callerRegisters, calleeRegisters, regPtr, wasSaved);
  1777. }
  1778. int DebugTarget::GetFrameBaseRegister(DbgSubprogram* dwSubprogram)
  1779. {
  1780. if (dwSubprogram->mFrameBaseLen == 0)
  1781. return -1;
  1782. auto locData = dwSubprogram->mFrameBaseData;
  1783. if (locData != NULL)
  1784. {
  1785. uint8 opCode = GET_FROM(locData, uint8);
  1786. if ((opCode >= DW_OP_reg0) && (opCode <= DW_OP_reg8))
  1787. {
  1788. return opCode - DW_OP_reg0;
  1789. }
  1790. }
  1791. #ifdef BF_DBG_32
  1792. if (dwSubprogram->mLocalBaseReg == DbgSubprogram::LocalBaseRegKind_ESP)
  1793. return X86Reg_ESP;
  1794. else if (dwSubprogram->mLocalBaseReg == DbgSubprogram::LocalBaseRegKind_EBX)
  1795. return X86Reg_EBX;
  1796. return X86Reg_EBP;
  1797. #else
  1798. if (dwSubprogram->mLocalBaseReg == DbgSubprogram::LocalBaseRegKind_RSP)
  1799. return X64Reg_RSP;
  1800. else if (dwSubprogram->mLocalBaseReg == DbgSubprogram::LocalBaseRegKind_R13)
  1801. return X64Reg_R13;
  1802. return X64Reg_RBP;
  1803. #endif
  1804. return -1;
  1805. }
  1806. bool DebugTarget::GetVariableIndexRegisterAndOffset(DbgVariable* dwVariable, int* outRegister, int* outOffset)
  1807. {
  1808. if (dwVariable->mLocationLen == 0)
  1809. return false;
  1810. auto locData = dwVariable->mLocationData;
  1811. uint8 opCode = GET_FROM(locData, uint8);
  1812. if (opCode == DW_OP_fbreg)
  1813. {
  1814. *outRegister = -1;
  1815. int64 offset = DecodeSLEB128(locData);
  1816. *outOffset = offset;
  1817. return true;
  1818. }
  1819. else if ((opCode >= DW_OP_breg0) && (opCode <= DW_OP_breg8))
  1820. {
  1821. *outRegister = opCode - DW_OP_breg0;
  1822. *outOffset = DecodeSLEB128(locData);
  1823. return true;
  1824. }
  1825. return false;
  1826. }
  1827. //int64 BfDebuggerReadMemory(int64 addr);
  1828. addr_target DebugTarget::GetStaticAddress(DbgVariable* dwVariable)
  1829. {
  1830. DbgAddrType addrType;
  1831. return dwVariable->mCompileUnit->mDbgModule->EvaluateLocation(NULL, dwVariable->mLocationData, dwVariable->mLocationLen, NULL, &addrType);
  1832. }
  1833. bool DebugTarget::GetValueByNameInBlock_Helper(DbgSubprogram* dwSubprogram, DbgBlock* dwBlock, String& name, WdStackFrame* stackFrame, intptr* outAddr, DbgType** outType, DbgAddrType* outAddrType)
  1834. {
  1835. // Checks for previous version of a local name by stripping off the '@' each time we find a match, until we don't have any @'s left
  1836. auto _CheckName = [&](const char* localName)
  1837. {
  1838. const char* namePtr = name.c_str();
  1839. if (*namePtr != '@')
  1840. return;
  1841. while (*namePtr == '@')
  1842. namePtr++;
  1843. if (strcmp(localName, namePtr) == 0)
  1844. {
  1845. name.Remove(0, 1);
  1846. }
  1847. };
  1848. SizedArray<DbgVariable*, 32> checkVars;
  1849. for (auto variable : dwBlock->mVariables)
  1850. {
  1851. checkVars.push_back(variable);
  1852. }
  1853. auto _FixParam = [&](DbgVariable* variable)
  1854. {
  1855. if (dwSubprogram->GetLanguage() != DbgLanguage_Beef)
  1856. {
  1857. if ((*outAddrType == DbgAddrType_Target) /*&& (variable->mIsParam)*/ && (dwSubprogram->mCompileUnit->mDbgModule->mDbgFlavor == DbgFlavor_MS))
  1858. {
  1859. auto dbgType = *outType;
  1860. int size = dbgType->GetByteCount();
  1861. if (dbgType->IsTypedPrimitive())
  1862. {
  1863. // Already correct
  1864. }
  1865. else if ((dbgType->IsCompositeType()) && (variable->mIsParam))
  1866. {
  1867. int size = (*outType)->mSize;
  1868. if ((size != 1) && (size != 2) && (size != 4) && (size != sizeof(intptr_target)))
  1869. {
  1870. auto actualAddr = mDebugger->ReadMemory<intptr_target>(*outAddr);
  1871. *outAddr = actualAddr;
  1872. }
  1873. }
  1874. }
  1875. }
  1876. if (variable->mSigNoPointer)
  1877. {
  1878. if (*outAddrType == DbgAddrType_Target)
  1879. *outAddrType = DbgAddrType_TargetDeref;
  1880. }
  1881. if ((variable->mIsParam) && (dwSubprogram->GetLanguage() == DbgLanguage_Beef))
  1882. {
  1883. if ((!(*outType)->IsRef()) && (!(*outType)->IsConst()))
  1884. *outType = dwSubprogram->mCompileUnit->mDbgModule->GetConstType(*outType);
  1885. }
  1886. };
  1887. int nameLen = (int)name.length();
  1888. //for (auto variable : dwBlock->mVariables)
  1889. for (int varIdx = (int)checkVars.size() - 1; varIdx >= 0; varIdx--)
  1890. {
  1891. auto variable = checkVars[varIdx];
  1892. // if (variable->mDeclFileIdx == 0)
  1893. // continue;
  1894. if (variable->mRangeStart != 0)
  1895. {
  1896. auto curPC = stackFrame->GetSourcePC();
  1897. if ((curPC < variable->mRangeStart) || (curPC >= variable->mRangeStart + variable->mRangeLen))
  1898. continue;
  1899. }
  1900. if (mCapturedNamesPtr != NULL)
  1901. {
  1902. mCapturedNamesPtr->push_back(variable->mName);
  1903. if (mCapturedTypesPtr != NULL)
  1904. mCapturedTypesPtr->push_back(variable->mType);
  1905. }
  1906. else if ((strncmp(name.c_str(), variable->mName, nameLen) == 0))
  1907. {
  1908. if ((variable->mName[nameLen] == '$') && (variable->mName[nameLen + 1] == 'a')) // Alias
  1909. {
  1910. const char* aliasName = variable->mName + nameLen + 3;
  1911. return GetValueByName(dwSubprogram, aliasName, stackFrame, outAddr, outType, outAddrType);
  1912. }
  1913. else if (variable->mName[nameLen] != 0)
  1914. continue;
  1915. *outType = variable->mType;
  1916. if (((variable->mType != NULL) && (variable->mType->mTypeCode == DbgType_Const)) || (variable->mIsConst))
  1917. {
  1918. if ((variable->mLocationData == NULL) || (variable->mIsConst))
  1919. {
  1920. if (variable->mType->IsCompositeType())
  1921. {
  1922. *outAddr = (intptr)variable;
  1923. *outAddrType = DbgAddrType_LocalSplat;
  1924. return true;
  1925. }
  1926. *outAddrType = DbgAddrType_Local;
  1927. if (variable->mIsConst)
  1928. *outAddr = (uint64)&variable->mConstValue;
  1929. else
  1930. *outAddr = NULL; // Optimized out?
  1931. return true;
  1932. }
  1933. else
  1934. {
  1935. // Strip off const part, for proper evaluation of value for receiver
  1936. //TODO: Why did we do this? This screwed up our 'abuse' of the const
  1937. // for 'let' statements.
  1938. // *outType = variable->mType->mTypeParam;
  1939. }
  1940. }
  1941. if (variable->mLocationData == NULL)
  1942. return false;
  1943. *outAddr = variable->mCompileUnit->mDbgModule->EvaluateLocation(dwSubprogram, variable->mLocationData, variable->mLocationLen, stackFrame, outAddrType);
  1944. _FixParam(variable);
  1945. return true;
  1946. }
  1947. else
  1948. _CheckName(variable->mName);
  1949. }
  1950. if (dwBlock == &dwSubprogram->mBlock)
  1951. {
  1952. for (auto variable : dwSubprogram->mParams)
  1953. {
  1954. /*if (variable->mDeclFileIdx == 0)
  1955. continue;*/
  1956. if (variable->mName == NULL)
  1957. continue;
  1958. if (mCapturedNamesPtr != NULL)
  1959. {
  1960. mCapturedNamesPtr->push_back(variable->mName);
  1961. if (mCapturedTypesPtr != NULL)
  1962. mCapturedTypesPtr->push_back(variable->mType);
  1963. }
  1964. else if (strcmp(name.c_str(), variable->mName) == 0)
  1965. {
  1966. *outType = variable->mType;
  1967. if (variable->mLocationData == NULL)
  1968. {
  1969. if (variable->mIsConst)
  1970. {
  1971. if (variable->mType->IsCompositeType())
  1972. {
  1973. *outType = dwSubprogram->mCompileUnit->mDbgModule->GetConstType(*outType);
  1974. *outAddr = (intptr)variable;
  1975. *outAddrType = DbgAddrType_LocalSplat;
  1976. return true;
  1977. }
  1978. }
  1979. return false;
  1980. }
  1981. *outAddr = variable->mCompileUnit->mDbgModule->EvaluateLocation(dwSubprogram, variable->mLocationData, variable->mLocationLen, stackFrame, outAddrType);
  1982. _FixParam(variable);
  1983. return true;
  1984. }
  1985. else
  1986. _CheckName(variable->mName);
  1987. }
  1988. }
  1989. return false;
  1990. }
  1991. bool DebugTarget::GetValueByNameInBlock(DbgSubprogram* dwSubprogram, DbgBlock* dwBlock, String& name, WdStackFrame* stackFrame, intptr* outAddr, DbgType** outType, DbgAddrType* outAddrType)
  1992. {
  1993. addr_target pc = stackFrame->GetSourcePC();
  1994. if (dwSubprogram != NULL)
  1995. {
  1996. auto dbgModule = dwSubprogram->mCompileUnit->mDbgModule;
  1997. if (dwBlock->mLowPC == -1)
  1998. {
  1999. //Debug ranges
  2000. addr_target* rangeData = (addr_target*)(dbgModule->mDebugRangesData + dwBlock->mHighPC);
  2001. while (true)
  2002. {
  2003. addr_target lowPC = *(rangeData++);
  2004. if (lowPC == 0)
  2005. return false;
  2006. addr_target highPC = *(rangeData++);
  2007. // Matches?
  2008. if ((pc >= lowPC) && (pc < highPC))
  2009. break;
  2010. }
  2011. }
  2012. else if ((pc < dwBlock->mLowPC) || (pc >= dwBlock->mHighPC))
  2013. return false;
  2014. }
  2015. for (auto subBlock : dwBlock->mSubBlocks)
  2016. {
  2017. if (GetValueByNameInBlock(dwSubprogram, subBlock, name, stackFrame, outAddr, outType, outAddrType))
  2018. return true;
  2019. }
  2020. if (GetValueByNameInBlock_Helper(dwSubprogram, dwBlock, name, stackFrame, outAddr, outType, outAddrType))
  2021. return true;
  2022. return false;
  2023. }
  2024. const DbgMemoryFlags DebugTarget::ReadOrigImageData(addr_target address, uint8* data, int size)
  2025. {
  2026. for (auto dwarf : mDbgModules)
  2027. {
  2028. if ((address >= dwarf->mImageBase) && (address < dwarf->mImageBase + dwarf->mImageSize) && (dwarf->mOrigImageData != NULL))
  2029. {
  2030. return dwarf->mOrigImageData->Read(address, data, size);
  2031. }
  2032. //return dbgModule->mOrigImageData + (address - dbgModule->mImageBase);
  2033. }
  2034. return DbgMemoryFlags_None;
  2035. }
  2036. bool DebugTarget::DecodeInstruction(addr_target address, CPUInst* inst)
  2037. {
  2038. for (auto dwarf : mDbgModules)
  2039. {
  2040. if ((address >= dwarf->mImageBase) && (address < dwarf->mImageBase + dwarf->mImageSize) && (dwarf->mOrigImageData != NULL))
  2041. {
  2042. return mDebugger->mCPU->Decode(address, dwarf->mOrigImageData, inst);
  2043. }
  2044. }
  2045. return false;
  2046. }
  2047. bool DebugTarget::IsObjectAccessBreak(addr_target address, CPURegisters* registers, intptr_target* objAddr)
  2048. {
  2049. for (auto dwarf : mDbgModules)
  2050. {
  2051. if ((address >= dwarf->mImageBase) && (address < dwarf->mImageBase + dwarf->mImageSize) && (dwarf->mOrigImageData != NULL))
  2052. {
  2053. bool result = mDebugger->mCPU->IsObjectAccessBreak(address, dwarf->mOrigImageData, registers->mIntRegsArray, objAddr);
  2054. return result;
  2055. }
  2056. }
  2057. return false;
  2058. }
  2059. DbgModule* DebugTarget::FindDbgModuleForAddress(addr_target address)
  2060. {
  2061. for (auto dwarf : mDbgModules)
  2062. {
  2063. if ((address >= dwarf->mImageBase) && (address < dwarf->mImageBase + dwarf->mImageSize))
  2064. return dwarf;
  2065. }
  2066. return NULL;
  2067. }
  2068. DbgModule* DebugTarget::GetMainDbgModule()
  2069. {
  2070. return mTargetBinary;
  2071. }
  2072. #ifdef BF_DBG_32
  2073. template <typename T>
  2074. void ReportRadixMap(MemReporter* memReporter, RadixMap32<T>& radixMap)
  2075. {
  2076. memReporter->Add(sizeof(void*) * RadixMap32<T>::ROOT_LENGTH);
  2077. for (int rootIdx = 0; rootIdx < RadixMap32<T>::ROOT_LENGTH; rootIdx++)
  2078. {
  2079. auto root = radixMap.mRoot[rootIdx];
  2080. if (root != NULL)
  2081. {
  2082. memReporter->Add(sizeof(RadixMap32<T>::Leaf));
  2083. }
  2084. }
  2085. }
  2086. #else
  2087. template <typename T>
  2088. void ReportRadixMap(MemReporter* memReporter, RadixMap64<T>& radixMap)
  2089. {
  2090. memReporter->Add(sizeof(void*) * RadixMap64<T>::ROOT_LENGTH);
  2091. for (int rootIdx = 0; rootIdx < RadixMap64<T>::ROOT_LENGTH; rootIdx++)
  2092. {
  2093. auto mid = radixMap.mRoot[rootIdx];
  2094. if (mid != NULL)
  2095. {
  2096. memReporter->Add(sizeof(RadixMap64<T>::Mid));
  2097. for (int midIdx = 0; midIdx < RadixMap64<T>::MID_LENGTH; midIdx++)
  2098. {
  2099. auto leaf = mid->mLeafs[midIdx];
  2100. if (leaf != NULL)
  2101. {
  2102. memReporter->Add(sizeof(RadixMap64<T>::Leaf));
  2103. }
  2104. }
  2105. }
  2106. }
  2107. }
  2108. #endif
  2109. void DebugTarget::ReportMemory(MemReporter* memReporter)
  2110. {
  2111. memReporter->BeginSection("SymbolMap");
  2112. ReportRadixMap(memReporter, mSymbolMap);
  2113. memReporter->EndSection();
  2114. memReporter->BeginSection("SubprogramMap");
  2115. ReportRadixMap(memReporter, mSubprogramMap);
  2116. memReporter->EndSection();
  2117. memReporter->BeginSection("ExceptionDirectoryMap");
  2118. ReportRadixMap(memReporter, mExceptionDirectoryMap);
  2119. memReporter->EndSection();
  2120. memReporter->BeginSection("ContribMap");
  2121. ReportRadixMap(memReporter, mContribMap);
  2122. memReporter->EndSection();
  2123. memReporter->BeginSection("CommonFrameDescriptors");
  2124. memReporter->AddVec(mCommonFrameDescriptors);
  2125. memReporter->EndSection();
  2126. for (auto dbgModule : mDbgModules)
  2127. {
  2128. memReporter->BeginSection("DbgModules");
  2129. dbgModule->ReportMemory(memReporter);
  2130. memReporter->EndSection();
  2131. }
  2132. }
  2133. template <typename T>
  2134. struct VectorRemoveCtx
  2135. {
  2136. T* mVec;
  2137. int mMatchStartIdx;
  2138. bool mFinished;
  2139. VectorRemoveCtx(T& vec)
  2140. {
  2141. mVec = &vec;
  2142. mMatchStartIdx = -1;
  2143. mFinished = false;
  2144. }
  2145. ~VectorRemoveCtx()
  2146. {
  2147. BF_ASSERT(mFinished);
  2148. }
  2149. void RemoveCond(int& idx, bool doRemove)
  2150. {
  2151. if (doRemove)
  2152. {
  2153. if (mMatchStartIdx == -1)
  2154. mMatchStartIdx = idx;
  2155. }
  2156. else
  2157. {
  2158. if (mMatchStartIdx != -1)
  2159. {
  2160. mVec->RemoveRange(mMatchStartIdx, idx - mMatchStartIdx);
  2161. idx = mMatchStartIdx;
  2162. mMatchStartIdx = -1;
  2163. }
  2164. }
  2165. }
  2166. void Finish()
  2167. {
  2168. if (mMatchStartIdx != -1)
  2169. mVec->RemoveRange(mMatchStartIdx, (int)mVec->size() - mMatchStartIdx);
  2170. mFinished = true;
  2171. }
  2172. };
  2173. void DebugTarget::RemoveTargetData()
  2174. {
  2175. BP_ZONE("DebugTarget::RemoveTargetData");
  2176. #ifdef _DEBUG
  2177. DbgModule* problemModule = NULL;
  2178. int checkIdx = 0;
  2179. for (DbgSymbol* headNode : mSymbolMap)
  2180. {
  2181. auto node = headNode;
  2182. while (node != NULL)
  2183. {
  2184. checkIdx++;
  2185. auto next = node->mNext;
  2186. if (node->mDbgModule->mDeleting)
  2187. {
  2188. problemModule = node->mDbgModule;
  2189. //OutputDebugStrF("Should have been removed by DbgModule::RemoveTargetData %@ %s\n", node->mAddress, node->mName);
  2190. BF_DBG_FATAL("Should have been removed by DbgModule::RemoveTargetData");
  2191. mSymbolMap.Remove(node);
  2192. }
  2193. node = next;
  2194. }
  2195. }
  2196. if (problemModule != NULL)
  2197. {
  2198. problemModule->RemoveTargetData();
  2199. }
  2200. for (DbgSubprogramMapEntry* headNode : mSubprogramMap)
  2201. {
  2202. auto node = headNode;
  2203. while (node != NULL)
  2204. {
  2205. auto next = node->mNext;
  2206. if (node->mEntry->mCompileUnit->mDbgModule->mDeleting)
  2207. {
  2208. //OutputDebugStrF("Should have been removed by DbgModule::RemoveTargetData %s\n", node->mEntry->mName);
  2209. BF_DBG_FATAL("Should have been removed by DbgModule::RemoveTargetData");
  2210. mSubprogramMap.Remove(node);
  2211. }
  2212. node = next;
  2213. }
  2214. }
  2215. for (DbgExceptionDirectoryEntry* exDirEntry : mExceptionDirectoryMap)
  2216. {
  2217. auto node = exDirEntry;
  2218. while (node != NULL)
  2219. {
  2220. auto next = node->mNext;
  2221. if (node->mDbgModule->mDeleting)
  2222. {
  2223. //BF_DBG_FATAL("Should have been removed by DbgModule::RemoveTargetData");
  2224. mExceptionDirectoryMap.Remove(node);
  2225. }
  2226. node = next;
  2227. }
  2228. }
  2229. #endif
  2230. VectorRemoveCtx<Array<DwCommonFrameDescriptor*>> cieRemoveCtx(mCommonFrameDescriptors);
  2231. for (int dieIdx = 0; dieIdx < (int)mCommonFrameDescriptors.size(); dieIdx++)
  2232. {
  2233. DwCommonFrameDescriptor* commonFrameDescriptor = mCommonFrameDescriptors[dieIdx];
  2234. cieRemoveCtx.RemoveCond(dieIdx, commonFrameDescriptor->mDbgModule->mDeleting);
  2235. }
  2236. cieRemoveCtx.Finish();
  2237. auto frameDescItr = mDwFrameDescriptorMap.begin();
  2238. while (frameDescItr != mDwFrameDescriptorMap.end())
  2239. {
  2240. DwFrameDescriptor* frameDesc = &frameDescItr->second;
  2241. if (frameDesc->mCommonFrameDescriptor->mDbgModule->mDeleting)
  2242. frameDescItr = mDwFrameDescriptorMap.erase(frameDescItr);
  2243. else
  2244. ++frameDescItr;
  2245. }
  2246. }