DebugManager.cpp 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699
  1. #include "DebugManager.h"
  2. #include "BeefySysLib/util/CritSect.h"
  3. #include "Compiler/BfSystem.h"
  4. #include "Compiler/BfParser.h"
  5. #include "Compiler/MemReporter.h"
  6. #include "Debugger.h"
  7. #include "DebugVisualizers.h"
  8. #include "RadixMap.h"
  9. #include "Compiler/BfDemangler.h"
  10. #include "llvm/Support/ErrorHandling.h"
  11. #include "BeefySysLib/util/BeefPerf.h"
  12. #include "NetManager.h"
  13. #ifdef BF_PLATFORM_WINDOWS
  14. #include "DbgMiniDump.h"
  15. #endif
  16. #include <iostream>
  17. #pragma warning(push)
  18. #pragma warning(disable:4141)
  19. #pragma warning(disable:4146)
  20. #pragma warning(disable:4291)
  21. #pragma warning(disable:4244)
  22. #pragma warning(disable:4267)
  23. #pragma warning(disable:4624)
  24. #pragma warning(disable:4800)
  25. #pragma warning(disable:4996)
  26. #include "llvm/IR/LLVMContext.h"
  27. #include "llvm/IRReader/IRReader.h"
  28. //#include "llvm/Bitcode/ReaderWriter.h"
  29. #pragma warning(pop)
  30. #ifdef BF_PLATFORM_WINDOWS
  31. #include <psapi.h>
  32. #include <shlobj.h>
  33. #endif
  34. #include "BeefySysLib/util/AllocDebug.h"
  35. #define ENABLE_DBG_32
  36. //#define BF_DBG_32
  37. //#include "WinDebugger.h"
  38. //#undef BF_DBG_32
  39. /*#define BF_DBG_64
  40. #include "WinDebugger.h"
  41. #undef BF_DBG_64*/
  42. int Beefy::sRadixMapCount = 0;
  43. int Beefy::sRootSize = 0;
  44. int Beefy::sMidSize = 0;
  45. int Beefy::sLeafSize = 0;
  46. USING_NS_BF;
  47. DebugManager* Beefy::gDebugManager = NULL;
  48. Debugger* Beefy::gDebugger = NULL;
  49. PerfManager* Beefy::gDbgPerfManager = NULL;
  50. int64 gBfAllocCount = 0;
  51. int64 gBfFreeCount = 0;
  52. static Dictionary<long, int> gBfAllocMap;
  53. static Dictionary<void*, long> gBfAllocAddrMap;
  54. //////////////////////////////////////////////////////////////////////////
  55. DebugManager::DebugManager()
  56. {
  57. gDbgPerfManager = new PerfManager();
  58. mDebugVisualizers = new DebugVisualizers();
  59. mStepFilterVersion = 0;
  60. mStepOverExternalFiles = false;
  61. mDebugger32 = NULL;
  62. mDebugger64 = NULL;
  63. mNetManager = new NetManager();
  64. mNetManager->mDebugManager = this;
  65. mSymSrvOptions.mCacheDir = "C:\\SymCache";
  66. mSymSrvOptions.mSymbolServers.Add("C:\\BeefSyms");
  67. mSymSrvOptions.mSymbolServers.Add("https://msdl.microsoft.com/download/symbols");
  68. mSymSrvOptions.mSymbolServers.Add("http://wintest.beefy2d.com/symbols/");
  69. mSymSrvOptions.mSymbolServers.Add("https://chromium-browser-symsrv.commondatastorage.googleapis.com");
  70. //TODO: Just for testing
  71. mSymSrvOptions.mSymbolServers.Add("http://127.0.0.1/symbols");
  72. SetSourceServerCacheDir();
  73. }
  74. DebugManager::~DebugManager()
  75. {
  76. delete mNetManager;
  77. delete mDebugger64;
  78. delete mDebugger32;
  79. /*for (auto stepFilter : mStepFilters)
  80. {
  81. }*/
  82. delete mDebugVisualizers;
  83. }
  84. void DebugManager::OutputMessage(const StringImpl& msg)
  85. {
  86. AutoCrit autoCrit(mCritSect);
  87. mOutMessages.push_back("msg " + msg);
  88. }
  89. void DebugManager::OutputRawMessage(const StringImpl& msg)
  90. {
  91. AutoCrit autoCrit(mCritSect);
  92. mOutMessages.push_back(msg);
  93. }
  94. void DebugManager::SetSourceServerCacheDir()
  95. {
  96. #ifdef BF_PLATFORM_WINDOWS
  97. AutoCrit autoCrit(mCritSect);
  98. WCHAR appDataPath[MAX_PATH] = { 0 };
  99. SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, appDataPath);
  100. mSymSrvOptions.mSourceServerCacheDir = UTF8Encode(appDataPath);
  101. mSymSrvOptions.mSourceServerCacheDir += "\\SourceServer";
  102. if (mSymSrvOptions.mFlags & BfSymSrvFlag_TempCache)
  103. {
  104. mSymSrvOptions.mSourceServerCacheDir += "\\temp";
  105. RecursiveDeleteDirectory(mSymSrvOptions.mSourceServerCacheDir);
  106. }
  107. #endif
  108. }
  109. //#define CAPTURE_ALLOC_BACKTRACE
  110. //#define CAPTURE_ALLOC_SOURCES
  111. #ifdef CAPTURE_ALLOC_BACKTRACE
  112. const int sNumAllocAddrs = 0x300000;
  113. const int sCaptureDepth = 14;
  114. const int sCaptureOffset = 4;
  115. static intptr gAllocAddrs[sNumAllocAddrs][sCaptureDepth];
  116. #endif
  117. #ifdef CAPTURE_ALLOC_SOURCES
  118. #include <Dbghelp.h>
  119. #pragma comment(lib, "dbghelp.lib")
  120. struct CaptureAllocLocation
  121. {
  122. public:
  123. char* mSymName;
  124. int mTotalSize;
  125. bool mIsEndpoint;
  126. };
  127. struct CaptureAllocEntry
  128. {
  129. public:
  130. CaptureAllocLocation* mLoc;
  131. int mAllocSize;
  132. };
  133. std::map<long, CaptureAllocEntry> gBfCaptureSourceAllocMap;
  134. //std::map<void*, CaptureAllocLocation> gBfCaptureAllocLocation;
  135. #define CAPTURE_ALLOC_POOL_SIZE 0x100000
  136. CaptureAllocLocation* gHashCaptureAllocSize[CAPTURE_ALLOC_POOL_SIZE] = { 0 };
  137. static void ReallocEntry(long oldRequest, long newRequest, int newSize)
  138. {
  139. auto itr = gBfCaptureSourceAllocMap.find(oldRequest);
  140. if (itr != gBfCaptureSourceAllocMap.end())
  141. {
  142. CaptureAllocEntry* entry = &itr->second;
  143. entry->mLoc->mTotalSize -= entry->mAllocSize;
  144. entry->mLoc->mTotalSize += newSize;
  145. entry->mAllocSize = newSize;
  146. gBfCaptureSourceAllocMap[newRequest] = *entry;
  147. gBfCaptureSourceAllocMap.erase(itr);
  148. }
  149. }
  150. static void RemoveAllocEntry(long lRequest)
  151. {
  152. auto itr = gBfCaptureSourceAllocMap.find(lRequest);
  153. if (itr != gBfCaptureSourceAllocMap.end())
  154. {
  155. CaptureAllocEntry* entry = &itr->second;
  156. entry->mLoc->mTotalSize -= entry->mAllocSize;
  157. gBfCaptureSourceAllocMap.erase(itr);
  158. }
  159. }
  160. //const LOC_HASHES
  161. #endif
  162. static int gBfNumAllocs = 0;
  163. #ifdef BF_PLATFORM_WINDOWS
  164. static bool gBgTrackingAllocs = false; ///// Leave false most of the time
  165. CritSect gBfCritSect;
  166. static bool gInsideAlloc = false;
  167. static int gLastReqId = 0;
  168. static int BfAllocHook(int nAllocType, void *pvData,
  169. size_t nSize, int nBlockUse, long lRequest,
  170. const unsigned char * szFileName, int nLine)
  171. {
  172. #ifdef CAPTURE_ALLOC_SOURCES
  173. if (gInsideAlloc)
  174. return TRUE;
  175. gInsideAlloc = true;
  176. intptr stackTrace[20];
  177. int traceCount = (int)RtlCaptureStackBackTrace(1, 20, (void**)&stackTrace, 0);
  178. /*intptr ebpVal;
  179. __asm
  180. {
  181. mov ebpVal, ebp
  182. }*/
  183. //intptr ebp = ebpVal;
  184. //intptr eip = 0;
  185. static HANDLE hProcess = 0;
  186. if (hProcess == NULL)
  187. {
  188. hProcess = GetCurrentProcess();
  189. BOOL worked = SymInitialize(hProcess, NULL, TRUE);
  190. }
  191. if (nAllocType == _HOOK_ALLOC)
  192. {
  193. for (int i = 0; i < traceCount; i++)
  194. {
  195. /*__try
  196. {
  197. ebp = *((intptr*)ebp + 0);
  198. if (ebp < 0x100000)
  199. break;
  200. eip = *((intptr*)ebp + 1);
  201. }
  202. __except (EXCEPTION_EXECUTE_HANDLER)
  203. {
  204. break;
  205. }*/
  206. intptr curAddr = stackTrace[i];
  207. const char* name = "?";
  208. int hashVal = (curAddr & 0x7FFFFFFF) % CAPTURE_ALLOC_POOL_SIZE;
  209. if (gHashCaptureAllocSize[hashVal] == NULL)
  210. {
  211. //static HPROCESS hProc = GEtProcessH
  212. char symData[4096];
  213. DWORD64 disp = 0;
  214. SYMBOL_INFO* symInfo = (SYMBOL_INFO*)&symData;
  215. memset(symInfo, 0, sizeof(SYMBOL_INFO));
  216. symInfo->SizeOfStruct = sizeof(SYMBOL_INFO);
  217. symInfo->MaxNameLen = sizeof(symData) - sizeof(SYMBOL_INFO);
  218. bool foundSym = false;
  219. if (SymFromAddr(hProcess, (DWORD64)curAddr, &disp, symInfo))
  220. {
  221. name = symInfo->Name;
  222. foundSym = true;
  223. }
  224. CaptureAllocLocation* captureAllocLoc = new CaptureAllocLocation();
  225. captureAllocLoc->mSymName = strdup(name);
  226. captureAllocLoc->mTotalSize = 0;
  227. captureAllocLoc->mIsEndpoint = (!foundSym) || (strncmp(name, "Beefy::", 7) == 0) || (strncmp(name, "llvm::", 6) == 0);
  228. if (strstr(name, "operator new") != NULL)
  229. captureAllocLoc->mIsEndpoint = false;
  230. if (strstr(name, "::allocateBuckets") != NULL)
  231. captureAllocLoc->mIsEndpoint = false;
  232. if (strstr(name, "::grow") != NULL)
  233. captureAllocLoc->mIsEndpoint = false;
  234. if (strstr(name, "::DenseMap") != NULL)
  235. captureAllocLoc->mIsEndpoint = false;
  236. /*if (strstr(name, "::Allocate") != NULL)
  237. captureAllocLoc->mIsEndpoint = false;*/
  238. if (strstr(name, "::Alloc") != NULL)
  239. captureAllocLoc->mIsEndpoint = false;
  240. /*if (strstr(name, "::AllocBytes") != NULL)
  241. captureAllocLoc->mIsEndpoint = false;
  242. if (strstr(name, "::AllocMemoryBlock") != NULL)
  243. captureAllocLoc->mIsEndpoint = false;*/
  244. if (strstr(name, "::GrowPool") != NULL)
  245. captureAllocLoc->mIsEndpoint = false;
  246. // Testing COnstantInt::get
  247. if (strstr(name, "::CreateConst") != NULL)
  248. captureAllocLoc->mIsEndpoint = false;
  249. if (strstr(name, "::get") != NULL)
  250. captureAllocLoc->mIsEndpoint = false;
  251. if ((captureAllocLoc->mIsEndpoint) && (foundSym))
  252. {
  253. }
  254. gHashCaptureAllocSize[hashVal] = captureAllocLoc;
  255. }
  256. CaptureAllocLocation* captureAllocLoc = gHashCaptureAllocSize[hashVal];
  257. if ((i < 19) && (!captureAllocLoc->mIsEndpoint))
  258. {
  259. continue;
  260. }
  261. captureAllocLoc->mTotalSize += (int)nSize;
  262. CaptureAllocEntry entry;
  263. entry.mAllocSize = (int)nSize;
  264. entry.mLoc = captureAllocLoc;
  265. gBfCaptureSourceAllocMap[lRequest] = entry;
  266. break;
  267. //if (i >= sCaptureOffset)
  268. //gAllocAddrs[lRequest][i - sCaptureOffset] = eip;
  269. }
  270. }
  271. else if (nAllocType == _HOOK_REALLOC)
  272. {
  273. long oldRequest = ((int*)pvData)[-2];
  274. ReallocEntry(oldRequest, lRequest, nSize);
  275. }
  276. else if (nAllocType == _HOOK_FREE)
  277. {
  278. lRequest = ((int*)pvData)[-2];
  279. RemoveAllocEntry(lRequest);
  280. }
  281. gInsideAlloc = false;
  282. #endif
  283. #ifdef CAPTURE_ALLOC_BACKTRACE
  284. if (lRequest < sNumAllocAddrs)
  285. {
  286. gAllocAddrs[lRequest][0] = 1;
  287. intptr ebpVal;
  288. __asm
  289. {
  290. mov ebpVal, ebp
  291. }
  292. intptr ebp = ebpVal;
  293. intptr eip = 0;
  294. for (int i = 0; i < sCaptureDepth + sCaptureOffset; i++)
  295. {
  296. __try
  297. {
  298. ebp = *((intptr*)ebp + 0);
  299. if (ebp < 0x100000)
  300. break;
  301. eip = *((intptr*)ebp + 1);
  302. }
  303. __except (EXCEPTION_EXECUTE_HANDLER)
  304. {
  305. break;
  306. }
  307. if (i >= sCaptureOffset)
  308. gAllocAddrs[lRequest][i - sCaptureOffset] = eip;
  309. }
  310. }
  311. #else
  312. if (!gBgTrackingAllocs)
  313. return TRUE;
  314. /*AutoCrit critSect(gBfCritSect);
  315. if (gLastReqId == lRequest)
  316. return TRUE;
  317. if (!gInsideAlloc)
  318. {
  319. gInsideAlloc = true;
  320. if (nAllocType == _HOOK_ALLOC)
  321. {
  322. gBfNumAllocs++;
  323. gBfAllocCount += nSize;
  324. gBfAllocMap[lRequest] = nSize;
  325. }
  326. if (nAllocType == _HOOK_FREE)
  327. {
  328. lRequest = ((int*)pvData)[-2];
  329. auto itr = gBfAllocMap.find(lRequest);
  330. if (itr != gBfAllocMap.end())
  331. {
  332. gBfFreeCount += itr->second;
  333. gBfAllocMap.erase(itr);
  334. }
  335. }
  336. gInsideAlloc = false;
  337. }
  338. gLastReqId = lRequest;
  339. if (szFileName == NULL)
  340. return TRUE; */
  341. /*char str[1024];
  342. sprintf(str, "Alloc: %d File: %s Line: %d\n", lRequest, szFileName, nLine);
  343. OutputDebugStringA(str);*/
  344. #endif
  345. return TRUE;
  346. }
  347. #endif //BF_PLATFORM_WINDOWS
  348. void BfReportMemory()
  349. {
  350. BfLogDbg("Used: %.2fM NumAllocs: %d Allocs: %.2fM\n", (gBfAllocCount - gBfFreeCount) / (1024.0 * 1024.0), gBfNumAllocs, gBfAllocCount / (1024.0 * 1024.0));
  351. }
  352. void BfFullReportMemory()
  353. {
  354. /*OutputDebugStrF("Testing OOB\n");
  355. char* str = new char[12];
  356. delete str;
  357. char c = str[1];*/
  358. if (gBfParserCache != NULL)
  359. {
  360. MemReporter memReporter;
  361. memReporter.BeginSection("ParserCache");
  362. gBfParserCache->ReportMemory(&memReporter);
  363. memReporter.EndSection();
  364. memReporter.Report();
  365. }
  366. OutputDebugStrF("Used: %.2fM NumAllocs: %d Allocs: %.2fM\n", (gBfAllocCount - gBfFreeCount) / (1024.0 * 1024.0), gBfNumAllocs, gBfAllocCount / (1024.0 * 1024.0));
  367. OutputDebugStrF("ChunkedDataBuffer allocated blocks: %d\n", ChunkedDataBuffer::sBlocksAllocated);
  368. if (gDebugManager != NULL)
  369. {
  370. MemReporter memReporter;
  371. if (gDebugManager->mDebugger32 != NULL)
  372. {
  373. memReporter.BeginSection("Debugger32");
  374. gDebugManager->mDebugger32->ReportMemory(&memReporter);
  375. memReporter.EndSection();
  376. }
  377. memReporter.BeginSection("Debugger64");
  378. gDebugManager->mDebugger64->ReportMemory(&memReporter);
  379. memReporter.EndSection();
  380. memReporter.Report();
  381. }
  382. BpDump();
  383. #ifdef CAPTURE_ALLOC_SOURCES
  384. int memTotal = 0;
  385. std::map<String, int> byNameMap;
  386. for (int i = 0; i < CAPTURE_ALLOC_POOL_SIZE; i++)
  387. {
  388. CaptureAllocLocation* allocLoc = gHashCaptureAllocSize[i];
  389. if ((allocLoc != NULL) && (allocLoc->mTotalSize > 0))
  390. {
  391. auto itr = byNameMap.insert(std::map<String, int>::value_type(allocLoc->mSymName, 0));
  392. itr.first->second += allocLoc->mTotalSize;
  393. memTotal += allocLoc->mTotalSize;
  394. }
  395. }
  396. std::multimap<int, String> bySizeMap;
  397. for (auto kv : byNameMap)
  398. {
  399. //OutputDebugStrF("%dk %s\n", (kv.second + 1023) / 1024, kv.first.c_str());
  400. bySizeMap.insert(std::multimap<int, String>::value_type(-kv.second, kv.first));
  401. }
  402. for (auto kv : bySizeMap)
  403. {
  404. OutputDebugStrF("%dk %s\n", (-kv.first + 1023) / 1024, kv.second.c_str());
  405. }
  406. OutputDebugStrF("Total %dk\n", memTotal / 1024);
  407. #endif
  408. }
  409. struct _CrtMemBlockHeader
  410. {
  411. _CrtMemBlockHeader* _block_header_next;
  412. _CrtMemBlockHeader* _block_header_prev;
  413. char const* _file_name;
  414. int _line_number;
  415. int _block_use;
  416. size_t _data_size;
  417. long _request_number;
  418. //unsigned char _gap[no_mans_land_size];
  419. // Followed by:
  420. // unsigned char _data[_data_size];
  421. // unsigned char _another_gap[no_mans_land_size];
  422. };
  423. //static _CrtMemBlockHeader* __acrt_first_block;
  424. //static _CrtMemBlockHeader* __acrt_last_block;
  425. void ShowMemoryUsage()
  426. {
  427. #ifdef BF_PLATFORM_WINDOWS
  428. PROCESS_MEMORY_COUNTERS processMemCounters;
  429. processMemCounters.cb = sizeof(PROCESS_MEMORY_COUNTERS);
  430. GetProcessMemoryInfo(GetCurrentProcess(), &processMemCounters, sizeof(PROCESS_MEMORY_COUNTERS));
  431. OutputDebugStrF("WorkingSet : %dk\n", (int)(processMemCounters.WorkingSetSize / 1024));
  432. OutputDebugStrF("VirtualMem : %dk\n", (int)(processMemCounters.PagefileUsage/1024));
  433. static bool hasCheckpoint = true;
  434. _CrtMemState memState;
  435. _CrtMemCheckpoint(&memState);
  436. //OutputDebugStrF("Crt Size: %dk\n", (int)(memState.lTotalCount / 1024));
  437. char* names[6] = { "_FREE_BLOCK", "_NORMAL_BLOCK", "_CRT_BLOCK", "_IGNORE_BLOCK", "_CLIENT_BLOCK", "_MAX_BLOCKS" };
  438. for (int i = 0; i < 5; i++)
  439. {
  440. OutputDebugStrF("%s : %d %dk\n", names[i], memState.lCounts[i], memState.lSizes[i] / 1024);
  441. }
  442. #ifdef _DEBUG
  443. // int64 totalCrtSize = 0;
  444. // int64 totalUseCrtSize = 0;
  445. // _CrtMemBlockHeader* blockPtr = memState.pBlockHeader;
  446. // while (blockPtr != NULL)
  447. // {
  448. // totalCrtSize += blockPtr->_data_size;
  449. // if (blockPtr->_block_use != _FREE_BLOCK)
  450. // totalUseCrtSize += blockPtr->_data_size;
  451. // blockPtr = blockPtr->_block_header_next;
  452. // }
  453. // OutputDebugStrF("Crt Size: %dk Used: %dk\n", (int)(totalCrtSize / 1024), (int)(totalUseCrtSize / 1024));
  454. #endif
  455. _HEAPINFO heapInfo = {0};
  456. int64 heapSize = 0;
  457. int heapStatus;
  458. while ((heapStatus = _heapwalk(&heapInfo)) == _HEAPOK)
  459. {
  460. heapSize += (int64)heapInfo._size;
  461. }
  462. OutputDebugStrF("WALKED HEAP SIZE: %dk\n", heapSize / 1024);
  463. //_CrtMemDumpStatistics(&memState);
  464. #endif
  465. }
  466. /*void* TestHeapAlloc(HANDLE hHeap, DWORD dwFlags, SIZE_T dwBytes)
  467. {
  468. return HeapAlloc(hHeap, dwFlags, dwBytes);
  469. }*/
  470. static void BfFatalErrorHandler(void *user_data, const std::string& reason, bool gen_crash_diag)
  471. {
  472. BF_FATAL(reason.c_str());
  473. OutputDebugStrF("LLVM ERROR: %s\n", reason.c_str());
  474. }
  475. #ifdef BF_PLATFORM_WINDOWS
  476. BOOL WINAPI DllMain(
  477. HANDLE hDllHandle,
  478. DWORD dwReason,
  479. LPVOID lpreserved)
  480. {
  481. //::MessageBoxA(NULL, "A", "B", MB_OK);
  482. // MemReporter memReporter;
  483. // memReporter.mShowInKB = false;
  484. // {
  485. // memReporter.BeginSection("A");
  486. // {
  487. // memReporter.BeginSection("B");
  488. // memReporter.Add(10);
  489. //
  490. // memReporter.Add("C", 1);
  491. // memReporter.Add("D", 2);
  492. //
  493. // memReporter.EndSection();
  494. // }
  495. // memReporter.EndSection();
  496. // }
  497. //
  498. // memReporter.Report();
  499. if (dwReason == DLL_PROCESS_ATTACH)
  500. {
  501. BpInit("127.0.0.1", "Beef IDE");
  502. BpSetThreadName("Main");
  503. BfpThread_SetName(NULL, "Main", NULL);
  504. llvm::install_fatal_error_handler(BfFatalErrorHandler, NULL);
  505. //_CRTDBG_CHECK_EVERY_16_DF
  506. //_CRTDBG_CHECK_ALWAYS_DF
  507. //_CRTDBG_DELAY_FREE_MEM_DF
  508. //_CrtSetDbgFlag (_CRTDBG_ALLOC_MEM_DF /*| _CRTDBG_CHECK_ALWAYS_DF*/);
  509. _CrtSetAllocHook(BfAllocHook);
  510. }
  511. if (dwReason == -123)
  512. {
  513. BpDump();
  514. }
  515. return TRUE;
  516. }
  517. #endif //BF_PLATFORM_WINDOWS
  518. //////
  519. void SleepTest()
  520. {
  521. BfpThread_Sleep(3000);
  522. }
  523. void WdAllocTest();
  524. #ifdef BF_PLATFORM_WINDOWS
  525. static _CrtMemState gStartMemCheckpoint;
  526. #endif
  527. BF_EXPORT void BF_CALLTYPE Debugger_Create()
  528. {
  529. String outStr = BfDemangler::Demangle(
  530. "??0?$_String_alloc@U?$_String_base_types@DV?$allocator@D@std@@@std@@@std@@QEAA@AEBV?$allocator@D@1@@Z"
  531. //"?_Tidy@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEAAX_N_K@Z"
  532. //"?gamma@Class1@@2PAY04NA"
  533. //"?alpha@@3HA"
  534. //"?Fis_i@myclass@@SAHH@Z"
  535. //"??$?0AEBV?$allocator@D@std@@$$V@?$_Compressed_pair@U?$_Wrap_alloc@V?$allocator@D@std@@@std@@V?$_String_val@U?$_Simple_types@D@std@@@2@$00@std@@QEAA@U_One_then_variadic_args_t@1@AEBV?$allocator@D@1@@Z"
  536. //"??0?$map@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@IU?$less@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@I@std@@@2@@std@@QEAA@XZ"
  537. //"??4?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEAAAEAV01@PEBD@Z"
  538. //"??0?$allocator@_W@std@@QEAA@XZ"
  539. //"??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEAA@XZ"
  540. , DbgLanguage_C);
  541. /*{
  542. struct TestStruct
  543. {
  544. TestStruct* mNext;
  545. int mInt;
  546. TestStruct(int i)
  547. {
  548. mNext = NULL;
  549. mInt = i;
  550. }
  551. };
  552. TestStruct tsArr[5] = { 1, 2, 3, 4, 5 };
  553. SLIList<TestStruct*> sliList;
  554. sliList.PushBack(&tsArr[0]);
  555. //sliList.PushBack(&tsArr[1]);
  556. //sliList.PushBack(&tsArr[2]);
  557. auto itr = sliList.begin();
  558. auto* val = *itr;
  559. //++itr;
  560. //val = *itr;
  561. //++itr;
  562. //val = *itr;
  563. sliList.erase(itr);
  564. bool isEnd = itr == sliList.end();
  565. }*/
  566. String str = StrFormat("%d:%@:%l@", 123, (intptr)0x1234567890LL, 0xABCDEF7890LL);
  567. //String str = StrFormat("%l@", "Yo");
  568. //TODO: Very slow, remove
  569. //_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_CHECK_ALWAYS_DF);
  570. //TODO: _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF /*| _CRTDBG_CHECK_EVERY_16_DF*/);
  571. //_CrtSetAllocHook(BfAllocHook);
  572. #ifdef BF_PLATFORM_WINDOWS
  573. _CrtMemCheckpoint(&gStartMemCheckpoint);
  574. #endif
  575. //_CrtSetBreakAlloc(621);
  576. gDebugManager = new DebugManager();
  577. #ifdef ENABLE_DBG_32
  578. gDebugManager->mDebugger32 = CreateDebugger32(gDebugManager, NULL);
  579. #else
  580. gDebugManager->mDebugger32 = NULL;
  581. #endif
  582. #ifdef BF32
  583. gDebugManager->mDebugger64 = NULL;
  584. #else
  585. gDebugManager->mDebugger64 = CreateDebugger64(gDebugManager, NULL);
  586. #endif
  587. #ifdef BF_PLATFORM_WINDOWS
  588. ::AllowSetForegroundWindow(ASFW_ANY);
  589. #endif
  590. }
  591. BF_EXPORT void BF_CALLTYPE Debugger_SetCallbacks(void* callback)
  592. {
  593. }
  594. BF_EXPORT void BF_CALLTYPE Debugger_FullReportMemory()
  595. {
  596. //WdAllocTest();
  597. ShowMemoryUsage();
  598. BfFullReportMemory();
  599. }
  600. BF_EXPORT void BF_CALLTYPE Debugger_Delete()
  601. {
  602. delete gDebugManager;
  603. gDebugManager = NULL;
  604. delete gPerfManager;
  605. gPerfManager = NULL;
  606. //OutputDebugStrF("Deleting Debugger\n");
  607. //BfReportMemory();
  608. #ifdef BF_PLATFORM_WINDOWS
  609. gBgTrackingAllocs = false;
  610. #endif
  611. }
  612. BF_EXPORT void BF_CALLTYPE Debugger_ProgramDone()
  613. {
  614. //TODO:
  615. //::MessageBoxA(NULL, "Done", "Done", MB_OK);
  616. BF_ASSERT(gDebugger == NULL);
  617. //ShowMemoryUsage();
  618. //BfFullReportMemory();
  619. #ifdef CAPTURE_ALLOC_SOURCES
  620. gInsideAlloc = true;
  621. for (int i = 0; i < CAPTURE_ALLOC_POOL_SIZE; i++)
  622. {
  623. if (gHashCaptureAllocSize[i] != NULL)
  624. {
  625. free(gHashCaptureAllocSize[i]->mSymName);
  626. delete gHashCaptureAllocSize[i];
  627. gHashCaptureAllocSize[i] = NULL;
  628. }
  629. }
  630. gBfCaptureSourceAllocMap.clear();
  631. #endif
  632. #ifdef BF_PLATFORM_WINDOWS
  633. _CrtMemDumpAllObjectsSince(&gStartMemCheckpoint);
  634. /*_CrtMemState curMemCheckpoint;
  635. _CrtMemCheckpoint(&curMemCheckpoint);
  636. _CrtMemState memDiff;
  637. if (_CrtMemDifference(&memDiff, &gStartMemCheckpoint, &curMemCheckpoint))
  638. _CrtMemDumpStatistics(&memDiff);*/
  639. _CrtMemState curMemCheckpoint = { 0 };
  640. _CrtMemCheckpoint(&curMemCheckpoint);
  641. OutputDebugStrF("Heap memory usage: %dk\n", curMemCheckpoint.lTotalCount / 1024);
  642. #endif //BF_PLATFORM_WINDOWS
  643. BpShutdown();
  644. }
  645. BF_EXPORT int BF_CALLTYPE Debugger_GetAddrSize()
  646. {
  647. if (gDebugger == NULL)
  648. return 0;
  649. return gDebugger->GetAddrSize();
  650. }
  651. BF_EXPORT bool BF_CALLTYPE Debugger_OpenFile(const char* launchPath, const char* targetPath, const char* args, const char* workingDir, void* envBlockPtr, int envBlockSize)
  652. {
  653. BF_ASSERT(gDebugger == NULL);
  654. if (!FileExists(launchPath))
  655. {
  656. gDebugManager->mOutMessages.push_back(StrFormat("error Unable to locate specified launch target '%s'", launchPath));
  657. return false;
  658. }
  659. DebuggerResult debuggerResult = DebuggerResult_Ok;
  660. if ((gDebugManager->mDebugger64 != NULL) && (gDebugManager->mDebugger64->CanOpen(launchPath, &debuggerResult)))
  661. gDebugger = gDebugManager->mDebugger64;
  662. else
  663. gDebugger = gDebugManager->mDebugger32;
  664. if (gDebugger == NULL)
  665. {
  666. if (debuggerResult == DebuggerResult_WrongBitSize)
  667. gDebugManager->mOutMessages.push_back(StrFormat("error The file 32-bit file '%s' cannot be debugged because 32-bit debugger has been disabled", launchPath));
  668. return false;
  669. }
  670. Array<uint8> envBlock;
  671. if (envBlockPtr != NULL)
  672. {
  673. if (envBlockSize != 0)
  674. envBlock.Insert(0, (uint8*)envBlockPtr, envBlockSize);
  675. }
  676. gDebugger->OpenFile(launchPath, targetPath, args, workingDir, envBlock);
  677. return true;
  678. }
  679. BF_EXPORT void BF_CALLTYPE Debugger_SetSymSrvOptions(const char* symCacheDir, const char* symSrvStr, int flags)
  680. {
  681. Array<String> symServers;
  682. const char* startStr = symSrvStr;
  683. for (const char* cPtr = symSrvStr; true; cPtr++)
  684. {
  685. if ((*cPtr == '\n') || (*cPtr == 0))
  686. {
  687. String symStr = String(startStr, cPtr - startStr);
  688. symStr.Trim();
  689. if (symStr.EndsWith('/'))
  690. symStr.Remove((int)symStr.length() - 1, 1);
  691. if (!symStr.IsEmpty())
  692. symServers.Add(symStr);
  693. startStr = cPtr;
  694. }
  695. if (*cPtr == 0)
  696. break;
  697. }
  698. AutoCrit autoCrit(gDebugManager->mCritSect);
  699. gDebugManager->mSymSrvOptions.mCacheDir = symCacheDir;
  700. gDebugManager->mSymSrvOptions.mSymbolServers = symServers;
  701. gDebugManager->mSymSrvOptions.mFlags = (BfSymSrvFlags)flags;
  702. gDebugManager->mSymSrvOptions.mCacheDir.Trim();
  703. if (gDebugManager->mSymSrvOptions.mCacheDir.IsEmpty())
  704. gDebugManager->mSymSrvOptions.mFlags = BfSymSrvFlag_Disable;
  705. if (flags & BfSymSrvFlag_TempCache)
  706. {
  707. if (!gDebugManager->mSymSrvOptions.mCacheDir.IsEmpty())
  708. {
  709. gDebugManager->mSymSrvOptions.mCacheDir.Append("\\temp");
  710. RecursiveDeleteDirectory(gDebugManager->mSymSrvOptions.mCacheDir);
  711. }
  712. }
  713. gDebugManager->SetSourceServerCacheDir();
  714. }
  715. BF_EXPORT bool BF_CALLTYPE Debugger_OpenMiniDump(const char* fileName)
  716. {
  717. #ifdef BF_PLATFORM_WINDOWS
  718. DbgMiniDump* dbgMiniDump = new DbgMiniDump();
  719. bool result = dbgMiniDump->StartLoad(fileName);
  720. if (!result)
  721. {
  722. delete dbgMiniDump;
  723. return false;
  724. }
  725. if (dbgMiniDump->GetTargetBitCount() == 32)
  726. gDebugger = CreateDebugger32(gDebugManager, dbgMiniDump);
  727. else
  728. gDebugger = CreateDebugger64(gDebugManager, dbgMiniDump);
  729. return result;
  730. #else //BF_PLATFORM_WINDOWS
  731. return false;
  732. #endif
  733. }
  734. BF_EXPORT bool BF_CALLTYPE Debugger_Attach(int processId, BfDbgAttachFlags attachFlags)
  735. {
  736. BF_ASSERT(gDebugger == NULL);
  737. if (gDebugManager->mDebugger64->Attach(processId, attachFlags))
  738. {
  739. gDebugger = gDebugManager->mDebugger64;
  740. return true;
  741. }
  742. if (gDebugManager->mDebugger32->Attach(processId, attachFlags))
  743. {
  744. gDebugger = gDebugManager->mDebugger32;
  745. return true;
  746. }
  747. return false;
  748. }
  749. BF_EXPORT void BF_CALLTYPE Debugger_Run()
  750. {
  751. gDebugger->Run();
  752. }
  753. BF_EXPORT bool BF_CALLTYPE Debugger_HotLoad(const char* fileNamesStr, int hotIdx)
  754. {
  755. //DbgModule* dwarf = new DbgModule(gDebugger);
  756. //dwarf->ReadPE(fileName);
  757. Array<String> fileNames;
  758. const char* curPtr = fileNamesStr;
  759. for (int i = 0; true; i++)
  760. {
  761. if ((fileNamesStr[i] == '\0') || (fileNamesStr[i] == '\n'))
  762. {
  763. String curFileName = String(curPtr, fileNamesStr + i);
  764. if ((curFileName.IndexOf("/vdata.") != -1) || (curFileName.IndexOf("\\vdata.") != -1))
  765. {
  766. // Do vdata first - so new data and special functions don't have to be deferred resolved
  767. fileNames.Insert(0, curFileName);
  768. }
  769. else
  770. fileNames.Add(curFileName);
  771. curPtr = fileNamesStr + i + 1;
  772. }
  773. if (fileNamesStr[i] == '\0')
  774. break;
  775. }
  776. gDebugger->HotLoad(fileNames, hotIdx);
  777. return true;
  778. }
  779. BF_EXPORT bool BF_CALLTYPE Debugger_LoadDebugVisualizers(const char* fileName)
  780. {
  781. String fn = fileName;
  782. bool worked = false;
  783. worked = gDebugManager->mDebugVisualizers->Load(fileName);
  784. if (!gDebugManager->mDebugVisualizers->mErrorString.empty())
  785. {
  786. gDebugManager->mOutMessages.push_back(StrFormat("msg ERROR: %s\n", gDebugManager->mDebugVisualizers->mErrorString.c_str()));
  787. }
  788. // {
  789. // BF_FATAL(gDebugManager->mDebugVisualizers->mErrorString.c_str());
  790. // }
  791. return worked;
  792. }
  793. BF_EXPORT void BF_CALLTYPE Debugger_StopDebugging()
  794. {
  795. gDebugger->StopDebugging();
  796. }
  797. BF_EXPORT void BF_CALLTYPE Debugger_Terminate()
  798. {
  799. gDebugger->Terminate();
  800. }
  801. BF_EXPORT void BF_CALLTYPE Debugger_Detach()
  802. {
  803. gDebugManager->mNetManager->CancelAll();
  804. gDebugger->Detach();
  805. if (gDebugger->IsOnDemandDebugger())
  806. delete gDebugger;
  807. gDebugger = NULL;
  808. gDebugManager->mNetManager->Clear();
  809. }
  810. BF_EXPORT Breakpoint* BF_CALLTYPE Debugger_CreateBreakpoint(const char* fileName, int lineNum, int wantColumn, int instrOffset)
  811. {
  812. return gDebugger->CreateBreakpoint(fileName, lineNum, wantColumn, instrOffset);
  813. }
  814. BF_EXPORT Breakpoint* BF_CALLTYPE Debugger_CreateMemoryBreakpoint(intptr address, int byteCount)
  815. {
  816. return gDebugger->CreateMemoryBreakpoint(address, byteCount);
  817. }
  818. BF_EXPORT Breakpoint* BF_CALLTYPE Debugger_CreateSymbolBreakpoint(const char* symbolName)
  819. {
  820. return gDebugger->CreateSymbolBreakpoint(symbolName);
  821. }
  822. BF_EXPORT Breakpoint* BF_CALLTYPE Debugger_CreateAddressBreakpoint(intptr address)
  823. {
  824. return gDebugger->CreateAddressBreakpoint(address);
  825. }
  826. BF_EXPORT Breakpoint* BF_CALLTYPE Debugger_GetActiveBreakpoint()
  827. {
  828. return gDebugger->GetActiveBreakpoint();
  829. }
  830. BF_EXPORT void BF_CALLTYPE Breakpoint_Delete(Breakpoint* wdBreakpoint)
  831. {
  832. gDebugger->DeleteBreakpoint(wdBreakpoint);
  833. }
  834. BF_EXPORT void BF_CALLTYPE Breakpoint_Check(Breakpoint* breakpoint)
  835. {
  836. gDebugger->CheckBreakpoint(breakpoint);
  837. }
  838. BF_EXPORT int BF_CALLTYPE Breakpoint_GetPendingHotBindIdx(Breakpoint* breakpoint)
  839. {
  840. return breakpoint->mPendingHotBindIdx;
  841. }
  842. BF_EXPORT void BF_CALLTYPE Breakpoint_HotBindBreakpoint(Breakpoint* breakpoint, int lineNum, int hotIdx)
  843. {
  844. gDebugger->HotBindBreakpoint(breakpoint, lineNum, hotIdx);
  845. }
  846. BF_EXPORT void BF_CALLTYPE Breakpoint_SetThreadId(Breakpoint* breakpoint, intptr threadId)
  847. {
  848. BfLogDbg("Breakpoint %p set ThreadId=%d\n", breakpoint, threadId);
  849. breakpoint->mThreadId = threadId;
  850. gDebugger->CheckBreakpoint(breakpoint);
  851. }
  852. BF_EXPORT int BF_CALLTYPE Breakpoint_GetHitCount(Breakpoint* breapoint)
  853. {
  854. return breapoint->mHitCount;
  855. }
  856. BF_EXPORT void BF_CALLTYPE Breakpoint_ClearHitCount(Breakpoint* breapoint)
  857. {
  858. breapoint->mHitCount = 0;
  859. }
  860. BF_EXPORT void BF_CALLTYPE Breakpoint_SetHitCountTarget(Breakpoint* breakpoint, int targetHitCount, DbgHitCountBreakKind breakKind)
  861. {
  862. breakpoint->mTargetHitCount = targetHitCount;
  863. breakpoint->mHitCountBreakKind = breakKind;
  864. }
  865. BF_EXPORT void BF_CALLTYPE Breakpoint_SetCondition(Breakpoint* wdBreakpoint, const char* condition)
  866. {
  867. gDebugger->SetBreakpointCondition(wdBreakpoint, condition);
  868. }
  869. BF_EXPORT void BF_CALLTYPE Breakpoint_SetLogging(Breakpoint* wdBreakpoint, const char* logging, bool breakAfterLogging)
  870. {
  871. gDebugger->SetBreakpointLogging(wdBreakpoint, logging, breakAfterLogging);
  872. }
  873. BF_EXPORT uintptr BF_CALLTYPE Breakpoint_GetAddress(Breakpoint* wdBreakpoint, Breakpoint** outLinkedSibling)
  874. {
  875. if (outLinkedSibling != NULL)
  876. *outLinkedSibling = wdBreakpoint->mLinkedSibling;
  877. return wdBreakpoint->GetAddr();
  878. }
  879. BF_EXPORT bool BF_CALLTYPE Breakpoint_IsMemoryBreakpointBound(Breakpoint* wdBreakpoint)
  880. {
  881. return wdBreakpoint->IsMemoryBreakpointBound();
  882. }
  883. BF_EXPORT intptr BF_CALLTYPE Breakpoint_GetLineNum(Breakpoint* wdBreakpoint)
  884. {
  885. return wdBreakpoint->mLineNum;
  886. }
  887. BF_EXPORT void BF_CALLTYPE Breakpoint_Move(Breakpoint* breakpoint, int lineNum, int wantColumn, bool rebindNow)
  888. {
  889. gDebugger->MoveBreakpoint(breakpoint, lineNum, wantColumn, rebindNow);
  890. }
  891. BF_EXPORT void BF_CALLTYPE Breakpoint_MoveMemoryBreakpoint(Breakpoint* breakpoint, intptr addr, int byteCount)
  892. {
  893. gDebugger->MoveMemoryBreakpoint(breakpoint, addr, byteCount);
  894. }
  895. BF_EXPORT void BF_CALLTYPE Breakpoint_Disable(Breakpoint* wdBreakpoint)
  896. {
  897. gDebugger->DisableBreakpoint(wdBreakpoint);
  898. }
  899. BF_EXPORT void BF_CALLTYPE Debugger_CreateStepFilter(const char* filter, bool isGlobal, BfStepFilterKind filterKind)
  900. {
  901. AutoCrit autoCrit(gDebugManager->mCritSect);
  902. StepFilter stepFilter;
  903. stepFilter.mFilterKind = filterKind;
  904. gDebugManager->mStepFilters[filter] = stepFilter;
  905. gDebugManager->mStepFilterVersion++;
  906. }
  907. BF_EXPORT void BF_CALLTYPE StepFilter_Delete(const char* filter)
  908. {
  909. AutoCrit autoCrit(gDebugManager->mCritSect);
  910. bool didRemove = gDebugManager->mStepFilters.Remove(filter);
  911. BF_ASSERT(didRemove);
  912. gDebugManager->mStepFilterVersion++;
  913. }
  914. BF_EXPORT int BF_CALLTYPE Debugger_GetRunState()
  915. {
  916. AutoCrit autoCrit(gDebugManager->mCritSect);
  917. if (gDebugger == NULL)
  918. return RunState_NotStarted;
  919. return gDebugger->mRunState;
  920. }
  921. BF_EXPORT bool BF_CALLTYPE Debugger_HasPendingDebugLoads()
  922. {
  923. if (gDebugger == NULL)
  924. return false;
  925. return gDebugger->HasPendingDebugLoads();
  926. }
  927. BF_EXPORT const char* BF_CALLTYPE Debugger_PopMessage()
  928. {
  929. AutoCrit autoCrit(gDebugManager->mCritSect);
  930. if (gDebugManager->mOutMessages.size() == 0)
  931. return NULL;
  932. String& outString = *gTLStrReturn.Get();
  933. outString = gDebugManager->mOutMessages.front();
  934. gDebugManager->mOutMessages.pop_front();
  935. //gDebugManager->mOutMessages.erase(gDebugManager->mOutMessages.begin());
  936. return outString.c_str();
  937. }
  938. BF_EXPORT bool BF_CALLTYPE Debugger_HasMessages()
  939. {
  940. AutoCrit autoCrit(gDebugManager->mCritSect);
  941. return gDebugManager->mOutMessages.size() != 0;
  942. }
  943. BF_EXPORT const char* BF_CALLTYPE Debugger_GetCurrentException()
  944. {
  945. /*outString = StrFormat("Exception at 0x%p, exception code 0x%08X",
  946. gDebugger->mCurException.ExceptionAddress, gDebugger->mCurException.ExceptionCode);*/
  947. String& outString = *gTLStrReturn.Get();
  948. outString = gDebugger->GetCurrentException();
  949. return outString.c_str();
  950. }
  951. BF_EXPORT void BF_CALLTYPE Debugger_BreakAll()
  952. {
  953. if (gDebugger != NULL)
  954. gDebugger->BreakAll();
  955. }
  956. BF_EXPORT void BF_CALLTYPE Debugger_Continue()
  957. {
  958. BfLogDbg("Debugger_Continue\n");
  959. gDebugger->ContinueDebugEvent();
  960. }
  961. BF_EXPORT void BF_CALLTYPE Debugger_StepInto(bool inAssembly)
  962. {
  963. gDebugger->StepInto(inAssembly);
  964. }
  965. BF_EXPORT void BF_CALLTYPE Debugger_StepIntoSpecific(intptr addr)
  966. {
  967. gDebugger->StepIntoSpecific(addr);
  968. }
  969. BF_EXPORT void BF_CALLTYPE Debugger_StepOver(bool inAssembly)
  970. {
  971. gDebugger->StepOver(inAssembly);
  972. }
  973. BF_EXPORT void BF_CALLTYPE Debugger_StepOut(bool inAssembly)
  974. {
  975. gDebugger->StepOut(inAssembly);
  976. }
  977. BF_EXPORT void BF_CALLTYPE Debugger_SetNextStatement(bool inAssembly, const char* fileName, int64 wantLineNumOrAsmAddr, int wantColumn)
  978. {
  979. if (fileName == NULL)
  980. fileName = "";
  981. gDebugger->SetNextStatement(inAssembly, fileName, wantLineNumOrAsmAddr, wantColumn);
  982. }
  983. BF_EXPORT void BF_CALLTYPE Debugger_Update()
  984. {
  985. if (gDebugger != NULL)
  986. gDebugger->Update();
  987. }
  988. BF_EXPORT void BF_CALLTYPE Debugger_SetDisplayTypes(const char* referenceId, int8 intDisplayType, int8 mmDisplayType)
  989. {
  990. DwDisplayInfo displayInfo;
  991. displayInfo.mIntDisplayType = (DwIntDisplayType)intDisplayType;
  992. displayInfo.mMmDisplayType = (DwMmDisplayType)mmDisplayType;
  993. if (referenceId == NULL)
  994. {
  995. gDebugManager->mDefaultDisplayInfo = displayInfo;
  996. }
  997. else if ((displayInfo.mIntDisplayType == DwIntDisplayType_Default) &&
  998. (displayInfo.mMmDisplayType == DwMmDisplayType_Default))
  999. {
  1000. /*auto itr = gDebugManager->mDisplayInfos.find(referenceId);
  1001. if (itr != gDebugManager->mDisplayInfos.end())
  1002. gDebugManager->mDisplayInfos.erase(itr);*/
  1003. gDebugManager->mDisplayInfos.Remove(referenceId);
  1004. }
  1005. else
  1006. {
  1007. gDebugManager->mDisplayInfos[referenceId] = displayInfo;
  1008. }
  1009. }
  1010. BF_EXPORT bool BF_CALLTYPE Debugger_GetDisplayTypes(const char* referenceId, int8* intDisplayType, int8* mmDisplayType)
  1011. {
  1012. bool foundSpecific = false;
  1013. DwDisplayInfo* displayInfo = &gDebugManager->mDefaultDisplayInfo;
  1014. if (referenceId != NULL)
  1015. {
  1016. /*auto itr = gDebugManager->mDisplayInfos.find(referenceId);
  1017. if (itr != gDebugManager->mDisplayInfos.end())
  1018. {
  1019. displayInfo = &itr->second;
  1020. foundSpecific = true;
  1021. }*/
  1022. if (gDebugManager->mDisplayInfos.TryGetValue(referenceId, &displayInfo))
  1023. {
  1024. foundSpecific = true;
  1025. }
  1026. }
  1027. *intDisplayType = (int)displayInfo->mIntDisplayType;
  1028. *mmDisplayType = (int)displayInfo->mMmDisplayType;
  1029. return foundSpecific;
  1030. }
  1031. BF_EXPORT const char* BF_CALLTYPE Debugger_GetDisplayTypeNames()
  1032. {
  1033. String& outString = *gTLStrReturn.Get();
  1034. outString.clear();
  1035. for (auto& displayInfoEntry : gDebugManager->mDisplayInfos)
  1036. {
  1037. outString += displayInfoEntry.mKey + "\n";
  1038. }
  1039. return outString.c_str();
  1040. }
  1041. BF_EXPORT const char* BF_CALLTYPE Debugger_EvaluateContinue()
  1042. {
  1043. auto debugger = gDebugger;
  1044. String& outString = *gTLStrReturn.Get();
  1045. outString = debugger->EvaluateContinue();
  1046. return outString.c_str();
  1047. }
  1048. BF_EXPORT void BF_CALLTYPE Debugger_EvaluateContinueKeep()
  1049. {
  1050. auto debugger = gDebugger;
  1051. debugger->EvaluateContinueKeep();
  1052. }
  1053. BF_EXPORT const char* BF_CALLTYPE Debugger_Evaluate(const char* expr, int callStackIdx, int cursorPos, int32 language, int8 expressionFlags)
  1054. {
  1055. auto debugger = gDebugger;
  1056. if (debugger == NULL)
  1057. debugger = gDebugManager->mDebugger64;
  1058. String& outString = *gTLStrReturn.Get();
  1059. outString.clear();
  1060. outString = debugger->Evaluate(expr, callStackIdx, cursorPos, language, (DwEvalExpressionFlags)expressionFlags);
  1061. #ifdef BF_WANTS_LOG_DBG
  1062. {
  1063. int crPos = (int)outString.IndexOf('\n');
  1064. if (crPos != -1)
  1065. BfLogDbg("Debugger_Evaluate Result=%s\n", outString.Substring(0, crPos).c_str());
  1066. else
  1067. BfLogDbg("Debugger_Evaluate Result=%s\n", outString.c_str());
  1068. }
  1069. #endif
  1070. return outString.c_str();
  1071. }
  1072. BF_EXPORT const char* BF_CALLTYPE Debugger_EvaluateToAddress(const char* expr, int callStackIdx, int cursorPos)
  1073. {
  1074. String& outString = *gTLStrReturn.Get();
  1075. outString.clear();
  1076. if (gDebugger != NULL)
  1077. outString = gDebugger->EvaluateToAddress(expr, callStackIdx, cursorPos);
  1078. return outString.c_str();
  1079. }
  1080. BF_EXPORT const char* BF_CALLTYPE Debugger_EvaluateAtAddress(const char* expr, intptr atAddr, int cursorPos)
  1081. {
  1082. String& outString = *gTLStrReturn.Get();
  1083. outString.clear();
  1084. if (gDebugger != NULL)
  1085. outString = gDebugger->EvaluateAtAddress(expr, atAddr, cursorPos);
  1086. return outString.c_str();
  1087. }
  1088. BF_EXPORT const char* BF_CALLTYPE Debugger_GetAutoExpressions(int callStackIdx, uint64 memoryRangeStart, uint64 memoryRangeLen)
  1089. {
  1090. String& outString = *gTLStrReturn.Get();
  1091. outString = gDebugger->GetAutoExpressions(callStackIdx, memoryRangeStart, memoryRangeLen);
  1092. return outString.c_str();
  1093. }
  1094. BF_EXPORT const char* BF_CALLTYPE Debugger_GetAutoLocals(int callStackIdx, bool showRegs)
  1095. {
  1096. String& outString = *gTLStrReturn.Get();
  1097. outString = gDebugger->GetAutoLocals(callStackIdx, showRegs);
  1098. return outString.c_str();
  1099. }
  1100. BF_EXPORT const char* BF_CALLTYPE Debugger_CompactChildExpression(const char* expr, const char* parentExpr, int callStackIdx)
  1101. {
  1102. String& outString = *gTLStrReturn.Get();
  1103. outString = gDebugger->CompactChildExpression(expr, parentExpr, callStackIdx);
  1104. return outString.c_str();
  1105. }
  1106. BF_EXPORT const char* BF_CALLTYPE Debugger_GetCollectionContinuation(const char* continuationData, int callStackIdx, int count)
  1107. {
  1108. String& outString = *gTLStrReturn.Get();
  1109. outString = gDebugger->GetCollectionContinuation(continuationData, callStackIdx, count);
  1110. return outString.c_str();
  1111. }
  1112. BF_EXPORT void BF_CALLTYPE Debugger_ForegroundTarget()
  1113. {
  1114. gDebugger->ForegroundTarget();
  1115. //BOOL worked = EnumThreadWindows(gDebugger->mProcessInfo.dwThreadId, WdEnumWindowsProc, 0);
  1116. //BF_ASSERT(worked);
  1117. }
  1118. BF_EXPORT const char* BF_CALLTYPE Debugger_GetThreadInfo()
  1119. {
  1120. String& outString = *gTLStrReturn.Get();
  1121. outString = gDebugger->GetThreadInfo();
  1122. return outString.c_str();
  1123. }
  1124. BF_EXPORT void BF_CALLTYPE Debugger_SetActiveThread(int threadId)
  1125. {
  1126. gDebugger->SetActiveThread(threadId);
  1127. }
  1128. BF_EXPORT int BF_CALLTYPE Debugger_GetActiveThread()
  1129. {
  1130. return gDebugger->GetActiveThread();
  1131. }
  1132. BF_EXPORT void BF_CALLTYPE Debugger_FreezeThread(int threadId)
  1133. {
  1134. gDebugger->FreezeThread(threadId);
  1135. }
  1136. BF_EXPORT void BF_CALLTYPE Debugger_ThawThread(int threadId)
  1137. {
  1138. gDebugger->ThawThread(threadId);
  1139. }
  1140. BF_EXPORT bool BF_CALLTYPE Debugger_IsActiveThreadWaiting()
  1141. {
  1142. return gDebugger->IsActiveThreadWaiting();
  1143. }
  1144. BF_EXPORT void BF_CALLTYPE CallStack_Update()
  1145. {
  1146. gDebugger->UpdateCallStack();
  1147. }
  1148. BF_EXPORT void BF_CALLTYPE CallStack_Rehup()
  1149. {
  1150. AutoCrit autoCrit(gDebugManager->mCritSect);
  1151. gDebugger->ClearCallStack();
  1152. }
  1153. BF_EXPORT int BF_CALLTYPE CallStack_GetCount()
  1154. {
  1155. return gDebugger->GetCallStackCount();
  1156. }
  1157. BF_EXPORT int BF_CALLTYPE CallStack_GetRequestedStackFrameIdx()
  1158. {
  1159. return gDebugger->GetRequestedStackFrameIdx();
  1160. }
  1161. BF_EXPORT int BF_CALLTYPE CallStack_GetBreakStackFrameIdx()
  1162. {
  1163. return gDebugger->GetBreakStackFrameIdx();
  1164. }
  1165. BF_EXPORT const char* BF_CALLTYPE CallStack_GetStackFrameInfo(int stackFrameIdx, intptr* addr, const char** outFile, int32* outHotIdx, int32* outDefLineStart, int32* outDefLineEnd,
  1166. int32* outLine, int32* outColumn, int32* outLanguage, int32* outStackSize, int8* outFlags)
  1167. {
  1168. String& outString = *gTLStrReturn.Get();
  1169. String& outString2 = *gTLStrReturn2.Get();
  1170. outString = gDebugger->GetStackFrameInfo(stackFrameIdx, addr, &outString2, outHotIdx, outDefLineStart, outDefLineEnd, outLine, outColumn, outLanguage, outStackSize, outFlags);
  1171. *outFile = outString2.c_str();
  1172. return outString.c_str();
  1173. }
  1174. BF_EXPORT const char* BF_CALLTYPE Callstack_GetStackFrameOldFileInfo(int stackFrameIdx)
  1175. {
  1176. String& outString = *gTLStrReturn.Get();
  1177. outString = gDebugger->Callstack_GetStackFrameOldFileInfo(stackFrameIdx);
  1178. return outString.c_str();
  1179. }
  1180. // -1 = no jump, 0 = won't jump, 1 = will jump
  1181. BF_EXPORT int BF_CALLTYPE CallStack_GetJmpState(int stackFrameIdx)
  1182. {
  1183. return gDebugger->GetJmpState(stackFrameIdx);
  1184. }
  1185. BF_EXPORT intptr BF_CALLTYPE Debugger_GetStackFrameCalleeAddr(int stackFrameIdx)
  1186. {
  1187. return gDebugger->GetStackFrameCalleeAddr(stackFrameIdx);
  1188. }
  1189. BF_EXPORT const char* BF_CALLTYPE Debugger_GetCodeAddrInfo(intptr addr, int* outHotIdx, int* outDefLineStart, int* outDefLineEnd, int* outLine, int* outColumn)
  1190. {
  1191. String& outString = *gTLStrReturn.Get();
  1192. outString.clear();
  1193. gDebugger->GetCodeAddrInfo(addr, &outString, outHotIdx, outDefLineStart, outDefLineEnd, outLine, outColumn);
  1194. return outString.c_str();
  1195. }
  1196. BF_EXPORT void BF_CALLTYPE Debugger_GetStackAllocInfo(intptr addr, int* outThreadId, int* outStackIdx)
  1197. {
  1198. gDebugger->GetStackAllocInfo(addr, outThreadId, outStackIdx);
  1199. }
  1200. BF_EXPORT const char* BF_CALLTYPE CallStack_GetStackMethodOwner(int stackFrameIdx, int& language)
  1201. {
  1202. String& outString = *gTLStrReturn.Get();
  1203. outString = gDebugger->GetStackMethodOwner(stackFrameIdx, language);
  1204. return outString.c_str();
  1205. }
  1206. BF_EXPORT const char* BF_CALLTYPE Debugger_FindCodeAddresses(const char* fileName, int line, int column, bool allowAutoResolve)
  1207. {
  1208. String& outString = *gTLStrReturn.Get();
  1209. outString = gDebugger->FindCodeAddresses(fileName, line, column, allowAutoResolve);
  1210. return outString.c_str();
  1211. }
  1212. BF_EXPORT const char* BF_CALLTYPE Debugger_GetAddressSourceLocation(intptr address)
  1213. {
  1214. String& outString = *gTLStrReturn.Get();
  1215. if (gDebugger != NULL)
  1216. outString = gDebugger->GetAddressSourceLocation(address);
  1217. else
  1218. outString = "";
  1219. return outString.c_str();
  1220. }
  1221. BF_EXPORT const char* BF_CALLTYPE Debugger_GetAddressSymbolName(intptr address, bool demangle)
  1222. {
  1223. String& outString = *gTLStrReturn.Get();
  1224. if (gDebugger != NULL)
  1225. outString = gDebugger->GetAddressSymbolName(address, demangle);
  1226. else
  1227. outString = "";
  1228. return outString.c_str();
  1229. }
  1230. BF_EXPORT const char* BF_CALLTYPE Debugger_FindLineCallAddresses(intptr address)
  1231. {
  1232. String& outString = *gTLStrReturn.Get();
  1233. outString = gDebugger->FindLineCallAddresses(address);
  1234. return outString.c_str();
  1235. }
  1236. BF_EXPORT const char* BF_CALLTYPE Debugger_DisassembleAt(intptr address)
  1237. {
  1238. String& outString = *gTLStrReturn.Get();
  1239. outString = gDebugger->DisassembleAt(address);
  1240. return outString.c_str();
  1241. }
  1242. BF_EXPORT void BF_CALLTYPE Debugger_ReadMemory(uintptr address, uintptr size, unsigned char* data)
  1243. {
  1244. if (gDebugger == NULL)
  1245. return;
  1246. //CDH TODO internally clamps to 32-bit here, need to make this more obvious in IDE memory panel etc.
  1247. gDebugger->ReadMemory(address, size, data);
  1248. }
  1249. BF_EXPORT void BF_CALLTYPE Debugger_WriteMemory(uintptr address, uintptr size, unsigned char* data)
  1250. {
  1251. //CDH TODO internally clamps to 32-bit here, need to make this more obvious in IDE memory panel etc.
  1252. gDebugger->WriteMemory(address, data, size);
  1253. }
  1254. BF_EXPORT const char* BF_CALLTYPE Debugger_GetModulesInfo()
  1255. {
  1256. String& outString = *gTLStrReturn.Get();
  1257. outString = gDebugger->GetModulesInfo();
  1258. return outString.c_str();
  1259. }
  1260. BF_EXPORT void BF_CALLTYPE Debugger_CancelSymSrv()
  1261. {
  1262. gDebugger->CancelSymSrv();
  1263. }
  1264. BF_EXPORT int BF_CALLTYPE Debugger_LoadDebugInfoForModule(const char* moduleName) // 0 = No Change, 1 = Loaded, 2 = Loading in background
  1265. {
  1266. return gDebugger->LoadDebugInfoForModule(moduleName);
  1267. }
  1268. BF_EXPORT int BF_CALLTYPE Debugger_LoadDebugInfoForModuleWith(const char* moduleName, const char* debugFilePath) // 0 = No Change, 1 = Loaded, 2 = Loading in background
  1269. {
  1270. return gDebugger->LoadDebugInfoForModule(moduleName, debugFilePath);
  1271. }
  1272. BF_EXPORT void BF_CALLTYPE Debugger_SetStepOverExternalFiles(bool stepOverExternalFiles)
  1273. {
  1274. gDebugManager->mStepOverExternalFiles = stepOverExternalFiles;
  1275. gDebugManager->mStepFilterVersion++;
  1276. }
  1277. BF_EXPORT void BF_CALLTYPE BfLog_Log(char* str)
  1278. {
  1279. BfLog(str);
  1280. }
  1281. BF_EXPORT void BF_CALLTYPE BfLog_LogDbg(char* str)
  1282. {
  1283. BfLogDbg(str);
  1284. }
  1285. BF_EXPORT Profiler* BF_CALLTYPE Debugger_StartProfiling(intptr threadId, char* desc, int sampleRate)
  1286. {
  1287. BF_ASSERT(sampleRate > 0);
  1288. Profiler* profiler = gDebugger->StartProfiling();
  1289. profiler->mTargetThreadId = threadId;
  1290. if (desc != NULL)
  1291. profiler->mDescription = desc;
  1292. profiler->mSamplesPerSecond = sampleRate;
  1293. profiler->Start();
  1294. return profiler;
  1295. }
  1296. BF_EXPORT Profiler* BF_CALLTYPE Debugger_PopProfiler()
  1297. {
  1298. Profiler* profiler = gDebugger->PopProfiler();
  1299. return profiler;
  1300. }
  1301. BF_EXPORT void BF_CALLTYPE Debugger_InitiateHotResolve(int flags)
  1302. {
  1303. if (gDebugger != NULL)
  1304. gDebugger->InitiateHotResolve((DbgHotResolveFlags)flags);
  1305. }
  1306. BF_EXPORT const char* BF_CALLTYPE Debugger_GetHotResolveData(uint8* outTypeData, int* outTypeDataSize)
  1307. {
  1308. AutoCrit autoCrit(gDebugManager->mCritSect);
  1309. if (gDebugger->mHotResolveData == NULL)
  1310. {
  1311. *outTypeDataSize = -1;
  1312. return NULL;
  1313. }
  1314. int dataSize = (int)gDebugger->mHotResolveData->mTypeData.size();
  1315. if (*outTypeDataSize < dataSize)
  1316. {
  1317. *outTypeDataSize = dataSize;
  1318. return NULL;
  1319. }
  1320. *outTypeDataSize = dataSize;
  1321. if (dataSize > 0)
  1322. memcpy(outTypeData, &gDebugger->mHotResolveData->mTypeData[0], dataSize);
  1323. String& outString = *gTLStrReturn.Get();
  1324. outString.Clear();
  1325. for (auto& str : gDebugger->mHotResolveData->mBeefCallStackEntries)
  1326. {
  1327. if (!outString.IsEmpty())
  1328. outString += "\n";
  1329. outString += str;
  1330. }
  1331. return outString.c_str();
  1332. }
  1333. BF_EXPORT void Debugger_SetAliasPath(char* origPath, char* localPath)
  1334. {
  1335. gDebugger->SetAliasPath(origPath, localPath);
  1336. }
  1337. ///
  1338. BF_EXPORT bool BF_CALLTYPE Profiler_IsRunning(Profiler* profiler)
  1339. {
  1340. return profiler->IsSampling();
  1341. }
  1342. BF_EXPORT void BF_CALLTYPE Profiler_Stop(Profiler* profiler)
  1343. {
  1344. profiler->Stop();
  1345. }
  1346. BF_EXPORT void BF_CALLTYPE Profiler_Clear(Profiler* profiler)
  1347. {
  1348. profiler->Clear();
  1349. }
  1350. BF_EXPORT const char* BF_CALLTYPE Profiler_GetOverview(Profiler* profiler)
  1351. {
  1352. String& outString = *gTLStrReturn.Get();
  1353. outString = profiler->GetOverview();
  1354. return outString.c_str();
  1355. }
  1356. BF_EXPORT const char* BF_CALLTYPE Profiler_GetThreadList(Profiler* profiler)
  1357. {
  1358. String& outString = *gTLStrReturn.Get();
  1359. outString = profiler->GetThreadList();
  1360. return outString.c_str();
  1361. }
  1362. BF_EXPORT const char* BF_CALLTYPE Profiler_GetCallTree(Profiler* profiler, int threadId, bool reverse)
  1363. {
  1364. String& outString = *gTLStrReturn.Get();
  1365. outString = profiler->GetCallTree(threadId, reverse);
  1366. return outString.c_str();
  1367. }
  1368. BF_EXPORT void BF_CALLTYPE Profiler_Delete(Profiler* profiler)
  1369. {
  1370. int z = 0;
  1371. delete profiler;
  1372. }
  1373. BF_TLS_DECLSPEC static int gTLSValue = 3;
  1374. BF_EXPORT void BF_CALLTYPE TimeTest(uint32 startTime)
  1375. {
  1376. gTLSValue++;
  1377. int elapsedTime = BFTickCount() - startTime;
  1378. OutputDebugStrF("Load Time: %d\n", elapsedTime);
  1379. }
  1380. BF_EXPORT void BF_CALLTYPE BFTest()
  1381. {
  1382. struct DeferredResolveEntry2
  1383. {
  1384. BfFieldDef* mFieldDef;
  1385. int mTypeArrayIdx;
  1386. };
  1387. DeferredResolveEntry2 entry = { NULL, 333 };
  1388. llvm::SmallVector<DeferredResolveEntry2, 8> vec;
  1389. vec.push_back(DeferredResolveEntry2 { NULL, 111 } );
  1390. vec.push_back(DeferredResolveEntry2 { NULL, 222 } );
  1391. }
  1392. ///
  1393. // __attribute__((weak))
  1394. // Debugger* Beefy::CreateDebugger32(DebugManager* debugManager, DbgMiniDump* miniDump)
  1395. // {
  1396. // return NULL;
  1397. // }