mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-07 19:18:19 +02:00
1834 lines
No EOL
47 KiB
C++
1834 lines
No EOL
47 KiB
C++
#include "DebugManager.h"
|
|
#include "BeefySysLib/util/CritSect.h"
|
|
#include "Compiler/BfSystem.h"
|
|
#include "Compiler/BfParser.h"
|
|
#include "Compiler/MemReporter.h"
|
|
#include "Compiler/BfIRCodeGen.h"
|
|
#include "Debugger.h"
|
|
#include "DebugVisualizers.h"
|
|
#include "RadixMap.h"
|
|
#include "Compiler/BfDemangler.h"
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
#include "BeefySysLib/util/BeefPerf.h"
|
|
#include "NetManager.h"
|
|
#include "Compiler/CeDebugger.h"
|
|
|
|
#ifdef BF_PLATFORM_WINDOWS
|
|
#include "DbgMiniDump.h"
|
|
#endif
|
|
|
|
#include <iostream>
|
|
|
|
#pragma warning(push)
|
|
#pragma warning(disable:4141)
|
|
#pragma warning(disable:4146)
|
|
#pragma warning(disable:4291)
|
|
#pragma warning(disable:4244)
|
|
#pragma warning(disable:4267)
|
|
#pragma warning(disable:4624)
|
|
#pragma warning(disable:4800)
|
|
#pragma warning(disable:4996)
|
|
#include "llvm/IR/LLVMContext.h"
|
|
#include "llvm/IRReader/IRReader.h"
|
|
//#include "llvm/Bitcode/ReaderWriter.h"
|
|
#pragma warning(pop)
|
|
|
|
#ifdef BF_PLATFORM_WINDOWS
|
|
#include <psapi.h>
|
|
#include <shlobj.h>
|
|
#endif
|
|
|
|
#include "BeefySysLib/util/AllocDebug.h"
|
|
|
|
#pragma warning(disable:4190)
|
|
|
|
#define ENABLE_DBG_32
|
|
|
|
//#define BF_DBG_32
|
|
//#include "WinDebugger.h"
|
|
//#undef BF_DBG_32
|
|
|
|
/*#define BF_DBG_64
|
|
#include "WinDebugger.h"
|
|
#undef BF_DBG_64*/
|
|
|
|
int Beefy::sRadixMapCount = 0;
|
|
int Beefy::sRootSize = 0;
|
|
int Beefy::sMidSize = 0;
|
|
int Beefy::sLeafSize = 0;
|
|
|
|
USING_NS_BF;
|
|
|
|
DebugManager* Beefy::gDebugManager = NULL;
|
|
Debugger* Beefy::gDebugger = NULL;
|
|
PerfManager* Beefy::gDbgPerfManager = NULL;
|
|
|
|
int64 gBfAllocCount = 0;
|
|
int64 gBfFreeCount = 0;
|
|
|
|
static Dictionary<long, int> gBfAllocMap;
|
|
static Dictionary<void*, long> gBfAllocAddrMap;
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
DebugManager::DebugManager()
|
|
{
|
|
gDbgPerfManager = new PerfManager();
|
|
|
|
mDebugVisualizers = new DebugVisualizers();
|
|
mStepFilterVersion = 0;
|
|
mStepOverExternalFiles = false;
|
|
|
|
mDebugger32 = NULL;
|
|
mDebugger64 = NULL;
|
|
mNetManager = new NetManager();
|
|
mNetManager->mDebugManager = this;
|
|
|
|
mSymSrvOptions.mCacheDir = "C:\\SymCache";
|
|
|
|
mSymSrvOptions.mSymbolServers.Add("C:\\BeefSyms");
|
|
mSymSrvOptions.mSymbolServers.Add("https://msdl.microsoft.com/download/symbols");
|
|
mSymSrvOptions.mSymbolServers.Add("http://wintest.beefy2d.com/symbols/");
|
|
mSymSrvOptions.mSymbolServers.Add("https://chromium-browser-symsrv.commondatastorage.googleapis.com");
|
|
//TODO: Just for testing
|
|
mSymSrvOptions.mSymbolServers.Add("http://127.0.0.1/symbols");
|
|
|
|
SetSourceServerCacheDir();
|
|
|
|
mOutputFilterFlags = BfOutputFilterFlags_None;
|
|
}
|
|
|
|
DebugManager::~DebugManager()
|
|
{
|
|
if ((gDebugger != NULL) && (gDebugger->IsOnDemandDebugger()))
|
|
{
|
|
delete gDebugger;
|
|
gDebugger = NULL;
|
|
}
|
|
|
|
delete mNetManager;
|
|
delete mDebugger64;
|
|
delete mDebugger32;
|
|
/*for (auto stepFilter : mStepFilters)
|
|
{
|
|
}*/
|
|
delete mDebugVisualizers;
|
|
}
|
|
|
|
void DebugManager::OutputMessage(const StringImpl& msg)
|
|
{
|
|
AutoCrit autoCrit(mCritSect);
|
|
mOutMessages.push_back("msg " + msg);
|
|
}
|
|
|
|
void DebugManager::OutputRawMessage(const StringImpl& msg)
|
|
{
|
|
AutoCrit autoCrit(mCritSect);
|
|
mOutMessages.push_back(msg);
|
|
}
|
|
|
|
void DebugManager::SetSourceServerCacheDir()
|
|
{
|
|
#ifdef BF_PLATFORM_WINDOWS
|
|
AutoCrit autoCrit(mCritSect);
|
|
|
|
WCHAR appDataPath[MAX_PATH] = { 0 };
|
|
SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, appDataPath);
|
|
mSymSrvOptions.mSourceServerCacheDir = UTF8Encode(appDataPath);
|
|
mSymSrvOptions.mSourceServerCacheDir += "\\SourceServer";
|
|
|
|
if (mSymSrvOptions.mFlags & BfSymSrvFlag_TempCache)
|
|
{
|
|
mSymSrvOptions.mSourceServerCacheDir += "\\temp";
|
|
RecursiveDeleteDirectory(mSymSrvOptions.mSourceServerCacheDir);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void DebugManager::SetOutputFilterFlags(BfOutputFilterFlags outputFilterFlags)
|
|
{
|
|
mOutputFilterFlags = outputFilterFlags;
|
|
}
|
|
|
|
BfOutputFilterFlags DebugManager::GetOutputFilterFlags()
|
|
{
|
|
return mOutputFilterFlags;
|
|
}
|
|
|
|
//#define CAPTURE_ALLOC_BACKTRACE
|
|
//#define CAPTURE_ALLOC_SOURCES
|
|
|
|
#ifdef CAPTURE_ALLOC_BACKTRACE
|
|
const int sNumAllocAddrs = 0x300000;
|
|
const int sCaptureDepth = 14;
|
|
const int sCaptureOffset = 4;
|
|
static intptr gAllocAddrs[sNumAllocAddrs][sCaptureDepth];
|
|
#endif
|
|
|
|
#ifdef CAPTURE_ALLOC_SOURCES
|
|
#include <Dbghelp.h>
|
|
#pragma comment(lib, "dbghelp.lib")
|
|
|
|
struct CaptureAllocLocation
|
|
{
|
|
public:
|
|
char* mSymName;
|
|
int mTotalSize;
|
|
bool mIsEndpoint;
|
|
};
|
|
|
|
struct CaptureAllocEntry
|
|
{
|
|
public:
|
|
CaptureAllocLocation* mLoc;
|
|
int mAllocSize;
|
|
};
|
|
|
|
std::map<long, CaptureAllocEntry> gBfCaptureSourceAllocMap;
|
|
//std::map<void*, CaptureAllocLocation> gBfCaptureAllocLocation;
|
|
|
|
#define CAPTURE_ALLOC_POOL_SIZE 0x100000
|
|
CaptureAllocLocation* gHashCaptureAllocSize[CAPTURE_ALLOC_POOL_SIZE] = { 0 };
|
|
|
|
static void ReallocEntry(long oldRequest, long newRequest, int newSize)
|
|
{
|
|
auto itr = gBfCaptureSourceAllocMap.find(oldRequest);
|
|
if (itr != gBfCaptureSourceAllocMap.end())
|
|
{
|
|
CaptureAllocEntry* entry = &itr->second;
|
|
entry->mLoc->mTotalSize -= entry->mAllocSize;
|
|
entry->mLoc->mTotalSize += newSize;
|
|
entry->mAllocSize = newSize;
|
|
gBfCaptureSourceAllocMap[newRequest] = *entry;
|
|
gBfCaptureSourceAllocMap.erase(itr);
|
|
}
|
|
}
|
|
|
|
static void RemoveAllocEntry(long lRequest)
|
|
{
|
|
auto itr = gBfCaptureSourceAllocMap.find(lRequest);
|
|
if (itr != gBfCaptureSourceAllocMap.end())
|
|
{
|
|
CaptureAllocEntry* entry = &itr->second;
|
|
|
|
entry->mLoc->mTotalSize -= entry->mAllocSize;
|
|
gBfCaptureSourceAllocMap.erase(itr);
|
|
}
|
|
}
|
|
|
|
//const LOC_HASHES
|
|
|
|
#endif
|
|
|
|
static int gBfNumAllocs = 0;
|
|
|
|
#ifdef BF_PLATFORM_WINDOWS
|
|
|
|
static bool gBgTrackingAllocs = false; ///// Leave false most of the time
|
|
CritSect gBfCritSect;
|
|
static bool gInsideAlloc = false;
|
|
static int gLastReqId = 0;
|
|
static int BfAllocHook(int nAllocType, void *pvData,
|
|
size_t nSize, int nBlockUse, long lRequest,
|
|
const unsigned char * szFileName, int nLine)
|
|
{
|
|
#ifdef CAPTURE_ALLOC_SOURCES
|
|
if (gInsideAlloc)
|
|
return TRUE;
|
|
|
|
gInsideAlloc = true;
|
|
|
|
intptr stackTrace[20];
|
|
int traceCount = (int)RtlCaptureStackBackTrace(1, 20, (void**)&stackTrace, 0);
|
|
|
|
/*intptr ebpVal;
|
|
__asm
|
|
{
|
|
mov ebpVal, ebp
|
|
}*/
|
|
|
|
//intptr ebp = ebpVal;
|
|
//intptr eip = 0;
|
|
|
|
static HANDLE hProcess = 0;
|
|
if (hProcess == NULL)
|
|
{
|
|
hProcess = GetCurrentProcess();
|
|
BOOL worked = SymInitialize(hProcess, NULL, TRUE);
|
|
}
|
|
|
|
if (nAllocType == _HOOK_ALLOC)
|
|
{
|
|
for (int i = 0; i < traceCount; i++)
|
|
{
|
|
/*__try
|
|
{
|
|
ebp = *((intptr*)ebp + 0);
|
|
if (ebp < 0x100000)
|
|
break;
|
|
eip = *((intptr*)ebp + 1);
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
break;
|
|
}*/
|
|
|
|
intptr curAddr = stackTrace[i];
|
|
|
|
const char* name = "?";
|
|
|
|
int hashVal = (curAddr & 0x7FFFFFFF) % CAPTURE_ALLOC_POOL_SIZE;
|
|
if (gHashCaptureAllocSize[hashVal] == NULL)
|
|
{
|
|
//static HPROCESS hProc = GEtProcessH
|
|
char symData[4096];
|
|
DWORD64 disp = 0;
|
|
SYMBOL_INFO* symInfo = (SYMBOL_INFO*)&symData;
|
|
memset(symInfo, 0, sizeof(SYMBOL_INFO));
|
|
symInfo->SizeOfStruct = sizeof(SYMBOL_INFO);
|
|
symInfo->MaxNameLen = sizeof(symData) - sizeof(SYMBOL_INFO);
|
|
bool foundSym = false;
|
|
if (SymFromAddr(hProcess, (DWORD64)curAddr, &disp, symInfo))
|
|
{
|
|
name = symInfo->Name;
|
|
foundSym = true;
|
|
}
|
|
|
|
CaptureAllocLocation* captureAllocLoc = new CaptureAllocLocation();
|
|
captureAllocLoc->mSymName = strdup(name);
|
|
captureAllocLoc->mTotalSize = 0;
|
|
captureAllocLoc->mIsEndpoint = (!foundSym) || (strncmp(name, "Beefy::", 7) == 0) || (strncmp(name, "llvm::", 6) == 0);
|
|
if (strstr(name, "operator new") != NULL)
|
|
captureAllocLoc->mIsEndpoint = false;
|
|
if (strstr(name, "::allocateBuckets") != NULL)
|
|
captureAllocLoc->mIsEndpoint = false;
|
|
if (strstr(name, "::grow") != NULL)
|
|
captureAllocLoc->mIsEndpoint = false;
|
|
if (strstr(name, "::DenseMap") != NULL)
|
|
captureAllocLoc->mIsEndpoint = false;
|
|
/*if (strstr(name, "::Allocate") != NULL)
|
|
captureAllocLoc->mIsEndpoint = false;*/
|
|
if (strstr(name, "::Alloc") != NULL)
|
|
captureAllocLoc->mIsEndpoint = false;
|
|
/*if (strstr(name, "::AllocBytes") != NULL)
|
|
captureAllocLoc->mIsEndpoint = false;
|
|
if (strstr(name, "::AllocMemoryBlock") != NULL)
|
|
captureAllocLoc->mIsEndpoint = false;*/
|
|
if (strstr(name, "::GrowPool") != NULL)
|
|
captureAllocLoc->mIsEndpoint = false;
|
|
|
|
// Testing COnstantInt::get
|
|
if (strstr(name, "::CreateConst") != NULL)
|
|
captureAllocLoc->mIsEndpoint = false;
|
|
if (strstr(name, "::get") != NULL)
|
|
captureAllocLoc->mIsEndpoint = false;
|
|
|
|
if ((captureAllocLoc->mIsEndpoint) && (foundSym))
|
|
{
|
|
}
|
|
|
|
gHashCaptureAllocSize[hashVal] = captureAllocLoc;
|
|
}
|
|
|
|
CaptureAllocLocation* captureAllocLoc = gHashCaptureAllocSize[hashVal];
|
|
|
|
if ((i < 19) && (!captureAllocLoc->mIsEndpoint))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
captureAllocLoc->mTotalSize += (int)nSize;
|
|
|
|
CaptureAllocEntry entry;
|
|
entry.mAllocSize = (int)nSize;
|
|
entry.mLoc = captureAllocLoc;
|
|
gBfCaptureSourceAllocMap[lRequest] = entry;
|
|
break;
|
|
//if (i >= sCaptureOffset)
|
|
//gAllocAddrs[lRequest][i - sCaptureOffset] = eip;
|
|
}
|
|
}
|
|
else if (nAllocType == _HOOK_REALLOC)
|
|
{
|
|
long oldRequest = ((int*)pvData)[-2];
|
|
ReallocEntry(oldRequest, lRequest, nSize);
|
|
}
|
|
else if (nAllocType == _HOOK_FREE)
|
|
{
|
|
lRequest = ((int*)pvData)[-2];
|
|
RemoveAllocEntry(lRequest);
|
|
}
|
|
|
|
gInsideAlloc = false;
|
|
#endif
|
|
|
|
#ifdef CAPTURE_ALLOC_BACKTRACE
|
|
if (lRequest < sNumAllocAddrs)
|
|
{
|
|
gAllocAddrs[lRequest][0] = 1;
|
|
|
|
intptr ebpVal;
|
|
__asm
|
|
{
|
|
mov ebpVal, ebp
|
|
}
|
|
|
|
intptr ebp = ebpVal;
|
|
intptr eip = 0;
|
|
|
|
for (int i = 0; i < sCaptureDepth + sCaptureOffset; i++)
|
|
{
|
|
__try
|
|
{
|
|
ebp = *((intptr*)ebp + 0);
|
|
if (ebp < 0x100000)
|
|
break;
|
|
eip = *((intptr*)ebp + 1);
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if (i >= sCaptureOffset)
|
|
gAllocAddrs[lRequest][i - sCaptureOffset] = eip;
|
|
}
|
|
}
|
|
#else
|
|
|
|
if (!gBgTrackingAllocs)
|
|
return TRUE;
|
|
|
|
/*AutoCrit critSect(gBfCritSect);
|
|
|
|
if (gLastReqId == lRequest)
|
|
return TRUE;
|
|
if (!gInsideAlloc)
|
|
{
|
|
gInsideAlloc = true;
|
|
if (nAllocType == _HOOK_ALLOC)
|
|
{
|
|
gBfNumAllocs++;
|
|
gBfAllocCount += nSize;
|
|
gBfAllocMap[lRequest] = nSize;
|
|
}
|
|
if (nAllocType == _HOOK_FREE)
|
|
{
|
|
lRequest = ((int*)pvData)[-2];
|
|
|
|
auto itr = gBfAllocMap.find(lRequest);
|
|
if (itr != gBfAllocMap.end())
|
|
{
|
|
gBfFreeCount += itr->second;
|
|
gBfAllocMap.erase(itr);
|
|
}
|
|
}
|
|
gInsideAlloc = false;
|
|
}
|
|
|
|
gLastReqId = lRequest;
|
|
if (szFileName == NULL)
|
|
return TRUE; */
|
|
|
|
/*char str[1024];
|
|
sprintf(str, "Alloc: %d File: %s Line: %d\n", lRequest, szFileName, nLine);
|
|
OutputDebugStringA(str);*/
|
|
#endif
|
|
return TRUE;
|
|
}
|
|
|
|
#endif //BF_PLATFORM_WINDOWS
|
|
|
|
void BfReportMemory()
|
|
{
|
|
BfLogDbg("Used: %.2fM NumAllocs: %d Allocs: %.2fM\n", (gBfAllocCount - gBfFreeCount) / (1024.0 * 1024.0), gBfNumAllocs, gBfAllocCount / (1024.0 * 1024.0));
|
|
}
|
|
|
|
void BfFullReportMemory()
|
|
{
|
|
/*OutputDebugStrF("Testing OOB\n");
|
|
char* str = new char[12];
|
|
delete str;
|
|
char c = str[1];*/
|
|
|
|
if (gBfParserCache != NULL)
|
|
{
|
|
MemReporter memReporter;
|
|
memReporter.BeginSection("ParserCache");
|
|
gBfParserCache->ReportMemory(&memReporter);
|
|
memReporter.EndSection();
|
|
memReporter.Report();
|
|
}
|
|
|
|
OutputDebugStrF("Used: %.2fM NumAllocs: %d Allocs: %.2fM\n", (gBfAllocCount - gBfFreeCount) / (1024.0 * 1024.0), gBfNumAllocs, gBfAllocCount / (1024.0 * 1024.0));
|
|
OutputDebugStrF("ChunkedDataBuffer allocated blocks: %d\n", ChunkedDataBuffer::sBlocksAllocated);
|
|
|
|
if (gDebugManager != NULL)
|
|
{
|
|
MemReporter memReporter;
|
|
if (gDebugManager->mDebugger32 != NULL)
|
|
{
|
|
memReporter.BeginSection("Debugger32");
|
|
gDebugManager->mDebugger32->ReportMemory(&memReporter);
|
|
memReporter.EndSection();
|
|
}
|
|
memReporter.BeginSection("Debugger64");
|
|
gDebugManager->mDebugger64->ReportMemory(&memReporter);
|
|
memReporter.EndSection();
|
|
memReporter.Report();
|
|
}
|
|
|
|
BpDump();
|
|
|
|
#ifdef CAPTURE_ALLOC_SOURCES
|
|
int memTotal = 0;
|
|
std::map<String, int> byNameMap;
|
|
for (int i = 0; i < CAPTURE_ALLOC_POOL_SIZE; i++)
|
|
{
|
|
CaptureAllocLocation* allocLoc = gHashCaptureAllocSize[i];
|
|
if ((allocLoc != NULL) && (allocLoc->mTotalSize > 0))
|
|
{
|
|
auto itr = byNameMap.insert(std::map<String, int>::value_type(allocLoc->mSymName, 0));
|
|
itr.first->second += allocLoc->mTotalSize;
|
|
memTotal += allocLoc->mTotalSize;
|
|
}
|
|
}
|
|
|
|
std::multimap<int, String> bySizeMap;
|
|
|
|
for (auto kv : byNameMap)
|
|
{
|
|
//OutputDebugStrF("%dk %s\n", (kv.second + 1023) / 1024, kv.first.c_str());
|
|
bySizeMap.insert(std::multimap<int, String>::value_type(-kv.second, kv.first));
|
|
}
|
|
|
|
for (auto kv : bySizeMap)
|
|
{
|
|
OutputDebugStrF("%dk %s\n", (-kv.first + 1023) / 1024, kv.second.c_str());
|
|
}
|
|
|
|
OutputDebugStrF("Total %dk\n", memTotal / 1024);
|
|
#endif
|
|
}
|
|
|
|
struct _CrtMemBlockHeader
|
|
{
|
|
_CrtMemBlockHeader* _block_header_next;
|
|
_CrtMemBlockHeader* _block_header_prev;
|
|
char const* _file_name;
|
|
int _line_number;
|
|
|
|
int _block_use;
|
|
size_t _data_size;
|
|
|
|
long _request_number;
|
|
//unsigned char _gap[no_mans_land_size];
|
|
|
|
// Followed by:
|
|
// unsigned char _data[_data_size];
|
|
// unsigned char _another_gap[no_mans_land_size];
|
|
};
|
|
|
|
//static _CrtMemBlockHeader* __acrt_first_block;
|
|
//static _CrtMemBlockHeader* __acrt_last_block;
|
|
|
|
void ShowMemoryUsage()
|
|
{
|
|
#ifdef BF_PLATFORM_WINDOWS
|
|
PROCESS_MEMORY_COUNTERS processMemCounters;
|
|
processMemCounters.cb = sizeof(PROCESS_MEMORY_COUNTERS);
|
|
GetProcessMemoryInfo(GetCurrentProcess(), &processMemCounters, sizeof(PROCESS_MEMORY_COUNTERS));
|
|
OutputDebugStrF("WorkingSet : %dk\n", (int)(processMemCounters.WorkingSetSize / 1024));
|
|
OutputDebugStrF("VirtualMem : %dk\n", (int)(processMemCounters.PagefileUsage/1024));
|
|
|
|
static bool hasCheckpoint = true;
|
|
_CrtMemState memState;
|
|
_CrtMemCheckpoint(&memState);
|
|
//OutputDebugStrF("Crt Size: %dk\n", (int)(memState.lTotalCount / 1024));
|
|
|
|
char* names[6] = { "_FREE_BLOCK", "_NORMAL_BLOCK", "_CRT_BLOCK", "_IGNORE_BLOCK", "_CLIENT_BLOCK", "_MAX_BLOCKS" };
|
|
for (int i = 0; i < 5; i++)
|
|
{
|
|
OutputDebugStrF("%s : %d %dk\n", names[i], memState.lCounts[i], memState.lSizes[i] / 1024);
|
|
}
|
|
|
|
#ifdef _DEBUG
|
|
// int64 totalCrtSize = 0;
|
|
// int64 totalUseCrtSize = 0;
|
|
// _CrtMemBlockHeader* blockPtr = memState.pBlockHeader;
|
|
// while (blockPtr != NULL)
|
|
// {
|
|
// totalCrtSize += blockPtr->_data_size;
|
|
// if (blockPtr->_block_use != _FREE_BLOCK)
|
|
// totalUseCrtSize += blockPtr->_data_size;
|
|
// blockPtr = blockPtr->_block_header_next;
|
|
// }
|
|
// OutputDebugStrF("Crt Size: %dk Used: %dk\n", (int)(totalCrtSize / 1024), (int)(totalUseCrtSize / 1024));
|
|
#endif
|
|
|
|
_HEAPINFO heapInfo = {0};
|
|
int64 heapSize = 0;
|
|
|
|
int heapStatus;
|
|
while ((heapStatus = _heapwalk(&heapInfo)) == _HEAPOK)
|
|
{
|
|
heapSize += (int64)heapInfo._size;
|
|
}
|
|
OutputDebugStrF("WALKED HEAP SIZE: %dk\n", heapSize / 1024);
|
|
|
|
//_CrtMemDumpStatistics(&memState);
|
|
#endif
|
|
}
|
|
|
|
/*void* TestHeapAlloc(HANDLE hHeap, DWORD dwFlags, SIZE_T dwBytes)
|
|
{
|
|
return HeapAlloc(hHeap, dwFlags, dwBytes);
|
|
}*/
|
|
|
|
static void BfFatalErrorHandler(void *user_data, const char* reason, bool gen_crash_diag)
|
|
{
|
|
BF_FATAL(reason);
|
|
OutputDebugStrF("LLVM ERROR: %s\n", reason);
|
|
}
|
|
|
|
#ifdef BF_PLATFORM_WINDOWS
|
|
BOOL WINAPI DllMain(
|
|
HANDLE hDllHandle,
|
|
DWORD dwReason,
|
|
LPVOID lpreserved)
|
|
{
|
|
if (dwReason == DLL_PROCESS_ATTACH)
|
|
{
|
|
BpInit("127.0.0.1", "Beef IDE");
|
|
BpSetThreadName("Main");
|
|
BfpThread_SetName(NULL, "Main", NULL);
|
|
|
|
llvm::install_fatal_error_handler(BfFatalErrorHandler, NULL);
|
|
|
|
//_CRTDBG_CHECK_EVERY_16_DF
|
|
//_CRTDBG_CHECK_ALWAYS_DF
|
|
//_CRTDBG_DELAY_FREE_MEM_DF
|
|
|
|
//_CrtSetDbgFlag (_CRTDBG_ALLOC_MEM_DF /*| _CRTDBG_CHECK_ALWAYS_DF*/);
|
|
_CrtSetAllocHook(BfAllocHook);
|
|
}
|
|
|
|
if (dwReason == -123)
|
|
{
|
|
BpDump();
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
#endif //BF_PLATFORM_WINDOWS
|
|
|
|
//////
|
|
|
|
void SleepTest()
|
|
{
|
|
BfpThread_Sleep(3000);
|
|
}
|
|
|
|
void WdAllocTest();
|
|
|
|
namespace BeefyDbg64
|
|
{
|
|
class WinDebugger;
|
|
void TestPDB(const StringImpl& fileName, WinDebugger* debugger);
|
|
}
|
|
|
|
#ifdef BF_PLATFORM_WINDOWS
|
|
static _CrtMemState gStartMemCheckpoint;
|
|
#endif
|
|
BF_EXPORT void BF_CALLTYPE Debugger_Create()
|
|
{
|
|
//TODO: Very slow, remove
|
|
//_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_CHECK_ALWAYS_DF);
|
|
//_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_CHECK_EVERY_16_DF);
|
|
//TODO: _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF /*| _CRTDBG_CHECK_EVERY_16_DF*/);
|
|
//_CrtSetAllocHook(BfAllocHook);
|
|
|
|
#ifdef BF_PLATFORM_WINDOWS
|
|
_CrtMemCheckpoint(&gStartMemCheckpoint);
|
|
#endif
|
|
//_CrtSetBreakAlloc(621);
|
|
|
|
gDebugManager = new DebugManager();
|
|
#ifdef ENABLE_DBG_32
|
|
gDebugManager->mDebugger32 = CreateDebugger32(gDebugManager, NULL);
|
|
#else
|
|
gDebugManager->mDebugger32 = NULL;
|
|
#endif
|
|
|
|
#ifdef BF32
|
|
gDebugManager->mDebugger64 = NULL;
|
|
#else
|
|
gDebugManager->mDebugger64 = CreateDebugger64(gDebugManager, NULL);
|
|
#endif
|
|
|
|
#ifdef BF_PLATFORM_WINDOWS
|
|
::AllowSetForegroundWindow(ASFW_ANY);
|
|
#endif
|
|
|
|
//BeefyDbg64::TestPDB("C:/Beef/IDE/dist/IDEHelper64_d.pdb", (BeefyDbg64::WinDebugger*)gDebugManager->mDebugger64);
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE Debugger_SetCallbacks(void* callback)
|
|
{
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE Debugger_FullReportMemory()
|
|
{
|
|
//WdAllocTest();
|
|
ShowMemoryUsage();
|
|
BfFullReportMemory();
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE Debugger_Delete()
|
|
{
|
|
delete gDebugManager;
|
|
gDebugManager = NULL;
|
|
|
|
delete gPerfManager;
|
|
gPerfManager = NULL;
|
|
|
|
//OutputDebugStrF("Deleting Debugger\n");
|
|
//BfReportMemory();
|
|
|
|
#ifdef BF_PLATFORM_WINDOWS
|
|
gBgTrackingAllocs = false;
|
|
#endif
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE IDEHelper_ProgramStart()
|
|
{
|
|
BfIRCodeGen::StaticInit();
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE IDEHelper_ProgramDone()
|
|
{
|
|
//TODO:
|
|
//::MessageBoxA(NULL, "Done", "Done", MB_OK);
|
|
|
|
BF_ASSERT(gDebugger == NULL);
|
|
|
|
//ShowMemoryUsage();
|
|
//BfFullReportMemory();
|
|
|
|
#ifdef CAPTURE_ALLOC_SOURCES
|
|
gInsideAlloc = true;
|
|
for (int i = 0; i < CAPTURE_ALLOC_POOL_SIZE; i++)
|
|
{
|
|
if (gHashCaptureAllocSize[i] != NULL)
|
|
{
|
|
free(gHashCaptureAllocSize[i]->mSymName);
|
|
delete gHashCaptureAllocSize[i];
|
|
gHashCaptureAllocSize[i] = NULL;
|
|
}
|
|
}
|
|
gBfCaptureSourceAllocMap.clear();
|
|
#endif
|
|
|
|
#ifdef BF_PLATFORM_WINDOWS
|
|
_CrtMemDumpAllObjectsSince(&gStartMemCheckpoint);
|
|
|
|
/*_CrtMemState curMemCheckpoint;
|
|
_CrtMemCheckpoint(&curMemCheckpoint);
|
|
|
|
_CrtMemState memDiff;
|
|
if (_CrtMemDifference(&memDiff, &gStartMemCheckpoint, &curMemCheckpoint))
|
|
_CrtMemDumpStatistics(&memDiff);*/
|
|
|
|
_CrtMemState curMemCheckpoint = { 0 };
|
|
_CrtMemCheckpoint(&curMemCheckpoint);
|
|
OutputDebugStrF("Heap memory usage: %dk\n", curMemCheckpoint.lTotalCount / 1024);
|
|
#endif //BF_PLATFORM_WINDOWS
|
|
|
|
BpShutdown();
|
|
}
|
|
|
|
BF_EXPORT int BF_CALLTYPE Debugger_GetAddrSize()
|
|
{
|
|
if (gDebugger == NULL)
|
|
return 0;
|
|
return gDebugger->GetAddrSize();
|
|
}
|
|
|
|
BF_EXPORT bool BF_CALLTYPE Debugger_OpenFile(const char* launchPath, const char* targetPath, const char* args, const char* workingDir, void* envBlockPtr, int envBlockSize, bool hotSwapEnabled, DbgOpenFileFlags openFileFlags)
|
|
{
|
|
BF_ASSERT(gDebugger == NULL);
|
|
|
|
if (!FileExists(launchPath))
|
|
{
|
|
gDebugManager->mOutMessages.push_back(StrFormat("error Unable to locate specified launch target '%s'", launchPath));
|
|
return false;
|
|
}
|
|
|
|
DebuggerResult debuggerResult = DebuggerResult_Ok;
|
|
if ((gDebugManager->mDebugger64 != NULL) && (gDebugManager->mDebugger64->CanOpen(launchPath, &debuggerResult)))
|
|
gDebugger = gDebugManager->mDebugger64;
|
|
else
|
|
gDebugger = gDebugManager->mDebugger32;
|
|
|
|
if (gDebugger == NULL)
|
|
{
|
|
if (debuggerResult == DebuggerResult_WrongBitSize)
|
|
gDebugManager->mOutMessages.push_back(StrFormat("error The file 32-bit file '%s' cannot be debugged because 32-bit debugger has been disabled", launchPath));
|
|
return false;
|
|
}
|
|
|
|
Array<uint8> envBlock;
|
|
if (envBlockPtr != NULL)
|
|
{
|
|
if (envBlockSize != 0)
|
|
envBlock.Insert(0, (uint8*)envBlockPtr, envBlockSize);
|
|
}
|
|
|
|
gDebugger->OpenFile(launchPath, targetPath, args, workingDir, envBlock, hotSwapEnabled, openFileFlags);
|
|
return true;
|
|
}
|
|
|
|
BF_EXPORT bool BF_CALLTYPE Debugger_ComptimeAttach(void* bfCompiler)
|
|
{
|
|
gDebugger = new CeDebugger(gDebugManager, (BfCompiler*)bfCompiler);
|
|
return true;
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE Debugger_SetSymSrvOptions(const char* symCacheDir, const char* symSrvStr, int flags)
|
|
{
|
|
Array<String> symServers;
|
|
|
|
const char* startStr = symSrvStr;
|
|
for (const char* cPtr = symSrvStr; true; cPtr++)
|
|
{
|
|
if ((*cPtr == '\n') || (*cPtr == 0))
|
|
{
|
|
String symStr = String(startStr, cPtr - startStr);
|
|
symStr.Trim();
|
|
if (symStr.EndsWith('/'))
|
|
symStr.Remove((int)symStr.length() - 1, 1);
|
|
if (!symStr.IsEmpty())
|
|
symServers.Add(symStr);
|
|
startStr = cPtr;
|
|
}
|
|
|
|
if (*cPtr == 0)
|
|
break;
|
|
}
|
|
|
|
AutoCrit autoCrit(gDebugManager->mCritSect);
|
|
|
|
gDebugManager->mSymSrvOptions.mCacheDir = symCacheDir;
|
|
gDebugManager->mSymSrvOptions.mSymbolServers = symServers;
|
|
gDebugManager->mSymSrvOptions.mFlags = (BfSymSrvFlags)flags;
|
|
|
|
gDebugManager->mSymSrvOptions.mCacheDir.Trim();
|
|
if (gDebugManager->mSymSrvOptions.mCacheDir.IsEmpty())
|
|
gDebugManager->mSymSrvOptions.mFlags = BfSymSrvFlag_Disable;
|
|
|
|
if (flags & BfSymSrvFlag_TempCache)
|
|
{
|
|
if (!gDebugManager->mSymSrvOptions.mCacheDir.IsEmpty())
|
|
{
|
|
gDebugManager->mSymSrvOptions.mCacheDir.Append("\\temp");
|
|
RecursiveDeleteDirectory(gDebugManager->mSymSrvOptions.mCacheDir);
|
|
}
|
|
}
|
|
|
|
gDebugManager->SetSourceServerCacheDir();
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE Debugger_SetSourcePathRemap(const char* remapStr)
|
|
{
|
|
AutoCrit autoCrit(gDebugManager->mCritSect);
|
|
|
|
gDebugManager->mSourcePathRemap.Clear();
|
|
|
|
const char* startStr = remapStr;
|
|
for (const char* cPtr = remapStr; true; cPtr++)
|
|
{
|
|
if ((*cPtr == '\n') || (*cPtr == 0))
|
|
{
|
|
String remapStr = String(startStr, cPtr - startStr);
|
|
remapStr.Trim();
|
|
|
|
int eqPos = (int)remapStr.IndexOf('=');
|
|
if (eqPos != -1)
|
|
{
|
|
auto keyStr = remapStr.Substring(0, eqPos);
|
|
keyStr.Trim();
|
|
auto valueStr = remapStr.Substring(eqPos + 1);
|
|
valueStr.Trim();
|
|
gDebugManager->mSourcePathRemap[keyStr] = valueStr;
|
|
}
|
|
|
|
startStr = cPtr;
|
|
}
|
|
|
|
if (*cPtr == 0)
|
|
break;
|
|
}
|
|
}
|
|
|
|
BF_EXPORT bool BF_CALLTYPE Debugger_OpenMiniDump(const char* fileName)
|
|
{
|
|
#ifdef BF_PLATFORM_WINDOWS
|
|
DbgMiniDump* dbgMiniDump = new DbgMiniDump();
|
|
bool result = dbgMiniDump->StartLoad(fileName);
|
|
if (!result)
|
|
{
|
|
delete dbgMiniDump;
|
|
return false;
|
|
}
|
|
|
|
if (dbgMiniDump->GetTargetBitCount() == 32)
|
|
gDebugger = CreateDebugger32(gDebugManager, dbgMiniDump);
|
|
else
|
|
gDebugger = CreateDebugger64(gDebugManager, dbgMiniDump);
|
|
|
|
return result;
|
|
#else //BF_PLATFORM_WINDOWS
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
BF_EXPORT bool BF_CALLTYPE Debugger_Attach(int processId, BfDbgAttachFlags attachFlags)
|
|
{
|
|
BF_ASSERT(gDebugger == NULL);
|
|
|
|
if (gDebugManager->mDebugger64->Attach(processId, attachFlags))
|
|
{
|
|
gDebugger = gDebugManager->mDebugger64;
|
|
return true;
|
|
}
|
|
|
|
if (gDebugManager->mDebugger32->Attach(processId, attachFlags))
|
|
{
|
|
gDebugger = gDebugManager->mDebugger32;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
BF_EXPORT void Debugger_GetStdHandles(BfpFile** outStdIn, BfpFile** outStdOut, BfpFile** outStdErr)
|
|
{
|
|
if (gDebugger != NULL)
|
|
gDebugger->GetStdHandles(outStdIn, outStdOut, outStdErr);
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE Debugger_Run()
|
|
{
|
|
gDebugger->Run();
|
|
}
|
|
|
|
BF_EXPORT bool BF_CALLTYPE Debugger_HotLoad(const char* fileNamesStr, int hotIdx)
|
|
{
|
|
//DbgModule* dwarf = new DbgModule(gDebugger);
|
|
//dwarf->ReadPE(fileName);
|
|
|
|
Array<String> fileNames;
|
|
const char* curPtr = fileNamesStr;
|
|
for (int i = 0; true; i++)
|
|
{
|
|
if ((fileNamesStr[i] == '\0') || (fileNamesStr[i] == '\n'))
|
|
{
|
|
String curFileName = String(curPtr, fileNamesStr + i);
|
|
|
|
if ((curFileName.IndexOf("/vdata.") != -1) || (curFileName.IndexOf("\\vdata.") != -1))
|
|
{
|
|
// Do vdata first - so new data and special functions don't have to be deferred resolved
|
|
fileNames.Insert(0, curFileName);
|
|
}
|
|
else
|
|
fileNames.Add(curFileName);
|
|
curPtr = fileNamesStr + i + 1;
|
|
}
|
|
|
|
if (fileNamesStr[i] == '\0')
|
|
break;
|
|
}
|
|
|
|
gDebugger->HotLoad(fileNames, hotIdx);
|
|
|
|
return true;
|
|
}
|
|
|
|
BF_EXPORT bool BF_CALLTYPE Debugger_LoadDebugVisualizers(const char* fileName)
|
|
{
|
|
String fn = fileName;
|
|
bool worked = false;
|
|
worked = gDebugManager->mDebugVisualizers->Load(fileName);
|
|
if (!gDebugManager->mDebugVisualizers->mErrorString.empty())
|
|
{
|
|
gDebugManager->mOutMessages.push_back(StrFormat("msg ERROR: %s\n", gDebugManager->mDebugVisualizers->mErrorString.c_str()));
|
|
}
|
|
|
|
// {
|
|
// BF_FATAL(gDebugManager->mDebugVisualizers->mErrorString.c_str());
|
|
// }
|
|
return worked;
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE Debugger_StopDebugging()
|
|
{
|
|
gDebugger->StopDebugging();
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE Debugger_Terminate()
|
|
{
|
|
gDebugger->Terminate();
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE Debugger_Detach()
|
|
{
|
|
gDebugManager->mNetManager->CancelAll();
|
|
gDebugger->Detach();
|
|
if (gDebugger->IsOnDemandDebugger())
|
|
delete gDebugger;
|
|
gDebugger = NULL;
|
|
gDebugManager->mNetManager->Clear();
|
|
}
|
|
|
|
BF_EXPORT Breakpoint* BF_CALLTYPE Debugger_CreateBreakpoint(const char* fileName, int lineNum, int wantColumn, int instrOffset)
|
|
{
|
|
return gDebugger->CreateBreakpoint(fileName, lineNum, wantColumn, instrOffset);
|
|
}
|
|
|
|
BF_EXPORT Breakpoint* BF_CALLTYPE Debugger_CreateMemoryBreakpoint(intptr address, int byteCount)
|
|
{
|
|
return gDebugger->CreateMemoryBreakpoint(address, byteCount);
|
|
}
|
|
|
|
BF_EXPORT Breakpoint* BF_CALLTYPE Debugger_CreateSymbolBreakpoint(const char* symbolName)
|
|
{
|
|
return gDebugger->CreateSymbolBreakpoint(symbolName);
|
|
}
|
|
|
|
BF_EXPORT Breakpoint* BF_CALLTYPE Debugger_CreateAddressBreakpoint(intptr address)
|
|
{
|
|
return gDebugger->CreateAddressBreakpoint(address);
|
|
}
|
|
|
|
BF_EXPORT Breakpoint* BF_CALLTYPE Debugger_GetActiveBreakpoint()
|
|
{
|
|
return gDebugger->GetActiveBreakpoint();
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE Breakpoint_Delete(Breakpoint* wdBreakpoint)
|
|
{
|
|
gDebugger->DeleteBreakpoint(wdBreakpoint);
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE Breakpoint_Check(Breakpoint* breakpoint)
|
|
{
|
|
gDebugger->CheckBreakpoint(breakpoint);
|
|
}
|
|
|
|
BF_EXPORT int BF_CALLTYPE Breakpoint_GetPendingHotBindIdx(Breakpoint* breakpoint)
|
|
{
|
|
return breakpoint->mPendingHotBindIdx;
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE Breakpoint_HotBindBreakpoint(Breakpoint* breakpoint, int lineNum, int hotIdx)
|
|
{
|
|
gDebugger->HotBindBreakpoint(breakpoint, lineNum, hotIdx);
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE Breakpoint_SetThreadId(Breakpoint* breakpoint, intptr threadId)
|
|
{
|
|
BfLogDbg("Breakpoint %p set ThreadId=%d\n", breakpoint, threadId);
|
|
breakpoint->mThreadId = threadId;
|
|
gDebugger->CheckBreakpoint(breakpoint);
|
|
}
|
|
|
|
BF_EXPORT int BF_CALLTYPE Breakpoint_GetHitCount(Breakpoint* breapoint)
|
|
{
|
|
return breapoint->mHitCount;
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE Breakpoint_ClearHitCount(Breakpoint* breapoint)
|
|
{
|
|
breapoint->mHitCount = 0;
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE Breakpoint_SetHitCountTarget(Breakpoint* breakpoint, int targetHitCount, DbgHitCountBreakKind breakKind)
|
|
{
|
|
breakpoint->mTargetHitCount = targetHitCount;
|
|
breakpoint->mHitCountBreakKind = breakKind;
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE Breakpoint_SetCondition(Breakpoint* wdBreakpoint, const char* condition)
|
|
{
|
|
gDebugger->SetBreakpointCondition(wdBreakpoint, condition);
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE Breakpoint_SetLogging(Breakpoint* wdBreakpoint, const char* logging, bool breakAfterLogging)
|
|
{
|
|
gDebugger->SetBreakpointLogging(wdBreakpoint, logging, breakAfterLogging);
|
|
}
|
|
|
|
BF_EXPORT uintptr BF_CALLTYPE Breakpoint_GetAddress(Breakpoint* wdBreakpoint, Breakpoint** outLinkedSibling)
|
|
{
|
|
if (outLinkedSibling != NULL)
|
|
*outLinkedSibling = wdBreakpoint->mLinkedSibling;
|
|
return gDebugger->GetBreakpointAddr(wdBreakpoint);
|
|
}
|
|
|
|
BF_EXPORT bool BF_CALLTYPE Breakpoint_IsMemoryBreakpointBound(Breakpoint* wdBreakpoint)
|
|
{
|
|
return wdBreakpoint->IsMemoryBreakpointBound();
|
|
}
|
|
|
|
BF_EXPORT intptr BF_CALLTYPE Breakpoint_GetLineNum(Breakpoint* wdBreakpoint)
|
|
{
|
|
return wdBreakpoint->mLineNum;
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE Breakpoint_Move(Breakpoint* breakpoint, int lineNum, int wantColumn, bool rebindNow)
|
|
{
|
|
gDebugger->MoveBreakpoint(breakpoint, lineNum, wantColumn, rebindNow);
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE Breakpoint_MoveMemoryBreakpoint(Breakpoint* breakpoint, intptr addr, int byteCount)
|
|
{
|
|
gDebugger->MoveMemoryBreakpoint(breakpoint, addr, byteCount);
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE Breakpoint_Disable(Breakpoint* wdBreakpoint)
|
|
{
|
|
gDebugger->DisableBreakpoint(wdBreakpoint);
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE Debugger_CreateStepFilter(const char* filter, bool isGlobal, BfStepFilterKind filterKind)
|
|
{
|
|
AutoCrit autoCrit(gDebugManager->mCritSect);
|
|
StepFilter stepFilter;
|
|
stepFilter.mFilterKind = filterKind;
|
|
gDebugManager->mStepFilters[filter] = stepFilter;
|
|
gDebugManager->mStepFilterVersion++;
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE StepFilter_Delete(const char* filter)
|
|
{
|
|
AutoCrit autoCrit(gDebugManager->mCritSect);
|
|
bool didRemove = gDebugManager->mStepFilters.Remove(filter);
|
|
BF_ASSERT(didRemove);
|
|
|
|
gDebugManager->mStepFilterVersion++;
|
|
}
|
|
|
|
BF_EXPORT int BF_CALLTYPE Debugger_GetRunState()
|
|
{
|
|
AutoCrit autoCrit(gDebugManager->mCritSect);
|
|
if (gDebugger == NULL)
|
|
return RunState_NotStarted;
|
|
return gDebugger->mRunState;
|
|
}
|
|
|
|
BF_EXPORT bool Debugger_HasLoadedTargetBinary()
|
|
{
|
|
AutoCrit autoCrit(gDebugManager->mCritSect);
|
|
if (gDebugger == NULL)
|
|
return false;
|
|
return gDebugger->HasLoadedTargetBinary();
|
|
}
|
|
|
|
BF_EXPORT bool BF_CALLTYPE Debugger_HasPendingDebugLoads()
|
|
{
|
|
if (gDebugger == NULL)
|
|
return false;
|
|
return gDebugger->HasPendingDebugLoads();
|
|
}
|
|
|
|
BF_EXPORT const char* BF_CALLTYPE Debugger_PopMessage()
|
|
{
|
|
AutoCrit autoCrit(gDebugManager->mCritSect);
|
|
if (gDebugManager->mOutMessages.size() == 0)
|
|
return NULL;
|
|
String& outString = *gTLStrReturn.Get();
|
|
outString = gDebugManager->mOutMessages.front();
|
|
gDebugManager->mOutMessages.pop_front();
|
|
//gDebugManager->mOutMessages.erase(gDebugManager->mOutMessages.begin());
|
|
return outString.c_str();
|
|
}
|
|
|
|
BF_EXPORT bool BF_CALLTYPE Debugger_HasMessages()
|
|
{
|
|
AutoCrit autoCrit(gDebugManager->mCritSect);
|
|
return gDebugManager->mOutMessages.size() != 0;
|
|
}
|
|
|
|
BF_EXPORT const char* BF_CALLTYPE Debugger_GetCurrentException()
|
|
{
|
|
/*outString = StrFormat("Exception at 0x%p, exception code 0x%08X",
|
|
gDebugger->mCurException.ExceptionAddress, gDebugger->mCurException.ExceptionCode);*/
|
|
|
|
String& outString = *gTLStrReturn.Get();
|
|
outString = gDebugger->GetCurrentException();
|
|
return outString.c_str();
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE Debugger_BreakAll()
|
|
{
|
|
if (gDebugger != NULL)
|
|
gDebugger->BreakAll();
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE Debugger_Continue()
|
|
{
|
|
BfLogDbg("Debugger_Continue\n");
|
|
gDebugger->ContinueDebugEvent();
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE Debugger_StepInto(bool inAssembly)
|
|
{
|
|
gDebugger->StepInto(inAssembly);
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE Debugger_StepIntoSpecific(intptr addr)
|
|
{
|
|
gDebugger->StepIntoSpecific(addr);
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE Debugger_StepOver(bool inAssembly)
|
|
{
|
|
gDebugger->StepOver(inAssembly);
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE Debugger_StepOut(bool inAssembly)
|
|
{
|
|
gDebugger->StepOut(inAssembly);
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE Debugger_SetNextStatement(bool inAssembly, const char* fileName, int64 wantLineNumOrAsmAddr, int wantColumn)
|
|
{
|
|
if (fileName == NULL)
|
|
fileName = "";
|
|
gDebugger->SetNextStatement(inAssembly, fileName, wantLineNumOrAsmAddr, wantColumn);
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE Debugger_Update()
|
|
{
|
|
if (gDebugger != NULL)
|
|
gDebugger->Update();
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE Debugger_SetDisplayTypes(const char* referenceId, const char* formatStr, int8 intDisplayType, int8 mmDisplayType, int8 floatDisplayType)
|
|
{
|
|
AutoCrit autoCrit(gDebugManager->mCritSect);
|
|
|
|
DwDisplayInfo* displayInfo = NULL;
|
|
if (referenceId == NULL)
|
|
displayInfo = &gDebugManager->mDefaultDisplayInfo;
|
|
else
|
|
gDebugManager->mDisplayInfos.TryAdd(referenceId, NULL, &displayInfo);
|
|
|
|
if (formatStr != NULL)
|
|
displayInfo->mFormatStr = formatStr;
|
|
displayInfo->mIntDisplayType = (DwIntDisplayType)intDisplayType;
|
|
displayInfo->mMmDisplayType = (DwMmDisplayType)mmDisplayType;
|
|
displayInfo->mFloatDisplayType = (DwFloatDisplayType)floatDisplayType;
|
|
|
|
if ((referenceId != NULL) &&
|
|
(displayInfo->mFormatStr.IsEmpty()) &&
|
|
(displayInfo->mIntDisplayType == DwIntDisplayType_Default) &&
|
|
(displayInfo->mMmDisplayType == DwMmDisplayType_Default) &&
|
|
(displayInfo->mFloatDisplayType == DwFloatDisplayType_Default))
|
|
{
|
|
gDebugManager->mDisplayInfos.Remove(referenceId);
|
|
}
|
|
}
|
|
|
|
BF_EXPORT const char* BF_CALLTYPE Debugger_GetDisplayTypes(const char* referenceId, int8* intDisplayType, int8* mmDisplayType, int8* floatDisplayType, bool* foundSpecific)
|
|
{
|
|
AutoCrit autoCrit(gDebugManager->mCritSect);
|
|
|
|
*foundSpecific = false;
|
|
DwDisplayInfo* displayInfo = &gDebugManager->mDefaultDisplayInfo;
|
|
if (referenceId != NULL)
|
|
{
|
|
/*auto itr = gDebugManager->mDisplayInfos.find(referenceId);
|
|
if (itr != gDebugManager->mDisplayInfos.end())
|
|
{
|
|
displayInfo = &itr->second;
|
|
foundSpecific = true;
|
|
}*/
|
|
|
|
if (gDebugManager->mDisplayInfos.TryGetValue(referenceId, &displayInfo))
|
|
{
|
|
*foundSpecific = true;
|
|
}
|
|
}
|
|
|
|
*intDisplayType = (int8)displayInfo->mIntDisplayType;
|
|
*mmDisplayType = (int8)displayInfo->mMmDisplayType;
|
|
*floatDisplayType = (int8)displayInfo->mFloatDisplayType;
|
|
return displayInfo->mFormatStr.c_str();
|
|
}
|
|
|
|
BF_EXPORT const char* BF_CALLTYPE Debugger_GetDisplayTypeNames()
|
|
{
|
|
AutoCrit autoCrit(gDebugManager->mCritSect);
|
|
|
|
String& outString = *gTLStrReturn.Get();
|
|
outString.clear();
|
|
for (auto& displayInfoEntry : gDebugManager->mDisplayInfos)
|
|
{
|
|
outString += displayInfoEntry.mKey + "\n";
|
|
}
|
|
return outString.c_str();
|
|
}
|
|
|
|
BF_EXPORT const char* BF_CALLTYPE Debugger_EvaluateContinue()
|
|
{
|
|
auto debugger = gDebugger;
|
|
|
|
String& outString = *gTLStrReturn.Get();
|
|
outString = debugger->EvaluateContinue();
|
|
return outString.c_str();
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE Debugger_EvaluateContinueKeep()
|
|
{
|
|
auto debugger = gDebugger;
|
|
debugger->EvaluateContinueKeep();
|
|
}
|
|
|
|
BF_EXPORT StringView BF_CALLTYPE Debugger_Evaluate(const char* expr, int callStackIdx, int cursorPos, int32 language, uint16 expressionFlags)
|
|
{
|
|
auto debugger = gDebugger;
|
|
|
|
if (debugger == NULL)
|
|
debugger = gDebugManager->mDebugger64;
|
|
|
|
String& outString = *gTLStrReturn.Get();
|
|
outString.clear();
|
|
outString = debugger->Evaluate(expr, callStackIdx, cursorPos, language, (DwEvalExpressionFlags)expressionFlags);
|
|
#ifdef BF_WANTS_LOG_DBG
|
|
{
|
|
int crPos = (int)outString.IndexOf('\n');
|
|
if (crPos != -1)
|
|
BfLogDbg("Debugger_Evaluate Result=%s\n", outString.Substring(0, crPos).c_str());
|
|
else
|
|
BfLogDbg("Debugger_Evaluate Result=%s\n", outString.c_str());
|
|
}
|
|
#endif
|
|
return outString;
|
|
}
|
|
|
|
BF_EXPORT const char* BF_CALLTYPE Debugger_EvaluateToAddress(const char* expr, int callStackIdx, int cursorPos)
|
|
{
|
|
String& outString = *gTLStrReturn.Get();
|
|
outString.clear();
|
|
if (gDebugger != NULL)
|
|
outString = gDebugger->EvaluateToAddress(expr, callStackIdx, cursorPos);
|
|
return outString.c_str();
|
|
}
|
|
|
|
BF_EXPORT const char* BF_CALLTYPE Debugger_EvaluateAtAddress(const char* expr, intptr atAddr, int cursorPos)
|
|
{
|
|
String& outString = *gTLStrReturn.Get();
|
|
outString.clear();
|
|
if (gDebugger != NULL)
|
|
outString = gDebugger->EvaluateAtAddress(expr, atAddr, cursorPos);
|
|
return outString.c_str();
|
|
}
|
|
|
|
BF_EXPORT const char* BF_CALLTYPE Debugger_GetAutoExpressions(int callStackIdx, uint64 memoryRangeStart, uint64 memoryRangeLen)
|
|
{
|
|
String& outString = *gTLStrReturn.Get();
|
|
outString = gDebugger->GetAutoExpressions(callStackIdx, memoryRangeStart, memoryRangeLen);
|
|
return outString.c_str();
|
|
}
|
|
|
|
BF_EXPORT const char* BF_CALLTYPE Debugger_GetAutoLocals(int callStackIdx, bool showRegs)
|
|
{
|
|
String& outString = *gTLStrReturn.Get();
|
|
outString = gDebugger->GetAutoLocals(callStackIdx, showRegs);
|
|
return outString.c_str();
|
|
}
|
|
|
|
BF_EXPORT const char* BF_CALLTYPE Debugger_CompactChildExpression(const char* expr, const char* parentExpr, int callStackIdx)
|
|
{
|
|
String& outString = *gTLStrReturn.Get();
|
|
outString = gDebugger->CompactChildExpression(expr, parentExpr, callStackIdx);
|
|
return outString.c_str();
|
|
}
|
|
|
|
BF_EXPORT const char* BF_CALLTYPE Debugger_GetCollectionContinuation(const char* continuationData, int callStackIdx, int count)
|
|
{
|
|
String& outString = *gTLStrReturn.Get();
|
|
outString = gDebugger->GetCollectionContinuation(continuationData, callStackIdx, count);
|
|
return outString.c_str();
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE Debugger_ForegroundTarget(int altProcessId)
|
|
{
|
|
gDebugger->ForegroundTarget(altProcessId);
|
|
|
|
//BOOL worked = EnumThreadWindows(gDebugger->mProcessInfo.dwThreadId, WdEnumWindowsProc, 0);
|
|
//BF_ASSERT(worked);
|
|
}
|
|
|
|
BF_EXPORT const char* BF_CALLTYPE Debugger_GetProcessInfo()
|
|
{
|
|
String& outString = *gTLStrReturn.Get();
|
|
outString = gDebugger->GetProcessInfo();
|
|
return outString.c_str();
|
|
}
|
|
|
|
BF_EXPORT int BF_CALLTYPE Debugger_GetProcessId()
|
|
{
|
|
return gDebugger->GetProcessId();
|
|
}
|
|
|
|
BF_EXPORT const char* BF_CALLTYPE Debugger_GetThreadInfo()
|
|
{
|
|
String& outString = *gTLStrReturn.Get();
|
|
outString = gDebugger->GetThreadInfo();
|
|
return outString.c_str();
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE Debugger_SetActiveThread(int threadId)
|
|
{
|
|
gDebugger->SetActiveThread(threadId);
|
|
}
|
|
|
|
BF_EXPORT int BF_CALLTYPE Debugger_GetActiveThread()
|
|
{
|
|
return gDebugger->GetActiveThread();
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE Debugger_FreezeThread(int threadId)
|
|
{
|
|
gDebugger->FreezeThread(threadId);
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE Debugger_ThawThread(int threadId)
|
|
{
|
|
gDebugger->ThawThread(threadId);
|
|
}
|
|
|
|
BF_EXPORT bool BF_CALLTYPE Debugger_IsActiveThreadWaiting()
|
|
{
|
|
return gDebugger->IsActiveThreadWaiting();
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE CallStack_Update()
|
|
{
|
|
gDebugger->UpdateCallStack();
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE CallStack_Rehup()
|
|
{
|
|
AutoCrit autoCrit(gDebugManager->mCritSect);
|
|
gDebugger->ClearCallStack();
|
|
}
|
|
|
|
BF_EXPORT int BF_CALLTYPE CallStack_GetCount()
|
|
{
|
|
return gDebugger->GetCallStackCount();
|
|
}
|
|
|
|
BF_EXPORT int BF_CALLTYPE CallStack_GetRequestedStackFrameIdx()
|
|
{
|
|
return gDebugger->GetRequestedStackFrameIdx();
|
|
}
|
|
|
|
BF_EXPORT int BF_CALLTYPE CallStack_GetBreakStackFrameIdx()
|
|
{
|
|
return gDebugger->GetBreakStackFrameIdx();
|
|
}
|
|
|
|
BF_EXPORT const char* BF_CALLTYPE CallStack_GetStackFrameInfo(int stackFrameIdx, intptr* addr, const char** outFile, int32* outHotIdx, int32* outDefLineStart, int32* outDefLineEnd,
|
|
int32* outLine, int32* outColumn, int32* outLanguage, int32* outStackSize, int8* outFlags)
|
|
{
|
|
String& outString = *gTLStrReturn.Get();
|
|
String& outString2 = *gTLStrReturn2.Get();
|
|
|
|
outString = gDebugger->GetStackFrameInfo(stackFrameIdx, addr, &outString2, outHotIdx, outDefLineStart, outDefLineEnd, outLine, outColumn, outLanguage, outStackSize, outFlags);
|
|
*outFile = outString2.c_str();
|
|
return outString.c_str();
|
|
}
|
|
|
|
BF_EXPORT const char* BF_CALLTYPE CallStack_GetStackFrameId(int stackFrameIdx)
|
|
{
|
|
String& outString = *gTLStrReturn.Get();
|
|
outString = gDebugger->GetStackFrameId(stackFrameIdx);
|
|
return outString.c_str();
|
|
}
|
|
|
|
BF_EXPORT const char* BF_CALLTYPE Callstack_GetStackFrameOldFileInfo(int stackFrameIdx)
|
|
{
|
|
String& outString = *gTLStrReturn.Get();
|
|
outString = gDebugger->Callstack_GetStackFrameOldFileInfo(stackFrameIdx);
|
|
return outString.c_str();
|
|
}
|
|
|
|
// -1 = no jump, 0 = won't jump, 1 = will jump
|
|
BF_EXPORT int BF_CALLTYPE CallStack_GetJmpState(int stackFrameIdx)
|
|
{
|
|
return gDebugger->GetJmpState(stackFrameIdx);
|
|
}
|
|
|
|
BF_EXPORT intptr BF_CALLTYPE Debugger_GetStackFrameCalleeAddr(int stackFrameIdx)
|
|
{
|
|
return gDebugger->GetStackFrameCalleeAddr(stackFrameIdx);
|
|
}
|
|
|
|
BF_EXPORT const char* BF_CALLTYPE Debugger_GetCodeAddrInfo(intptr addr, intptr inlineCallAddr, int* outHotIdx, int* outDefLineStart, int* outDefLineEnd, int* outLine, int* outColumn)
|
|
{
|
|
String& outString = *gTLStrReturn.Get();
|
|
outString.clear();
|
|
gDebugger->GetCodeAddrInfo(addr, inlineCallAddr, &outString, outHotIdx, outDefLineStart, outDefLineEnd, outLine, outColumn);
|
|
return outString.c_str();
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE Debugger_GetStackAllocInfo(intptr addr, int* outThreadId, int* outStackIdx)
|
|
{
|
|
gDebugger->GetStackAllocInfo(addr, outThreadId, outStackIdx);
|
|
}
|
|
|
|
BF_EXPORT const char* BF_CALLTYPE CallStack_GetStackMethodOwner(int stackFrameIdx, int& language)
|
|
{
|
|
String& outString = *gTLStrReturn.Get();
|
|
outString = gDebugger->GetStackMethodOwner(stackFrameIdx, language);
|
|
return outString.c_str();
|
|
}
|
|
|
|
BF_EXPORT const char* BF_CALLTYPE Debugger_FindCodeAddresses(const char* fileName, int line, int column, bool allowAutoResolve)
|
|
{
|
|
String& outString = *gTLStrReturn.Get();
|
|
outString = gDebugger->FindCodeAddresses(fileName, line, column, allowAutoResolve);
|
|
return outString.c_str();
|
|
}
|
|
|
|
BF_EXPORT const char* BF_CALLTYPE Debugger_GetAddressSourceLocation(intptr address)
|
|
{
|
|
String& outString = *gTLStrReturn.Get();
|
|
if (gDebugger != NULL)
|
|
outString = gDebugger->GetAddressSourceLocation(address);
|
|
else
|
|
outString = "";
|
|
return outString.c_str();
|
|
}
|
|
|
|
BF_EXPORT const char* BF_CALLTYPE Debugger_GetAddressSymbolName(intptr address, bool demangle)
|
|
{
|
|
String& outString = *gTLStrReturn.Get();
|
|
if (gDebugger != NULL)
|
|
outString = gDebugger->GetAddressSymbolName(address, demangle);
|
|
else
|
|
outString = "";
|
|
return outString.c_str();
|
|
}
|
|
|
|
BF_EXPORT const char* BF_CALLTYPE Debugger_FindLineCallAddresses(intptr address)
|
|
{
|
|
String& outString = *gTLStrReturn.Get();
|
|
outString = gDebugger->FindLineCallAddresses(address);
|
|
return outString.c_str();
|
|
}
|
|
|
|
BF_EXPORT const char* BF_CALLTYPE Debugger_DisassembleAt(intptr address)
|
|
{
|
|
String& outString = *gTLStrReturn.Get();
|
|
outString = gDebugger->DisassembleAt(address);
|
|
return outString.c_str();
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE Debugger_ReadMemory(uintptr address, uintptr size, unsigned char* data)
|
|
{
|
|
if (gDebugger == NULL)
|
|
return;
|
|
gDebugger->ReadMemory(address, size, data);
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE Debugger_WriteMemory(uintptr address, uintptr size, unsigned char* data)
|
|
{
|
|
if (gDebugger == NULL)
|
|
return;
|
|
gDebugger->WriteMemory(address, data, size);
|
|
}
|
|
|
|
BF_EXPORT const char* BF_CALLTYPE Debugger_GetModulesInfo()
|
|
{
|
|
String& outString = *gTLStrReturn.Get();
|
|
outString = gDebugger->GetModulesInfo();
|
|
return outString.c_str();
|
|
}
|
|
|
|
BF_EXPORT const char* BF_CALLTYPE Debugger_GetModuleInfo(const char* moduleName)
|
|
{
|
|
String& outString = *gTLStrReturn.Get();
|
|
outString = gDebugger->GetModuleInfo(moduleName);
|
|
return outString.c_str();
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE Debugger_CancelSymSrv()
|
|
{
|
|
gDebugger->CancelSymSrv();
|
|
}
|
|
|
|
BF_EXPORT int BF_CALLTYPE Debugger_LoadImageForModuleWith(const char* moduleName, const char* debugFilePath) // 0 = No Change, 1 = Loaded, 2 = Loading in background
|
|
{
|
|
return gDebugger->LoadImageForModule(moduleName, debugFilePath);
|
|
}
|
|
|
|
BF_EXPORT int BF_CALLTYPE Debugger_LoadDebugInfoForModule(const char* moduleName) // 0 = No Change, 1 = Loaded, 2 = Loading in background
|
|
{
|
|
return gDebugger->LoadDebugInfoForModule(moduleName);
|
|
}
|
|
|
|
BF_EXPORT int BF_CALLTYPE Debugger_LoadDebugInfoForModuleWith(const char* moduleName, const char* debugFilePath) // 0 = No Change, 1 = Loaded, 2 = Loading in background
|
|
{
|
|
return gDebugger->LoadDebugInfoForModule(moduleName, debugFilePath);
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE Debugger_SetStepOverExternalFiles(bool stepOverExternalFiles)
|
|
{
|
|
gDebugManager->mStepOverExternalFiles = stepOverExternalFiles;
|
|
gDebugManager->mStepFilterVersion++;
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE BfLog_Log(char* str)
|
|
{
|
|
BfLog(str);
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE BfLog_LogDbg(char* str)
|
|
{
|
|
BfLogDbg(str);
|
|
}
|
|
|
|
BF_EXPORT Profiler* BF_CALLTYPE Debugger_StartProfiling(intptr threadId, char* desc, int sampleRate)
|
|
{
|
|
BF_ASSERT(sampleRate > 0);
|
|
Profiler* profiler = gDebugger->StartProfiling();
|
|
profiler->mTargetThreadId = threadId;
|
|
if (desc != NULL)
|
|
profiler->mDescription = desc;
|
|
profiler->mSamplesPerSecond = sampleRate;
|
|
profiler->Start();
|
|
return profiler;
|
|
}
|
|
|
|
BF_EXPORT Profiler* BF_CALLTYPE Debugger_PopProfiler()
|
|
{
|
|
Profiler* profiler = gDebugger->PopProfiler();
|
|
return profiler;
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE Debugger_InitiateHotResolve(int flags)
|
|
{
|
|
if (gDebugger != NULL)
|
|
gDebugger->InitiateHotResolve((DbgHotResolveFlags)flags);
|
|
}
|
|
|
|
BF_EXPORT intptr BF_CALLTYPE Debugger_GetDbgAllocHeapSize()
|
|
{
|
|
AutoCrit autoCrit(gDebugManager->mCritSect);
|
|
return gDebugger->GetDbgAllocHeapSize();
|
|
}
|
|
|
|
BF_EXPORT const char* BF_CALLTYPE Debugger_GetDbgAllocInfo()
|
|
{
|
|
AutoCrit autoCrit(gDebugManager->mCritSect);
|
|
|
|
String& outString = *gTLStrReturn.Get();
|
|
outString = gDebugger->GetDbgAllocInfo();
|
|
return outString.c_str();
|
|
}
|
|
|
|
BF_EXPORT const char* BF_CALLTYPE Debugger_GetHotResolveData(uint8* outTypeData, int* outTypeDataSize)
|
|
{
|
|
AutoCrit autoCrit(gDebugManager->mCritSect);
|
|
|
|
if (gDebugger->mHotResolveData == NULL)
|
|
{
|
|
*outTypeDataSize = -1;
|
|
return NULL;
|
|
}
|
|
|
|
int dataSize = (int)gDebugger->mHotResolveData->mTypeData.size();
|
|
if (*outTypeDataSize < dataSize)
|
|
{
|
|
*outTypeDataSize = dataSize;
|
|
return NULL;
|
|
}
|
|
|
|
*outTypeDataSize = dataSize;
|
|
if (dataSize > 0)
|
|
{
|
|
for (int i = 0; i < dataSize; i++)
|
|
outTypeData[i] = (gDebugger->mHotResolveData->mTypeData[i].mCount > 0) ? 1 : 0;
|
|
}
|
|
|
|
String& outString = *gTLStrReturn.Get();
|
|
outString.Clear();
|
|
|
|
for (auto& str : gDebugger->mHotResolveData->mBeefCallStackEntries)
|
|
{
|
|
if (!outString.IsEmpty())
|
|
outString += "\n";
|
|
outString += str;
|
|
}
|
|
|
|
return outString.c_str();
|
|
}
|
|
|
|
BF_EXPORT const char* BF_CALLTYPE Debugger_GetEmitSource(char* inFilePath)
|
|
{
|
|
AutoCrit autoCrit(gDebugManager->mCritSect);
|
|
|
|
String& outString = *gTLStrReturn.Get();
|
|
outString.Clear();
|
|
|
|
if (!gDebugger->GetEmitSource(inFilePath, outString))
|
|
return NULL;
|
|
|
|
return outString.c_str();
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE Debugger_SetOutputFilterFlags(int flags)
|
|
{
|
|
if (gDebugManager != NULL)
|
|
{
|
|
gDebugManager->SetOutputFilterFlags((BfOutputFilterFlags)flags);
|
|
}
|
|
}
|
|
|
|
BF_EXPORT int BF_CALLTYPE Debugger_GetOutputFilterFlags()
|
|
{
|
|
if (gDebugManager != NULL)
|
|
{
|
|
return (int)gDebugManager->GetOutputFilterFlags();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
BF_EXPORT NetResult* HTTP_GetFile(char* url, char* destPath)
|
|
{
|
|
AutoCrit autoCrit(gDebugManager->mNetManager->mThreadPool.mCritSect);
|
|
|
|
auto netResult = gDebugManager->mNetManager->QueueGet(url, destPath, false);
|
|
netResult->mDoneEvent = new SyncEvent();
|
|
return netResult;
|
|
}
|
|
|
|
BF_EXPORT int HTTP_GetResult(NetResult* netResult, int waitMS)
|
|
{
|
|
if (netResult->mDoneEvent->WaitFor(waitMS))
|
|
{
|
|
return netResult->mFailed ? 0 : 1;
|
|
}
|
|
else
|
|
{
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
BF_EXPORT void HTTP_GetLastError(NetResult* netResult, const char** error, int* errorLength)
|
|
{
|
|
*error = netResult->mError.GetPtr();
|
|
*errorLength = netResult->mError.GetLength();
|
|
}
|
|
|
|
BF_EXPORT void HTTP_Delete(NetResult* netResult)
|
|
{
|
|
if (!netResult->mDoneEvent->WaitFor(0))
|
|
{
|
|
///
|
|
{
|
|
AutoCrit autoCrit(gDebugManager->mNetManager->mThreadPool.mCritSect);
|
|
if (netResult->mCurRequest != NULL)
|
|
netResult->mCurRequest->Cancel();
|
|
}
|
|
netResult->mDoneEvent->WaitFor(-1);
|
|
}
|
|
delete netResult;
|
|
}
|
|
|
|
BF_EXPORT void Debugger_SetAliasPath(char* origPath, char* localPath)
|
|
{
|
|
gDebugger->SetAliasPath(origPath, localPath);
|
|
}
|
|
|
|
///
|
|
|
|
BF_EXPORT bool BF_CALLTYPE Profiler_IsRunning(Profiler* profiler)
|
|
{
|
|
return profiler->IsSampling();
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE Profiler_Stop(Profiler* profiler)
|
|
{
|
|
profiler->Stop();
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE Profiler_Clear(Profiler* profiler)
|
|
{
|
|
profiler->Clear();
|
|
}
|
|
|
|
BF_EXPORT const char* BF_CALLTYPE Profiler_GetOverview(Profiler* profiler)
|
|
{
|
|
String& outString = *gTLStrReturn.Get();
|
|
outString = profiler->GetOverview();
|
|
return outString.c_str();
|
|
}
|
|
|
|
BF_EXPORT const char* BF_CALLTYPE Profiler_GetThreadList(Profiler* profiler)
|
|
{
|
|
String& outString = *gTLStrReturn.Get();
|
|
outString = profiler->GetThreadList();
|
|
return outString.c_str();
|
|
}
|
|
|
|
BF_EXPORT const char* BF_CALLTYPE Profiler_GetCallTree(Profiler* profiler, int threadId, bool reverse)
|
|
{
|
|
String& outString = *gTLStrReturn.Get();
|
|
outString = profiler->GetCallTree(threadId, reverse);
|
|
return outString.c_str();
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE Profiler_Delete(Profiler* profiler)
|
|
{
|
|
int z = 0;
|
|
delete profiler;
|
|
}
|
|
|
|
BF_TLS_DECLSPEC static int gTLSValue = 3;
|
|
|
|
BF_EXPORT void BF_CALLTYPE TimeTest(uint32 startTime)
|
|
{
|
|
gTLSValue++;
|
|
|
|
int elapsedTime = BFTickCount() - startTime;
|
|
OutputDebugStrF("Load Time: %d\n", elapsedTime);
|
|
}
|
|
|
|
BF_EXPORT void BF_CALLTYPE BFTest()
|
|
{
|
|
struct DeferredResolveEntry2
|
|
{
|
|
BfFieldDef* mFieldDef;
|
|
int mTypeArrayIdx;
|
|
};
|
|
|
|
DeferredResolveEntry2 entry = { NULL, 333 };
|
|
|
|
llvm::SmallVector<DeferredResolveEntry2, 8> vec;
|
|
vec.push_back(DeferredResolveEntry2 { NULL, 111 } );
|
|
vec.push_back(DeferredResolveEntry2 { NULL, 222 } );
|
|
}
|
|
|
|
///
|
|
|
|
// __attribute__((weak))
|
|
// Debugger* Beefy::CreateDebugger32(DebugManager* debugManager, DbgMiniDump* miniDump)
|
|
// {
|
|
// return NULL;
|
|
// }
|