From a5b1ee8ab31ff40dcf71d0e8ceca00eb41d5ca09 Mon Sep 17 00:00:00 2001 From: M0n7y5 <17201053+M0n7y5@users.noreply.github.com> Date: Fri, 23 Oct 2026 23:59:26 +0200 Subject: [PATCH] Extract DbgTargetHost interface from WinDebugger DbgModule, DebugTarget and DbgExprEvaluator now reach the debugger only through DbgTargetHost, so they compile without WinDebugger.h and can be built on Linux (BF_DBG_HOST, off by default). Windows behaviour is unchanged. --- BeefySysLib/util/MappedFile.cpp | 45 ++ BeefySysLib/util/MappedFile.h | 19 +- BeefySysLib/util/MultiDictionary.h | 36 +- Debugger32/Debugger32.vcxproj | 2 + Debugger32/Debugger32.vcxproj.filters | 6 + Debugger64/Debugger64.vcxproj | 2 + Debugger64/Debugger64.vcxproj.filters | 6 + IDEHelper/CMakeLists.txt | 16 + IDEHelper/COFF.cpp | 43 +- IDEHelper/COFF.h | 4 +- IDEHelper/COFFData.h | 95 ++++ IDEHelper/DbgEvalSupport.cpp | 497 ++++++++++++++++++++ IDEHelper/DbgExprEvaluator.cpp | 33 +- IDEHelper/DbgExprEvaluator.h | 6 +- IDEHelper/DbgModule.cpp | 92 +++- IDEHelper/DbgModule.h | 17 +- IDEHelper/DbgTargetHost.h | 177 +++++++ IDEHelper/DbgTypeMap.h | 4 +- IDEHelper/DebugTarget.cpp | 48 +- IDEHelper/DebugTarget.h | 6 +- IDEHelper/MiniDumpDebugger.h | 2 +- IDEHelper/StrBloomMap.h | 2 +- IDEHelper/WinDebugger.cpp | 645 +++----------------------- IDEHelper/WinDebugger.h | 186 ++------ 24 files changed, 1166 insertions(+), 823 deletions(-) create mode 100644 IDEHelper/DbgEvalSupport.cpp create mode 100644 IDEHelper/DbgTargetHost.h diff --git a/BeefySysLib/util/MappedFile.cpp b/BeefySysLib/util/MappedFile.cpp index 102a44a81..a75edc16f 100644 --- a/BeefySysLib/util/MappedFile.cpp +++ b/BeefySysLib/util/MappedFile.cpp @@ -1,5 +1,13 @@ #include "MappedFile.h" +#ifndef BF_PLATFORM_WINDOWS +#include +#include +#include +#include +#include +#endif + USING_NS_BF; #ifdef BF_PLATFORM_WINDOWS @@ -43,4 +51,41 @@ bool MappedFile::Open(const StringImpl& fileName) return true; } +#else + +MappedFile::MappedFile() +{ + mData = NULL; + mFileSize = 0; +} + +MappedFile::~MappedFile() +{ + if (mData != NULL) + munmap(mData, mFileSize); +} + +bool MappedFile::Open(const StringImpl& fileName) +{ + mFileName = fileName; + int fd = open(fileName.c_str(), O_RDONLY); + if (fd == -1) + return false; + + struct stat fileStat; + if ((fstat(fd, &fileStat) != 0) || (fileStat.st_size <= 0) || (fileStat.st_size > INT_MAX)) + { + close(fd); + return false; + } + + mFileSize = (int)fileStat.st_size; + void* data = mmap(NULL, mFileSize, PROT_READ, MAP_PRIVATE, fd, 0); + close(fd); + if (data == MAP_FAILED) + return false; + mData = data; + return true; +} + #endif \ No newline at end of file diff --git a/BeefySysLib/util/MappedFile.h b/BeefySysLib/util/MappedFile.h index 42346c810..807a162d3 100644 --- a/BeefySysLib/util/MappedFile.h +++ b/BeefySysLib/util/MappedFile.h @@ -23,6 +23,23 @@ class MappedFile ~MappedFile(); }; -#endif //BF_PLATFORM_WINDOWS +#else + +class MappedFile +{ + BF_DISALLOW_COPY(MappedFile); +public: + String mFileName; + void* mData; + int mFileSize; + +public: + bool Open(const StringImpl& fileName); + + MappedFile(); + ~MappedFile(); +}; + +#endif NS_BF_END \ No newline at end of file diff --git a/BeefySysLib/util/MultiDictionary.h b/BeefySysLib/util/MultiDictionary.h index 2d1972255..e7a826ffa 100644 --- a/BeefySysLib/util/MultiDictionary.h +++ b/BeefySysLib/util/MultiDictionary.h @@ -171,10 +171,10 @@ class MultiDictionary : public TFuncs { while (true) { - MoveToNextHashMatch(); - if (*this == mDict->end()) + this->MoveToNextHashMatch(); + if (*this == this->mDict->end()) break; - if (mKey == GetKey()) + if (mKey == this->GetKey()) break; } return *this; @@ -212,7 +212,7 @@ class MultiDictionary : public TFuncs void ResizeEntries(int newSize) { BF_ASSERT(newSize >= mAllocSize); - Entry* newEntries = TFuncs::allocate(newSize); + Entry* newEntries = TFuncs::template allocate(newSize); for (int i = 0; i < mCount; i++) { @@ -309,7 +309,7 @@ class MultiDictionary : public TFuncs { if (this->mHashHeads == NULL) { - this->mHashHeads = TFuncs::allocate(mHashSize); + this->mHashHeads = TFuncs::template allocate(mHashSize); memset(this->mHashHeads, -1, sizeof(int) * mHashSize); } @@ -318,7 +318,7 @@ class MultiDictionary : public TFuncs int headEntry = this->mHashHeads[hashIdx]; Entry* newEntry = &mEntries[index]; - newEntry->mValue = T(); + newEntry->mValue = TValue(); newEntry->mNext = headEntry; newEntry->mHashCode = hash; @@ -331,7 +331,7 @@ class MultiDictionary : public TFuncs { if (this->mHashHeads == NULL) { - this->mHashHeads = TFuncs::allocate(mHashSize); + this->mHashHeads = TFuncs::template allocate(mHashSize); memset(this->mHashHeads, -1, sizeof(int) * mHashSize); } @@ -367,7 +367,7 @@ class MultiDictionary : public TFuncs void Rehash(int newHashSize) { - auto newHashHeads = TFuncs::allocate(newHashSize); + auto newHashHeads = TFuncs::template allocate(newHashSize); memset(newHashHeads, -1, sizeof(int) * newHashSize); if (mHashHeads != NULL) @@ -414,8 +414,8 @@ class MultiDictionary : public TFuncs } } - template - bool TryGet(const TKey& key, TKey* outKey, TValue* outValue) + template + bool TryGet(const TAltKey& key, TAltKey* outKey, TValue* outValue) { if (mHashHeads == NULL) return false; @@ -441,8 +441,8 @@ class MultiDictionary : public TFuncs return false; } - template - MatchIterator TryGet(const TKey& key) + template + MatchIterator TryGet(const TAltKey& key) { if (mHashHeads == NULL) return end(); @@ -468,14 +468,14 @@ class MultiDictionary : public TFuncs return end(); } - template - bool Contains(const TKey& key) + template + bool Contains(const TAltKey& key) { return TryGet(key) != end(); } - template - int GetCount(const TKey& key) + template + int GetCount(const TAltKey& key) { int count = 0; for (auto itr = TryGet(key); itr != end(); ++itr) @@ -483,8 +483,8 @@ class MultiDictionary : public TFuncs return count; } - template - bool Remove(const TKey& key) + template + bool Remove(const TAltKey& key) { if (mHashHeads == NULL) return false; diff --git a/Debugger32/Debugger32.vcxproj b/Debugger32/Debugger32.vcxproj index 2b28f6b87..6888afefa 100644 --- a/Debugger32/Debugger32.vcxproj +++ b/Debugger32/Debugger32.vcxproj @@ -24,6 +24,7 @@ + @@ -42,6 +43,7 @@ + diff --git a/Debugger32/Debugger32.vcxproj.filters b/Debugger32/Debugger32.vcxproj.filters index ab717c796..7b6fd6083 100644 --- a/Debugger32/Debugger32.vcxproj.filters +++ b/Debugger32/Debugger32.vcxproj.filters @@ -56,6 +56,9 @@ Source Files + + Source Files + Source Files @@ -96,6 +99,9 @@ Source Files + + Source Files + Source Files diff --git a/Debugger64/Debugger64.vcxproj b/Debugger64/Debugger64.vcxproj index 61040a7ce..8a3e46c6d 100644 --- a/Debugger64/Debugger64.vcxproj +++ b/Debugger64/Debugger64.vcxproj @@ -24,6 +24,7 @@ + @@ -44,6 +45,7 @@ + diff --git a/Debugger64/Debugger64.vcxproj.filters b/Debugger64/Debugger64.vcxproj.filters index aad8c11e8..48ebbb456 100644 --- a/Debugger64/Debugger64.vcxproj.filters +++ b/Debugger64/Debugger64.vcxproj.filters @@ -56,6 +56,9 @@ Source Files + + Source Files + Source Files @@ -101,6 +104,9 @@ Source Files + + Source Files + Source Files diff --git a/IDEHelper/CMakeLists.txt b/IDEHelper/CMakeLists.txt index 8c810cd74..4c0832868 100644 --- a/IDEHelper/CMakeLists.txt +++ b/IDEHelper/CMakeLists.txt @@ -203,6 +203,22 @@ if(UNIX AND NOT APPLE) endif() +option(BF_DBG_HOST "Build the Beef debug info and expression evaluation layer" OFF) + +if (BF_DBG_HOST AND NOT MSVC) + set(DBG_HOST_FILES + DbgModule.cpp + DebugTarget.cpp + DbgTypeMap.cpp + DbgExprEvaluator.cpp + DbgEvalSupport.cpp + DbgEvalPool.cpp + HotHeap.cpp + ) + set_source_files_properties(${DBG_HOST_FILES} PROPERTIES COMPILE_DEFINITIONS BF_DBG_64) + list(APPEND SRC_FILES ${DBG_HOST_FILES}) +endif() + # Add library to build. add_library(${PROJECT_NAME} STATIC ${SRC_FILES} diff --git a/IDEHelper/COFF.cpp b/IDEHelper/COFF.cpp index 841625751..a2a3553aa 100644 --- a/IDEHelper/COFF.cpp +++ b/IDEHelper/COFF.cpp @@ -297,7 +297,7 @@ COFF::~COFF() { BF_ASSERT(mTempBufIdx == 0); ClosePDB(); - mDebugger->mDbgSymSrv.ReleaseRequest(mDbgSymRequest); + GetWinDebugger()->mDbgSymSrv.ReleaseRequest(mDbgSymRequest); } const char* COFF::CvCheckTargetMatch(const char* name, bool& wasBeef) @@ -497,6 +497,11 @@ void COFF::InitCvTypes() CREATE_PRIMITIVE(T_REAL80, DbgType_Double, "double80", double); // This isn't correct } +WinDebugger* COFF::GetWinDebugger() +{ + return static_cast(mDebugger); +} + addr_target COFF::GetSectionAddr(uint16 section, uint32 offset) { if (section == 0) @@ -6133,7 +6138,7 @@ bool COFF::TryLoadPDB(const String& pdbPath, uint8 wantGuid[16], int32 wantAge) //OutputDebugStrF("COFF::TryLoadPDB %s\n", pdbPath.c_str()); if (!isVerifyOnly) - mDebugger->ModuleChanged(this); + GetWinDebugger()->ModuleChanged(this); mPDBLoaded = true; @@ -6193,13 +6198,13 @@ bool COFF::LoadPDB(const String& pdbPath, uint8 wantGuid[16], int32 wantAge) memcpy(mWantPDBGuid, wantGuid, 16); mWantAge = wantAge; - mDbgSymRequest = mDebugger->mDbgSymSrv.CreateRequest(mFilePath, pdbPath, wantGuid, wantAge); + mDbgSymRequest = GetWinDebugger()->mDbgSymSrv.CreateRequest(mFilePath, pdbPath, wantGuid, wantAge); mDbgSymRequest->SearchLocal(); if (!mDbgSymRequest->mFinalPDBPath.IsEmpty()) { TryLoadPDB(mDbgSymRequest->mFinalPDBPath, wantGuid, wantAge); - mDebugger->mDbgSymSrv.ReleaseRequest(mDbgSymRequest); + GetWinDebugger()->mDbgSymSrv.ReleaseRequest(mDbgSymRequest); mDbgSymRequest = NULL; } else @@ -6829,7 +6834,7 @@ void COFF::PreCacheImage() if (mOrigImageData != NULL) return; - mDebugger->mDbgSymSrv.PreCacheImage(mFilePath, mTimeStamp, mImageSize); + GetWinDebugger()->mDbgSymSrv.PreCacheImage(mFilePath, mTimeStamp, mImageSize); } void COFF::PreCacheDebugInfo() @@ -6844,7 +6849,7 @@ void COFF::PreCacheDebugInfo() mDbgSymRequest->SearchCache(); if (mDbgSymRequest->mFinalPDBPath.IsEmpty()) { - if (GetCurrentThreadId() == mDebugger->mDebuggerThreadId) + if (GetCurrentThreadId() == GetWinDebugger()->mDebuggerThreadId) { mDbgSymRequest->mIsPreCache = true; mDbgSymRequest->SearchSymSrv(); @@ -6897,21 +6902,21 @@ bool COFF::RequestImage() if (mOrigImageData != NULL) return false; - if (GetCurrentThreadId() == mDebugger->mDebuggerThreadId) + if (GetCurrentThreadId() == GetWinDebugger()->mDebuggerThreadId) { auto prevRunState = mDebugger->mRunState; mDebugger->mRunState = RunState_SearchingSymSrv; mDebugger->mDebugManager->mOutMessages.push_back(StrFormat("symsrv Searching for image '%s'", mFilePath.c_str())); - auto dbgSymRequest = mDebugger->mDbgSymSrv.CreateRequest(); - mDebugger->mActiveSymSrvRequest = dbgSymRequest; + auto dbgSymRequest = GetWinDebugger()->mDbgSymSrv.CreateRequest(); + GetWinDebugger()->mActiveSymSrvRequest = dbgSymRequest; BF_ASSERT(mDebugger->mDebugManager->mCritSect.mLockCount == 1); mDebugger->mDebugManager->mCritSect.Unlock(); // We unlock to allow the IDE to continue updating while we search String imagePath = dbgSymRequest->SearchForImage(mFilePath, mTimeStamp, mImageSize); mDebugger->mDebugManager->mCritSect.Lock(); - delete mDebugger->mActiveSymSrvRequest; - mDebugger->mActiveSymSrvRequest = NULL; + delete GetWinDebugger()->mActiveSymSrvRequest; + GetWinDebugger()->mActiveSymSrvRequest = NULL; mDebugger->mRunState = prevRunState; @@ -6940,18 +6945,18 @@ bool COFF::RequestDebugInfo(bool allowRemote) if (!allowRemote) return false; - if (GetCurrentThreadId() == mDebugger->mDebuggerThreadId) + if (GetCurrentThreadId() == GetWinDebugger()->mDebuggerThreadId) { auto prevRunState = mDebugger->mRunState; mDebugger->mRunState = RunState_SearchingSymSrv; mDbgSymRequest->mInProcess = true; - mDebugger->mActiveSymSrvRequest = mDbgSymRequest; + GetWinDebugger()->mActiveSymSrvRequest = mDbgSymRequest; BF_ASSERT(mDebugger->mDebugManager->mCritSect.mLockCount == 1); mDebugger->mDebugManager->mCritSect.Unlock(); mDbgSymRequest->SearchSymSrv(); mDebugger->mDebugManager->mCritSect.Lock(); - mDebugger->mActiveSymSrvRequest = NULL; + GetWinDebugger()->mActiveSymSrvRequest = NULL; mDbgSymRequest->mInProcess = false; mDebugger->mRunState = prevRunState; @@ -6963,7 +6968,7 @@ bool COFF::RequestDebugInfo(bool allowRemote) } if (!mDbgSymRequest->mFinalPDBPath.IsEmpty()) hasDebugInfo = TryLoadPDB(mDbgSymRequest->mFinalPDBPath, mDbgSymRequest->mWantGuid, mDbgSymRequest->mWantAge); - mDebugger->mDbgSymSrv.ReleaseRequest(mDbgSymRequest); + GetWinDebugger()->mDbgSymSrv.ReleaseRequest(mDbgSymRequest); mDbgSymRequest = NULL; return hasDebugInfo; } @@ -7099,7 +7104,7 @@ addr_target COFF::LocateSymbol(const StringImpl& name) jumpOp.mOpCode1 = 0x25; jumpOp.mRIPRel = 0; jumpOp.mTarget = entry->mValue->mAddress; - mDebugger->WriteMemory(hotAddr, jumpOp); + GetWinDebugger()->WriteMemory(hotAddr, jumpOp); callTarget = hotAddr; #endif @@ -7137,8 +7142,8 @@ addr_target COFF::LocateSymbol(const StringImpl& name) fileStream.mSize = libEntry->mLength; fileStream.SetPos(0); - DbgModule* dbgModule = new COFF(mDebugger->mDebugTarget); - dbgModule->mHotIdx = mDebugger->mActiveHotIdx; + DbgModule* dbgModule = new COFF(GetWinDebugger()->mDebugTarget); + dbgModule->mHotIdx = GetWinDebugger()->mActiveHotIdx; dbgModule->mFilePath = libEntry->mName + "@" + libEntry->mLibFile->mFilePath; bool success = dbgModule->ReadCOFF(&fileStream, DbgModuleKind_FromLocateSymbol); fileStream.mFP = NULL; @@ -7154,7 +7159,7 @@ addr_target COFF::LocateSymbol(const StringImpl& name) delete dbgModule; return 0; } - mDebugger->mDebugTarget->AddDbgModule(dbgModule); + GetWinDebugger()->mDebugTarget->AddDbgModule(dbgModule); auto symbolEntry = mSymbolNameMap.Find(name.c_str()); if (symbolEntry != NULL) diff --git a/IDEHelper/COFF.h b/IDEHelper/COFF.h index a403d9caf..33d963306 100644 --- a/IDEHelper/COFF.h +++ b/IDEHelper/COFF.h @@ -168,6 +168,7 @@ class CvModuleInfoNameEntry }; class COFF; +class WinDebugger; class CvStreamReader { @@ -361,7 +362,8 @@ class COFF : public DbgModule void InitCvTypes(); DbgType* CvCreateType(); int CvConvRegNum(int regNum, int* outBits = NULL); - addr_target GetSectionAddr(uint16 section, uint32 offset); + virtual addr_target GetSectionAddr(uint16 section, uint32 offset) override; + WinDebugger* GetWinDebugger(); int64 CvParseConstant(uint16 constVal, uint8*& data); int64 CvParseConstant(uint8*& data); DbgType* CvGetType(int typeId); diff --git a/IDEHelper/COFFData.h b/IDEHelper/COFFData.h index d0b19a4d1..45a3df861 100644 --- a/IDEHelper/COFFData.h +++ b/IDEHelper/COFFData.h @@ -5,6 +5,101 @@ struct CV_LVAR_ADDR_RANGE; struct CV_LVAR_ADDR_GAP; +#ifndef BF_PLATFORM_WINDOWS +#define IMAGE_SIZEOF_SHORT_NAME 8 + +#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 +#define IMAGE_DIRECTORY_ENTRY_DEBUG 6 +#define IMAGE_DIRECTORY_ENTRY_TLS 9 +#define IMAGE_DEBUG_TYPE_CODEVIEW 2 + +#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 +#define IMAGE_SCN_MEM_EXECUTE 0x20000000 +#define IMAGE_SCN_MEM_WRITE 0x80000000 + +#define IMAGE_REL_AMD64_ADDR64 0x0001 +#define IMAGE_REL_AMD64_ADDR32 0x0002 +#define IMAGE_REL_AMD64_ADDR32NB 0x0003 +#define IMAGE_REL_AMD64_REL32 0x0004 +#define IMAGE_REL_AMD64_REL32_5 0x0009 +#define IMAGE_REL_AMD64_SECTION 0x000A +#define IMAGE_REL_AMD64_SECREL 0x000B + +#define FIELD_OFFSET(type, field) ((int32)offsetof(type, field)) + +struct IMAGE_EXPORT_DIRECTORY +{ + uint32 Characteristics; + uint32 TimeDateStamp; + uint16 MajorVersion; + uint16 MinorVersion; + uint32 Name; + uint32 Base; + uint32 NumberOfFunctions; + uint32 NumberOfNames; + uint32 AddressOfFunctions; + uint32 AddressOfNames; + uint32 AddressOfNameOrdinals; +}; + +struct IMAGE_DEBUG_DIRECTORY +{ + uint32 Characteristics; + uint32 TimeDateStamp; + uint16 MajorVersion; + uint16 MinorVersion; + uint32 Type; + uint32 SizeOfData; + uint32 AddressOfRawData; + uint32 PointerToRawData; +}; + +struct IMAGE_RESOURCE_DIRECTORY +{ + uint32 Characteristics; + uint32 TimeDateStamp; + uint16 MajorVersion; + uint16 MinorVersion; + uint16 NumberOfNamedEntries; + uint16 NumberOfIdEntries; +}; + +struct IMAGE_RESOURCE_DIRECTORY_ENTRY +{ + union + { + uint32 Name; + uint16 Id; + }; + uint32 OffsetToData; +}; + +struct IMAGE_RESOURCE_DATA_ENTRY +{ + uint32 OffsetToData; + uint32 Size; + uint32 CodePage; + uint32 Reserved; +}; + +struct VS_FIXEDFILEINFO +{ + uint32 dwSignature; + uint32 dwStrucVersion; + uint32 dwFileVersionMS; + uint32 dwFileVersionLS; + uint32 dwProductVersionMS; + uint32 dwProductVersionLS; + uint32 dwFileFlagsMask; + uint32 dwFileFlags; + uint32 dwFileOS; + uint32 dwFileType; + uint32 dwFileSubtype; + uint32 dwFileDateMS; + uint32 dwFileDateLS; +}; +#endif + NS_BF_BEGIN #define PE_SIZEOF_SHORT_NAME 8 diff --git a/IDEHelper/DbgEvalSupport.cpp b/IDEHelper/DbgEvalSupport.cpp new file mode 100644 index 000000000..406a3cf1c --- /dev/null +++ b/IDEHelper/DbgEvalSupport.cpp @@ -0,0 +1,497 @@ +#include "DbgTargetHost.h" +#include "DbgExprEvaluator.h" +#include "DebugManager.h" +#include "DebugVisualizers.h" +#include "Compiler/BfSystem.h" +#include "Compiler/BfParser.h" +#include "Compiler/BfReducer.h" + +#include "BeefySysLib/util/AllocDebug.h" + +USING_NS_BF_DBG; + +DbgEvaluationContext::DbgEvaluationContext(DbgTargetHost* debugger, DbgModule* dbgModule, const StringImpl& expr, DwFormatInfo* formatInfo, DbgTypedValue contextValue) +{ + Init(debugger, dbgModule, expr, formatInfo, contextValue); +} + +DbgEvaluationContext::DbgEvaluationContext(DbgTargetHost* debugger, DbgCompileUnit* dbgCompileUnit, const StringImpl& expr, DwFormatInfo* formatInfo, DbgTypedValue contextValue) +{ + DbgModule* dbgModule = NULL; + if (dbgCompileUnit != NULL) + dbgModule = dbgCompileUnit->mDbgModule; + Init(debugger, dbgModule, expr, formatInfo, contextValue); +} + +void DbgEvaluationContext::Init(DbgTargetHost* debugger, DbgModule* dbgModule, const StringImpl& expr, DwFormatInfo* formatInfo, DbgTypedValue contextValue) +{ + if (expr.empty()) + { + mParser = NULL; + mReducer = NULL; + mPassInstance = NULL; + mDbgExprEvaluator = NULL; + mExprNode = NULL; + return; + } + + mParser = new BfParser(debugger->mBfSystem); + mParser->mCompatMode = true; + mPassInstance = new BfPassInstance(debugger->mBfSystem); + auto terminatedExpr = expr + ";"; + mParser->SetSource(terminatedExpr.c_str(), terminatedExpr.length()); + mParser->Parse(mPassInstance); + + mReducer = new BfReducer(); + mReducer->mAlloc = mParser->mAlloc; + mReducer->mSystem = debugger->mBfSystem; + mReducer->mPassInstance = mPassInstance; + mReducer->mVisitorPos = BfReducer::BfVisitorPos(mParser->mRootNode); + mReducer->mVisitorPos.MoveNext(); + mReducer->mCompatMode = mParser->mCompatMode; + mReducer->mSource = mParser; + mExprNode = mReducer->CreateExpression(mParser->mRootNode->GetFirst()); + mParser->Close(); + mDbgExprEvaluator = new DbgExprEvaluator(debugger, dbgModule, mPassInstance, -1, -1); + + if ((formatInfo != NULL) && (mExprNode != NULL) && (mExprNode->GetSrcEnd() < (int) expr.length())) + { + String formatFlags = expr.Substring(mExprNode->GetSrcEnd()); + String errorString = "Invalid expression"; + if (!debugger->ParseFormatInfo(dbgModule, formatFlags, formatInfo, mPassInstance, NULL, NULL, &errorString, contextValue)) + { + mPassInstance->FailAt(errorString, mParser->mSourceData, mExprNode->GetSrcEnd(), (int)expr.length() - mExprNode->GetSrcEnd()); + formatFlags = ""; + } + } + + if (formatInfo != NULL) + { + mDbgExprEvaluator->mExplicitThis = formatInfo->mExplicitThis; + mDbgExprEvaluator->mCallStackIdx = formatInfo->mCallStackIdx; + mDbgExprEvaluator->mLanguage = formatInfo->mLanguage; + } +} + +bool DbgEvaluationContext::HasExpression() +{ + return mExprNode != NULL; +} + +DbgEvaluationContext::~DbgEvaluationContext() +{ + delete mParser; + delete mReducer; + delete mDbgExprEvaluator; + delete mPassInstance; +} + +DbgTypedValue DbgEvaluationContext::EvaluateInContext(DbgTypedValue contextTypedValue) +{ + if (mExprNode == NULL) + return DbgTypedValue(); + mPassInstance->ClearErrors(); + if (contextTypedValue) + { + mDbgExprEvaluator->mExplicitThis = contextTypedValue; + if ((mDbgExprEvaluator->mExplicitThis.mType->IsPointer()) && (mDbgExprEvaluator->mExplicitThis.mType->mTypeParam->WantsRefThis())) + { + mDbgExprEvaluator->mExplicitThis.mType = mDbgExprEvaluator->mExplicitThis.mType->mTypeParam; + mDbgExprEvaluator->mExplicitThis.mSrcAddress = mDbgExprEvaluator->mExplicitThis.mPtr; + mDbgExprEvaluator->mExplicitThis.mPtr = 0; + } + + if ((mDbgExprEvaluator->mExplicitThis.mType->IsCompositeType()) && (!mDbgExprEvaluator->mExplicitThis.mType->WantsRefThis())) + { + if (mDbgExprEvaluator->mExplicitThis.mSrcAddress != 0) + { + mDbgExprEvaluator->mExplicitThis.mType = mDbgExprEvaluator->mDbgModule->GetPointerType(mDbgExprEvaluator->mExplicitThis.mType); + mDbgExprEvaluator->mExplicitThis.mPtr = mDbgExprEvaluator->mExplicitThis.mSrcAddress; + mDbgExprEvaluator->mExplicitThis.mSrcAddress = 0; + } + } + } + if (contextTypedValue.mType != NULL) + mDbgExprEvaluator->mDbgCompileUnit = contextTypedValue.mType->mCompileUnit; + DbgTypedValue exprResult; + auto result = mDbgExprEvaluator->Resolve(mExprNode); + return result; +} + +bool DbgEvaluationContext::HadError() +{ + return mPassInstance->mFailedIdx != 0; +} + +String DbgEvaluationContext::GetErrorStr() +{ + String errorStr = mPassInstance->mErrors[0]->mError; + if (mExprNode != NULL) + { + errorStr += ": "; + errorStr += mExprNode->ToString(); + } + return errorStr; +} + +bool DbgTargetHost::ParseFormatInfo(DbgModule* dbgModule, const StringImpl& formatInfoStr, DwFormatInfo* formatInfo, BfPassInstance* bfPassInstance, int* assignExprOffset, String* assignExprString, String* errorString, DbgTypedValue contextTypedValue) +{ + String formatFlags = formatInfoStr; + if (assignExprOffset != NULL) + *assignExprOffset = -1; + + while (formatFlags.length() > 0) + { + formatFlags = Trim(formatFlags); + if (formatFlags.IsEmpty()) + break; + if (formatFlags[0] != ',') + { + return false; + } + else + { + int nextComma = formatFlags.IndexOf(',', 1); + int quotePos = formatFlags.IndexOf('"', 1); + if ((quotePos != -1) && (quotePos < nextComma)) + { + int nextQuotePos = formatFlags.IndexOf('"', quotePos + 1); + if (nextQuotePos != -1) + nextComma = formatFlags.IndexOf(',', nextQuotePos + 1); + } + if (nextComma == -1) + nextComma = formatFlags.length(); + + String formatCmd = formatFlags.Substring(1, nextComma - 1); + formatCmd = Trim(formatCmd); + bool hadError = false; + + if (strncmp(formatCmd.c_str(), "this=", 5) == 0) + { + formatCmd = formatFlags.Substring(1); + formatCmd = Trim(formatCmd); + String thisExpr = formatCmd.Substring(5); + if (thisExpr.empty()) + break; + DbgEvaluationContext dbgEvaluationContext(this, dbgModule, thisExpr, formatInfo); + formatInfo->mExplicitThis = dbgEvaluationContext.EvaluateInContext(contextTypedValue); + if (dbgEvaluationContext.HadError()) + { + if (errorString != NULL) + *errorString = dbgEvaluationContext.GetErrorStr(); + return false; + } + formatFlags = thisExpr.Substring(dbgEvaluationContext.mExprNode->GetSrcEnd()); + continue; + } + else if (strncmp(formatCmd.c_str(), "count=", 6) == 0) + { + formatCmd = formatFlags.Substring(1); + formatCmd = Trim(formatCmd); + String countExpr = formatCmd.Substring(6); + if (countExpr.empty()) + break; + DbgEvaluationContext dbgEvaluationContext(this, dbgModule, countExpr, formatInfo); + DbgTypedValue countValue = dbgEvaluationContext.EvaluateInContext(contextTypedValue); + if ((countValue) && (countValue.mType->IsInteger())) + formatInfo->mOverrideCount = (intptr)countValue.GetInt64(); + if (dbgEvaluationContext.HadError()) + { + if (errorString != NULL) + *errorString = dbgEvaluationContext.GetErrorStr(); + return false; + } + formatFlags = countExpr.Substring(dbgEvaluationContext.mExprNode->GetSrcEnd()); + continue; + } + else if (strncmp(formatCmd.c_str(), "maxcount=", 9) == 0) + { + formatCmd = formatFlags.Substring(1); + formatCmd = Trim(formatCmd); + String countExpr = formatCmd.Substring(9); + if (countExpr.empty()) + break; + DbgEvaluationContext dbgEvaluationContext(this, dbgModule, countExpr, formatInfo); + DbgTypedValue countValue = dbgEvaluationContext.EvaluateInContext(contextTypedValue); + if ((countValue) && (countValue.mType->IsInteger())) + formatInfo->mMaxCount = (intptr)countValue.GetInt64(); + if (dbgEvaluationContext.HadError()) + { + if (errorString != NULL) + *errorString = dbgEvaluationContext.GetErrorStr(); + return false; + } + formatFlags = countExpr.Substring(dbgEvaluationContext.mExprNode->GetSrcEnd()); + continue; + } + else if (strncmp(formatCmd.c_str(), "arraysize=", 10) == 0) + { + formatCmd = formatFlags.Substring(1); + formatCmd = Trim(formatCmd); + String countExpr = formatCmd.Substring(10); + if (countExpr.empty()) + break; + DbgEvaluationContext dbgEvaluationContext(this, dbgModule, countExpr, formatInfo); + DbgTypedValue countValue = dbgEvaluationContext.EvaluateInContext(contextTypedValue); + if ((countValue) && (countValue.mType->IsInteger())) + formatInfo->mArrayLength = (intptr)countValue.GetInt64(); + if (dbgEvaluationContext.HadError()) + { + if (errorString != NULL) + *errorString = dbgEvaluationContext.GetErrorStr(); + return false; + } + formatFlags = countExpr.Substring(dbgEvaluationContext.mExprNode->GetSrcEnd()); + continue; + } + else if (strncmp(formatCmd.c_str(), "assign=", 7) == 0) + { + formatCmd = formatFlags.Substring(1); + formatCmd = Trim(formatCmd); + String assignExpr = formatCmd.Substring(7); + if (assignExpr.empty()) + break; + DbgEvaluationContext dbgEvaluationContext(this, dbgModule, assignExpr, formatInfo); + if (dbgEvaluationContext.HadError()) + { + if (errorString != NULL) + *errorString = dbgEvaluationContext.GetErrorStr(); + return false; + } + if (assignExprOffset != NULL) + { + //TODO: Keep track of the offset directly, this is a hack + *assignExprOffset = (int)formatInfoStr.IndexOf("assign=") + 7; + } + if (assignExprString != NULL) + *assignExprString = dbgEvaluationContext.mExprNode->ToString(); + formatFlags = assignExpr.Substring(dbgEvaluationContext.mExprNode->GetSrcEnd()); + continue; + } + else if (strncmp(formatCmd.c_str(), "refid=", 6) == 0) + { + formatInfo->mReferenceId = formatCmd.Substring(6); + if ((formatInfo->mReferenceId.mLength >= 2) && (formatInfo->mReferenceId[0] == '\"')) + formatInfo->mReferenceId = formatInfo->mReferenceId.Substring(1, formatInfo->mReferenceId.length() - 2); + } + else if (strncmp(formatCmd.c_str(), "action=", 7) == 0) + { + formatInfo->mAction = formatCmd.Substring(7); + if ((formatInfo->mAction.mLength >= 2) && (formatInfo->mAction[0] == '\"')) + formatInfo->mAction = formatInfo->mReferenceId.Substring(1, formatInfo->mReferenceId.length() - 2); + } + else if (strncmp(formatCmd.c_str(), "_=", 2) == 0) + { + formatInfo->mSubjectExpr = formatCmd.Substring(2); + if ((formatInfo->mSubjectExpr.mLength >= 2) && (formatInfo->mSubjectExpr[0] == '\"')) + formatInfo->mSubjectExpr = formatInfo->mSubjectExpr.Substring(1, formatInfo->mSubjectExpr.length() - 2); + } + else if (strncmp(formatCmd.c_str(), "expectedType=", 13) == 0) + { + formatInfo->mExpectedType = formatCmd.Substring(13); + if ((formatInfo->mExpectedType.mLength >= 2) && (formatInfo->mExpectedType[0] == '\"')) + formatInfo->mExpectedType = formatInfo->mExpectedType.Substring(1, formatInfo->mExpectedType.length() - 2); + } + else if (strncmp(formatCmd.c_str(), "namespaceSearch=", 16) == 0) + { + formatInfo->mNamespaceSearch = formatCmd.Substring(16); + if ((formatInfo->mNamespaceSearch.mLength >= 2) && (formatInfo->mNamespaceSearch[0] == '\"')) + formatInfo->mNamespaceSearch = formatInfo->mNamespaceSearch.Substring(1, formatInfo->mNamespaceSearch.length() - 2); + } + else if (formatCmd == "d") + { + formatInfo->mDisplayType = DwDisplayType_Decimal; + } + else if (formatCmd == "x") + { + formatInfo->mDisplayType = DwDisplayType_HexLower; + } + else if (formatCmd == "X") + { + formatInfo->mDisplayType = DwDisplayType_HexUpper; + } + else if (formatCmd == "s") + { + formatInfo->mHidePointers = true; + formatInfo->mDisplayType = DwDisplayType_Ascii; + } + else if (formatCmd == "s8") + { + formatInfo->mHidePointers = true; + formatInfo->mDisplayType = DwDisplayType_Utf8; + } + else if (formatCmd == "s16") + { + formatInfo->mHidePointers = true; + formatInfo->mDisplayType = DwDisplayType_Utf16; + } + else if (formatCmd == "s32") + { + formatInfo->mHidePointers = true; + formatInfo->mDisplayType = DwDisplayType_Utf32; + } + else if (formatCmd == "nd") + { + formatInfo->mIgnoreDerivedClassInfo = true; + } + else if (formatCmd == "na") + { + formatInfo->mHidePointers = true; + } + else if (formatCmd == "nm") + { + formatInfo->mNoMembers = true; + } + else if (formatCmd == "ne") + { + formatInfo->mNoEdit = true; + } + else if (formatCmd == "nv") + { + formatInfo->mNoVisualizers = true; + } + else if (formatCmd == "rawStr") + { + formatInfo->mRawString = true; + } + else if (((!formatCmd.IsEmpty()) && ((formatCmd[0] >= '0') && (formatCmd[0] <= '9'))) || + (formatCmd.StartsWith("("))) + { + String countExpr = formatCmd; + if (countExpr.empty()) + break; + DbgEvaluationContext dbgEvaluationContext(this, dbgModule, countExpr, formatInfo); + DbgTypedValue countValue = dbgEvaluationContext.EvaluateInContext(contextTypedValue); + if ((countValue) && (countValue.mType->IsInteger())) + formatInfo->mArrayLength = (intptr)countValue.GetInt64(); + if (dbgEvaluationContext.HadError()) + { + if (errorString != NULL) + *errorString = dbgEvaluationContext.GetErrorStr(); + return false; + } + formatFlags = countExpr.Substring(dbgEvaluationContext.mExprNode->GetSrcEnd()); + continue; + } + else + hadError = true; + + if (hadError) + { + if (errorString != NULL) + *errorString = "Invalid format flags"; + return false; + } + + formatFlags = formatFlags.Substring(nextComma); + } + } + return true; +} + +String DbgTargetHost::MaybeQuoteFormatInfoParam(const StringImpl& str) +{ + bool needsQuote = false; + for (int i = 0; i < (int)str.length(); i++) + { + char c = str[i]; + if (c == ',') + needsQuote = true; + } + if (!needsQuote) + return str; + + String qStr = "\""; + qStr += str; + qStr += "\""; + return qStr; +} + +DbgTypedValue DbgTargetHost::EvaluateInContext(DbgCompileUnit* dbgCompileUnit, const DbgTypedValue& contextTypedValue, const StringImpl& subExpr, DwFormatInfo* formatInfo, String* outReferenceId, String* outErrors) +{ + DbgEvaluationContext dbgEvaluationContext(this, dbgCompileUnit->mDbgModule, subExpr, formatInfo, contextTypedValue); + if (dbgEvaluationContext.mDbgExprEvaluator == NULL) + return DbgTypedValue(); + dbgEvaluationContext.mDbgExprEvaluator->mDbgCompileUnit = dbgCompileUnit; + if (formatInfo != NULL) + { + dbgEvaluationContext.mDbgExprEvaluator->mLanguage = formatInfo->mLanguage; + dbgEvaluationContext.mDbgExprEvaluator->mSubjectExpr = formatInfo->mSubjectExpr; + } + dbgEvaluationContext.mDbgExprEvaluator->mReferenceId = outReferenceId; + auto result = dbgEvaluationContext.EvaluateInContext(contextTypedValue); + if ((formatInfo != NULL) && (dbgEvaluationContext.mDbgExprEvaluator->mCountResultOverride != -1)) + formatInfo->mOverrideCount = dbgEvaluationContext.mDbgExprEvaluator->mCountResultOverride; + if (dbgEvaluationContext.mPassInstance->HasFailed()) + { + if (outErrors != NULL) + { + int errIdx = 0; + for (auto err : dbgEvaluationContext.mPassInstance->mErrors) + { + if (errIdx > 0) + (*outErrors) += "\n"; + (*outErrors) += err->mError; + errIdx++; + } + } + return DbgTypedValue(); + } + return result; +} + +void DbgTargetHost::DbgVisFailed(DebugVisualizerEntry* debugVis, const StringImpl& evalString, const StringImpl& errors) +{ + bool onlyMemError = errors.StartsWith("Failed to read") && !errors.Contains('\n'); + if ((!debugVis->mShowedError) && (!onlyMemError)) + { + debugVis->mShowedError = true; + String errStr = StrFormat("DbgVis '%s' failed while evaluating condition '%s'\n", debugVis->mName.c_str(), evalString.c_str()); + String spacedErrors = errors; + spacedErrors.Insert(0, " "); + spacedErrors.Replace("\n", "\n "); + errStr += spacedErrors; + OutputMessage(errStr); + } +} + +bool DbgTargetHost::EvalCondition(DebugVisualizerEntry* debugVis, DbgCompileUnit* dbgCompileUnit, DbgTypedValue typedVal, DwFormatInfo& formatInfo, const StringImpl& condition, const Array& dbgVisWildcardCaptures, String& errorStr) +{ + DwFormatInfo displayStrFormatInfo = formatInfo; + displayStrFormatInfo.mHidePointers = false; + displayStrFormatInfo.mRawString = false; + + String errors; + const String conditionStr = mDebugManager->mDebugVisualizers->DoStringReplace(condition, dbgVisWildcardCaptures); + DbgTypedValue evalResult = EvaluateInContext(dbgCompileUnit, typedVal, conditionStr, &displayStrFormatInfo, NULL, &errors); + if ((!evalResult) || (!evalResult.mType->IsBoolean())) + { + if (formatInfo.mRawString) + return false; + + errorStr += ""; + DbgVisFailed(debugVis, conditionStr, errors); + return false; + } + + return evalResult.mBool; +} + +DebugVisualizerEntry* DbgTargetHost::FindVisualizerForType(DbgType* dbgType, Array* wildcardCaptures) +{ + auto entry = mDebugManager->mDebugVisualizers->FindEntryForType(dbgType->ToString(DbgLanguage_Unknown, true), dbgType->mCompileUnit->mDbgModule->mDbgFlavor, wildcardCaptures); + + if (entry == NULL) + { + dbgType = dbgType->GetPrimaryType(); + dbgType->PopulateType(); + for (auto baseTypeEntry : dbgType->mBaseTypes) + { + entry = FindVisualizerForType(baseTypeEntry->mBaseType, wildcardCaptures); + if (entry != NULL) + break; + } + } + + return entry; +} diff --git a/IDEHelper/DbgExprEvaluator.cpp b/IDEHelper/DbgExprEvaluator.cpp index e4e05cb68..24693625a 100644 --- a/IDEHelper/DbgExprEvaluator.cpp +++ b/IDEHelper/DbgExprEvaluator.cpp @@ -1,5 +1,6 @@ #include "DbgExprEvaluator.h" -#include "WinDebugger.h" +#include "DbgTargetHost.h" +#include "DebugTarget.h" #include "Compiler/BfUtil.h" #include "Compiler/BfSystem.h" #include "Compiler/BfParser.h" @@ -727,12 +728,12 @@ bool DwMethodMatcher::CheckType(DbgType* typeInstance, bool isFailurePass) ////////////////////////////////////////////////////////////////////////// -DbgExprEvaluator::DbgExprEvaluator(WinDebugger* winDebugger, DbgModule* dbgModule, BfPassInstance* passInstance, int callStackIdx, int cursorPos) +DbgExprEvaluator::DbgExprEvaluator(DbgTargetHost* debugger, DbgModule* dbgModule, BfPassInstance* passInstance, int callStackIdx, int cursorPos) { mCountResultOverride = -1; mCapturingChildRef = true; mPassInstance = passInstance; - mDebugger = winDebugger; + mDebugger = debugger; mLanguage = DbgLanguage_NotSet; mOrigDbgModule = dbgModule; if (dbgModule != NULL) @@ -3639,9 +3640,9 @@ DbgTypedValue DbgExprEvaluator::DoLookupIdentifier(BfAstNode* identifierNode, bo if (findName == "$this") return GetThis(); else if (findName == "$ThreadId") - return GetInt(mDebugger->mActiveThread->mThreadId); + return GetInt(mDebugger->GetActiveThreadId()); else if (findName == "$ThreadName") - return GetString(mDebugger->mActiveThread->mName); + return GetString(mDebugger->GetActiveThreadName()); else if (findName == "$TargetName") return GetString(GetFileName(mDebugTarget->mTargetPath)); else if (findName == "LaunchName") @@ -3653,19 +3654,11 @@ DbgTypedValue DbgExprEvaluator::DoLookupIdentifier(BfAstNode* identifierNode, bo else if (findName == "$ModulePath") return GetString(mDbgModule->mFilePath); else if (findName == "$HitCount") - { - if (mDebugger->mActiveBreakpoint != NULL) - return GetInt(mDebugger->mActiveBreakpoint->GetHeadBreakpoint()->mHitCount); - return GetInt(0); - } + return GetInt(mDebugger->GetActiveBreakpointHitCount()); else if (findName == "$BreakpointCondition") - { - if ((mDebugger->mActiveBreakpoint != NULL) && (mDebugger->mActiveBreakpoint->mCondition != NULL)) - return GetString(mDebugger->mActiveBreakpoint->GetHeadBreakpoint()->mCondition->mExpr); - return GetString(""); - } + return GetString(mDebugger->GetActiveBreakpointCondition()); else if (findName == "$ProcessId") - return GetInt(mDebugger->mProcessInfo.dwProcessId); + return GetInt(mDebugger->GetTargetProcessId()); bool mayBeRegister = true; for (int i = 1; i < findName.length(); i++) @@ -6686,7 +6679,7 @@ void DbgExprEvaluator::PerformUnaryExpression(BfAstNode* opToken, BfUnaryOp unar val.mDouble += add; break; default: - Fail(StrFormat("Unable to perform operation on type '%s'", ptr.mType->ToString()), expr); + Fail(StrFormat("Unable to perform operation on type '%s'", ptr.mType->ToString().c_str()), expr); return; } @@ -7016,7 +7009,7 @@ DbgTypedValue DbgExprEvaluator::CreateCall(DbgSubprogram* method, DbgTypedValue mDebugger->SaveAllRegisters(); - BfLogDbg("Starting RunState_DebugEval on thread %d\n", mDebugger->mActiveThread->mThreadId); + BfLogDbg("Starting RunState_DebugEval on thread %d\n", mDebugger->GetActiveThreadId()); addr_target prevSP = registers->GetSP(); @@ -7052,10 +7045,10 @@ DbgTypedValue DbgExprEvaluator::CreateCall(DbgSubprogram* method, DbgTypedValue // mDebugger->mActiveThread->mBreakpointAddressContinuing = 0; auto prevRunState = mDebugger->mRunState; mDebugger->mRunState = RunState_DebugEval; - mDebugger->mExplicitStopThread = NULL; + mDebugger->ClearExplicitStopThread(); mDebugger->mRequestedStackFrameIdx = -1; - BfLogDbg("DbgExprEvaluator::CreateCall %p in thread %d\n", startAddr, mDebugger->mActiveThread->mThreadId); + BfLogDbg("DbgExprEvaluator::CreateCall %p in thread %d\n", startAddr, mDebugger->GetActiveThreadId()); DbgCallResult callResult; callResult.mSubProgram = method; diff --git a/IDEHelper/DbgExprEvaluator.h b/IDEHelper/DbgExprEvaluator.h index ecfa164f2..c1227ff0a 100644 --- a/IDEHelper/DbgExprEvaluator.h +++ b/IDEHelper/DbgExprEvaluator.h @@ -13,7 +13,7 @@ namespace Beefy NS_BF_DBG_BEGIN -class WinDebugger; +class DbgTargetHost; class WdStackFrame; typedef WdStackFrame CPUStackFrame; @@ -339,7 +339,7 @@ class DbgExprEvaluator : public BfStructuralVisitor DbgLanguage mLanguage; BfPassInstance* mPassInstance; - WinDebugger* mDebugger; + DbgTargetHost* mDebugger; String mExpectingTypeName; String mSubjectExpr; DbgTypedValue mSubjectValue; @@ -407,7 +407,7 @@ class DbgExprEvaluator : public BfStructuralVisitor DbgFlavor GetFlavor(); public: - DbgExprEvaluator(WinDebugger* winDebugger, DbgModule* dbgModule, BfPassInstance* passInstance, int callStackIdx, int cursorPos); + DbgExprEvaluator(DbgTargetHost* debugger, DbgModule* dbgModule, BfPassInstance* passInstance, int callStackIdx, int cursorPos); ~DbgExprEvaluator(); DbgTypedValue GetInt(int value); diff --git a/IDEHelper/DbgModule.cpp b/IDEHelper/DbgModule.cpp index 46033674a..5bff25088 100644 --- a/IDEHelper/DbgModule.cpp +++ b/IDEHelper/DbgModule.cpp @@ -7,14 +7,16 @@ #include "DbgModule.h" #include "DWARFInfo.h" +#ifdef BF_PLATFORM_WINDOWS #include +#endif #include #include #include #include #include #include -#include "WinDebugger.h" +#include "DbgTargetHost.h" #include "DebugManager.h" #include "DebugTarget.h" #include "COFFData.h" @@ -23,7 +25,7 @@ #include "BeefySysLib/util/BeefPerf.h" #include "BeefySysLib/util/MultiDictionary.h" #include "DbgSymSrv.h" -#include "MiniDumpDebugger.h" +#include "COFF.h" #pragma warning(pop) @@ -3183,6 +3185,75 @@ void DbgModule::MapSubprogram(DbgSubprogram* dbgSubprogram) } } +static int CompareLineData(const void* lineDataP1, const void* lineDataP2) +{ + int cmpResult = (int)(((DbgLineData*)lineDataP1)->mRelAddress - ((DbgLineData*)lineDataP2)->mRelAddress); + if (cmpResult != 0) + return cmpResult; + + // A larger contrib size means it's the 'outer' inlinee + cmpResult = -(((DbgLineData*)lineDataP1)->mContribSize - ((DbgLineData*)lineDataP2)->mContribSize); + if (cmpResult != 0) + return cmpResult; + + return -(((DbgLineData*)lineDataP1)->mCtxIdx - ((DbgLineData*)lineDataP2)->mCtxIdx); +} + +void DbgModule::FixupLineDataForSubprogram(DbgSubprogram* subProgram) +{ + if ((subProgram == NULL) || (!subProgram->mNeedLineDataFixup)) + return; + + BP_ZONE("FixupLineDataForSubprogram"); + + subProgram->mNeedLineDataFixup = false; + if (subProgram->mInlineeInfo != NULL) + FixupLineDataForSubprogram(subProgram->mInlineeInfo->mRootInliner); + + if ((subProgram->mLineInfo == NULL) || (subProgram->mLineInfo->mLines.mSize == 0)) + return; + + //TODO: I think this was covering up a bug in DWARF line encoding? Figure this out +// if (subProgram->mLineInfo->mLines.mSize >= 2) +// { +// DbgLineData* line0 = &subProgram->mLineInfo->mLines[0]; +// DbgLineData* line1 = &subProgram->mLineInfo->mLines[1]; +// +// +// if ((line0->mRelAddress == line1->mRelAddress) && (!line0->IsStackFrameSetup()) && (line1->IsStackFrameSetup())) +// { +// CPUInst inst; +// if (mCPU->Decode(line0->mAddress, subProgram->mCompileUnit->mDbgModule->mOrigImageData, &inst)) +// line1->mAddress += inst.GetLength(); +// } +// } + + qsort(subProgram->mLineInfo->mLines.mVals, subProgram->mLineInfo->mLines.mSize, sizeof(DbgLineData), CompareLineData); + + // If we have multiple lines with the same line/column/context, merge them + if (!subProgram->mLineInfo->mLines.IsEmpty()) + { + auto prevLine = &subProgram->mLineInfo->mLines[0]; + for (int i = 1; i < subProgram->mLineInfo->mLines.mSize; i++) + { + auto nextLine = &subProgram->mLineInfo->mLines[i]; + + if ((nextLine->mLine == prevLine->mLine) && (nextLine->mColumn == prevLine->mColumn) && (nextLine->mCtxIdx == prevLine->mCtxIdx) && + (nextLine->mRelAddress == prevLine->mRelAddress + prevLine->mContribSize)) + { + prevLine->mContribSize += nextLine->mContribSize; + // This messed up inline cases because mContribSize actually INCLUDES inlined lines so it caused the address to skip too far + //nextLine->mRelAddress += nextLine->mContribSize; + //nextLine->mContribSize = 0; + } + else + { + prevLine = nextLine; + } + } + } +} + bool DbgModule::ParseDWARF(const uint8*& dataPtr) { BP_ZONE("ParseDWARF"); @@ -5763,11 +5834,7 @@ bool DbgModule::ReadCOFF(DataStream* stream, DbgModuleKind moduleKind) DbgModule* mainModule = mDebugTarget->mTargetBinary; - MiniDumpDebugger* miniDumpDebugger = NULL; - if (mDebugger->IsMiniDumpDebugger()) - { - miniDumpDebugger = (MiniDumpDebugger*)mDebugger; - } + bool isMiniDump = mDebugger->IsMiniDumpDebugger(); mModuleKind = moduleKind; bool isHotSwap = mModuleKind == DbgModuleKind_HotObject; @@ -5844,10 +5911,10 @@ bool DbgModule::ReadCOFF(DataStream* stream, DbgModuleKind moduleKind) int sectionStartPos = stream->GetPos(); int sectionDataEndPos = 0; - if (miniDumpDebugger != NULL) + if (isMiniDump) { // Map header - miniDumpDebugger->MapMemory((addr_target)mImageBase, (uint8*)mMappedImageFile->mData, 0x1000); + mDebugger->MapMemory((addr_target)mImageBase, (uint8*)mMappedImageFile->mData, 0x1000); } bool wantStringTable = isObjectFile; @@ -5864,9 +5931,9 @@ bool DbgModule::ReadCOFF(DataStream* stream, DbgModuleKind moduleKind) if (sectHdr.mNumberOfRelocations > 0) sectionDataEndPos = BF_MAX(sectionDataEndPos, (int)(sectHdr.mPointerToRelocations + sectHdr.mNumberOfRelocations * sizeof(COFFRelocation))); - if (miniDumpDebugger != NULL) + if (isMiniDump) { - miniDumpDebugger->MapMemory((addr_target)(mImageBase + sectHdr.mVirtualAddress), (uint8*)mMappedImageFile->mData + sectHdr.mPointerToRawData, sectHdr.mSizeOfRawData); + mDebugger->MapMemory((addr_target)(mImageBase + sectHdr.mVirtualAddress), (uint8*)mMappedImageFile->mData + sectHdr.mPointerToRawData, sectHdr.mSizeOfRawData); } } @@ -7051,7 +7118,6 @@ intptr DbgModule::EvaluateLocation(DbgSubprogram* dwSubprogram, const uint8* loc BF_ASSERT(dbgModule->mDbgFlavor == DbgFlavor_MS); if (dbgModule->mDbgFlavor == DbgFlavor_MS) { - COFF* coff = (COFF*)dbgModule; struct SegOfsData { uint32 mOfs; @@ -7060,7 +7126,7 @@ intptr DbgModule::EvaluateLocation(DbgSubprogram* dwSubprogram, const uint8* loc SegOfsData* segOfsData = (SegOfsData*)locData; *outAddrType = DbgAddrType_Target; - return coff->GetSectionAddr(segOfsData->mSeg, segOfsData->mOfs); + return dbgModule->GetSectionAddr(segOfsData->mSeg, segOfsData->mOfs); } else { diff --git a/IDEHelper/DbgModule.h b/IDEHelper/DbgModule.h index 6087ac2ba..b1081d56b 100644 --- a/IDEHelper/DbgModule.h +++ b/IDEHelper/DbgModule.h @@ -14,6 +14,7 @@ #include "RadixMap.h" #include #include +#include #include #include "Debugger.h" #include "StrHashMap.h" @@ -97,7 +98,7 @@ enum DbgTypeCode : uint8 }; class DebugTarget; -class WinDebugger; +class DbgTargetHost; class DbgType; class DbgBlock; @@ -162,7 +163,7 @@ enum DbgLocationLenKind class DbgVariable : public DbgDebugData { public: - static const DbgClassType ClassType = DbgClassType_Variable; + static constexpr DbgClassType ClassType = DbgClassType_Variable; const char* mName; const char* mLinkName; @@ -218,7 +219,7 @@ typedef std::map > DwAsmDebugLineMap; class DbgBlock : public DbgDebugData { public: - static const DbgClassType ClassType = DbgClassType_Block; + static constexpr DbgClassType ClassType = DbgClassType_Block; addr_target mLowPC; // If LowPC is -1 then mHighPC is index into debugRanges addr_target mHighPC; @@ -345,7 +346,7 @@ class DbgInlineeInfo class DbgSubprogram : public DbgDebugData { public: - static const DbgClassType ClassType = DbgClassType_Subprogram; + static constexpr DbgClassType ClassType = DbgClassType_Subprogram; #ifdef BF_DBG_32 enum LocalBaseRegKind : uint8 @@ -534,7 +535,7 @@ enum DbgExtType : int8 class DbgType : public DbgDebugData { public: - static const DbgClassType ClassType = DbgClassType_Type; + static constexpr DbgClassType ClassType = DbgClassType_Type; DbgType* mParent; BumpList mAlternates; // From other compile units DbgType* mPrimaryType; @@ -830,7 +831,7 @@ class DbgCompileUnitContrib class DbgCompileUnit { public: - static const DbgClassType ClassType = DbgClassType_CompileUnit; + static constexpr DbgClassType ClassType = DbgClassType_CompileUnit; DbgModule* mDbgModule; DbgLanguage mLanguage; @@ -1112,7 +1113,7 @@ class DbgModule public: static const int ImageBlockSize = 4096; - WinDebugger* mDebugger; + DbgTargetHost* mDebugger; DebugTarget* mDebugTarget; DbgModuleLoadState mLoadState; MappedFile* mMappedImageFile; @@ -1230,6 +1231,7 @@ class DbgModule virtual void PopulateStaticVariableMap(); virtual void ProcessDebugInfo(); virtual bool CanGetOldSource() { return false; } + virtual addr_target GetSectionAddr(uint16 section, uint32 offset) { return 0; } virtual String GetOldSourceCommand(const StringImpl& path) { return ""; } virtual bool GetEmitSource(const StringImpl& filePath, String& outText) { return false; } virtual bool DbgIsStrMutable(const char* str) { return true; } // Always assume its a copy @@ -1253,6 +1255,7 @@ class DbgModule DbgType* GetOrCreateType(int typeIdx, DbgDataMap& typeMap); //void SplitName(const char* inName, const char*& outBaseName, const char*& outTemplateParams, bool alwaysDup = false); void MapSubprogram(DbgSubprogram* dbgSubprogram); + static void FixupLineDataForSubprogram(DbgSubprogram* subProgram); bool ParseDWARF(const uint8*& dataPtr); void ParseAbbrevData(const uint8* data); void ParseExceptionData(); diff --git a/IDEHelper/DbgTargetHost.h b/IDEHelper/DbgTargetHost.h new file mode 100644 index 000000000..b08d998bd --- /dev/null +++ b/IDEHelper/DbgTargetHost.h @@ -0,0 +1,177 @@ +#pragma once + +#include "Debugger.h" +#include "DbgExprEvaluator.h" + +namespace Beefy +{ + class BfSystem; + class BfReducer; + class BfPassInstance; + class DebugVisualizerEntry; +}; + +NS_BF_DBG_BEGIN + +class DbgTargetHost; + +class DbgEvaluationContext +{ +public: + BfParser* mParser; + BfReducer* mReducer; + BfPassInstance* mPassInstance; + DbgExprEvaluator* mDbgExprEvaluator; + BfExpression* mExprNode; + +public: + DbgEvaluationContext(DbgTargetHost* debugger, DbgModule* dbgModule, const StringImpl& expr, DwFormatInfo* formatInfo = NULL, DbgTypedValue contextValue = DbgTypedValue()); + DbgEvaluationContext(DbgTargetHost* debugger, DbgCompileUnit* dbgCompileUnit, const StringImpl& expr, DwFormatInfo* formatInfo = NULL, DbgTypedValue contextValue = DbgTypedValue()); + void Init(DbgTargetHost* debugger, DbgModule* dbgModule, const StringImpl& expr, DwFormatInfo* formatInfo = NULL, DbgTypedValue contextValue = DbgTypedValue()); + bool HasExpression(); + ~DbgEvaluationContext(); + DbgTypedValue EvaluateInContext(DbgTypedValue contextTypedValue); + String GetErrorStr(); + bool HadError(); +}; + +class WdStackFrame +{ +public: + CPURegisters mRegisters; + bool mIsStart; + bool mIsEnd; + bool mInInlineMethod; + bool mInInlineCall; // Means the frame above us is inlined + + DbgSubprogram* mSubProgram; + bool mHasGottenSubProgram; + Array mRegForms; + +public: + WdStackFrame() + { + mSubProgram = NULL; + mHasGottenSubProgram = false; + mIsStart = true; + mIsEnd = false; + mInInlineMethod = false; + mInInlineCall = false; + } + + addr_target GetSourcePC() + { + // 'PC' is return address of call in these cases, so subtract 1 for cases where + // we want to bring it back into the calling block range (note that this doesn't + // properly determine the actual starting address of the call instruction, though) + if ((!mIsStart) && (!mInInlineCall)) + return mRegisters.GetPC() - 1; + return mRegisters.GetPC(); + } +}; + +typedef WdStackFrame CPUStackFrame; + +struct DbgPendingDebugInfoLoad +{ + DbgModule* mModule; + bool mAllowRemote; + + DbgPendingDebugInfoLoad() + { + mModule = NULL; + mAllowRemote = false; + } +}; + +class DbgTargetHost : public Debugger +{ +public: + BfSystem* mBfSystem; + volatile bool mIsRunning; + int mPageSize; + Array mCallStack; + int mRequestedStackFrameIdx; // -1 means to show mShowPCOverride, -2 means "auto" stop, -3 means breakpoint - normally 0 but during inlining the address can be ambiguous + CPURegisters mDebugEvalSetRegisters; + Dictionary mPendingDebugInfoLoad; + HashSet mLiteralSet; + +public: + virtual void Fail(const StringImpl& error) = 0; + virtual addr_target GetTLSOffset(int tlsIndex) = 0; + virtual int EnableWriting(intptr address, int size) = 0; + virtual int SetProtection(intptr address, int size, int prot) = 0; + virtual bool IsMiniDumpDebugger() = 0; + virtual void MapMemory(addr_target addr, void* data, intptr_target size) {} + + virtual int GetActiveThreadId() = 0; + virtual String GetActiveThreadName() = 0; + virtual void ClearExplicitStopThread() = 0; + virtual int GetActiveBreakpointHitCount() = 0; + virtual String GetActiveBreakpointCondition() = 0; + virtual int GetTargetProcessId() = 0; + + virtual bool PopulateRegisters(CPURegisters* registers) = 0; + virtual DbgTypedValue GetRegister(const StringImpl& regName, DbgLanguage language, CPURegisters* registers, Array* regForms = NULL) = 0; + virtual bool AssignToReg(int callStackIdx, DbgTypedValue reg, DbgTypedValue value, String& outError) = 0; + virtual bool SetRegisters(CPURegisters* registers) = 0; + virtual void SaveAllRegisters() = 0; + virtual void RestoreAllRegisters() = 0; + + virtual void PushValue(CPURegisters* registers, int64 val) = 0; + virtual void PushValue(CPURegisters* registers, const DbgTypedValue& typedValue) = 0; + virtual void SetThisRegister(CPURegisters* registers, addr_target val) = 0; + virtual void AddParamValue(int paramIdx, bool hadThis, CPURegisters* registers, const DbgTypedValue& typedValue) = 0; + virtual bool CheckNeedsSRetArgument(DbgType* retType) = 0; + virtual DbgTypedValue ReadReturnValue(CPURegisters* registers, DbgType* type) = 0; + + virtual bool ProcessEvalString(DbgCompileUnit* dbgCompileUnit, DbgTypedValue useTypedValue, String& evalStr, String& displayString, DwFormatInfo& formatInfo, DebugVisualizerEntry* debugVis, bool limitLength) = 0; + + virtual bool WantsHotHeap() = 0; + virtual addr_target ReserveHotHeapMemory(addr_target address, int size) = 0; + virtual void ReleaseHotHeapMemory(addr_target address) = 0; + virtual void ReserveHotTargetMemory(int size) = 0; + virtual addr_target AllocHotTargetMemory(int size, bool canExecute, bool canWrite, int* outAllocSize) = 0; + virtual void ReleaseHotTargetMemory(addr_target addr, int size) = 0; + virtual bool WriteInstructions(intptr address, void* src, uint64 length) = 0; + virtual bool SetHotJump(DbgSubprogram* oldSubprogram, addr_target newTarget, int newTargetSize) = 0; + virtual void PhysSetBreakpoint(addr_target address) = 0; + + virtual addr_target DecodeThunk(addr_target address, DbgModuleMemoryCache* memoryCache) = 0; + virtual bool DecodeInstruction(addr_target address, DbgModuleMemoryCache* memoryCache, CPUInst* inst) = 0; + virtual DbgBreakKind GetDbgBreakKind(addr_target address, DbgModuleMemoryCache* memoryCache, intptr_target* regs, intptr_target* outObjectPtr) = 0; + + template T ReadMemory(intptr addr, bool local = false, bool* failed = NULL); + using Debugger::ReadMemory; + + bool ParseFormatInfo(DbgModule* dbgModule, const StringImpl& formatInfoStr, DwFormatInfo* formatInfo, BfPassInstance* bfPassInstance, int* assignExprOffset, String* assignExpr = NULL, String* errorString = NULL, DbgTypedValue contextTypedValue = DbgTypedValue()); + String MaybeQuoteFormatInfoParam(const StringImpl& str); + void DbgVisFailed(DebugVisualizerEntry* debugVis, const StringImpl& evalString, const StringImpl& errors); + DbgTypedValue EvaluateInContext(DbgCompileUnit* dbgCompileUnit, const DbgTypedValue& contextTypedValue, const StringImpl& subExpr, DwFormatInfo* formatInfo = NULL, String* outReferenceId = NULL, String* outErrors = NULL); + bool EvalCondition(DebugVisualizerEntry* debugVis, DbgCompileUnit* dbgCompileUnit, DbgTypedValue typedVal, DwFormatInfo& formatInfo, const StringImpl& condition, const Array& dbgVisWildcardCaptures, String& errorStr); + DebugVisualizerEntry* FindVisualizerForType(DbgType* dbgType, Array* wildcardCaptures); +}; + +template T DbgTargetHost::ReadMemory(intptr addr, bool local, bool* failed) +{ + bool success = true; + T val; + memset(&val, 0, sizeof(T)); + if (local) + { + if (addr != 0) + memcpy(&val, (void*)(intptr)addr, sizeof(T)); + else + success = false; + } + else + { + success = ReadMemory(addr, (int)sizeof(T), &val); + } + + if (failed != NULL) + *failed = !success; + return val; +} + +NS_BF_DBG_END diff --git a/IDEHelper/DbgTypeMap.h b/IDEHelper/DbgTypeMap.h index 327b518ea..483d8dc57 100644 --- a/IDEHelper/DbgTypeMap.h +++ b/IDEHelper/DbgTypeMap.h @@ -1,8 +1,8 @@ #pragma once #include "DebugCommon.h" -#include "BeefySysLib/Util/BumpAllocator.h" -#include "BeefySysLib/Util/HashSet.h" +#include "BeefySysLib/util/BumpAllocator.h" +#include "BeefySysLib/util/HashSet.h" namespace Beefy { diff --git a/IDEHelper/DebugTarget.cpp b/IDEHelper/DebugTarget.cpp index 86f258fb3..f7dd15d78 100644 --- a/IDEHelper/DebugTarget.cpp +++ b/IDEHelper/DebugTarget.cpp @@ -1,11 +1,14 @@ #include "DebugTarget.h" -#include "WinDebugger.h" +#include "DbgTargetHost.h" #include "DWARFInfo.h" #include "BeefySysLib/FileStream.h" #include "BeefySysLib/MemStream.h" -#include "BeefySysLib/Util/BeefPerf.h" +#include "BeefySysLib/util/BeefPerf.h" #include "DebugManager.h" #include "HotHeap.h" +#ifdef BF_PLATFORM_WINDOWS +#include "COFF.h" +#endif //#include #include "BeefySysLib/util/AllocDebug.h" @@ -15,7 +18,7 @@ USING_NS_BF_DBG; #define GET(T) *((T*)(data += sizeof(T)) - 1) #define GET_FROM(ptr, T) *((T*)(ptr += sizeof(T)) - 1) -DebugTarget::DebugTarget(WinDebugger* debugger) +DebugTarget::DebugTarget(DbgTargetHost* debugger) { mCheckedCompilerSettings = false; mBfObjectHasFlags = false; @@ -89,7 +92,7 @@ static bool PathEquals(const String& pathA, String& pathB) void DebugTarget::SetupTargetBinary() { - bool wantsHotHeap = (mDebugger->mHotSwapEnabled == true && mDebugger->mDbgProcessId == 0); + bool wantsHotHeap = mDebugger->WantsHotHeap(); #ifdef BF_DBG_32 if (wantsHotHeap) @@ -111,7 +114,7 @@ void DebugTarget::SetupTargetBinary() addr_target reservedPtr = NULL; while ((addr_target)checkHotReserveAddr < (addr_target)mTargetBinary->mImageBase + 0x30000000) { - reservedPtr = (addr_target)VirtualAllocEx(mDebugger->mProcessInfo.hProcess, (void*)(intptr)checkHotReserveAddr, reserveSize, MEM_RESERVE, PAGE_EXECUTE_READWRITE); + reservedPtr = mDebugger->ReserveHotHeapMemory(checkHotReserveAddr, reserveSize); if (reservedPtr != NULL) { mHotHeapAddr = reservedPtr; @@ -147,6 +150,15 @@ void DebugTarget::CheckTargetBinary(DbgModule* module) SetupTargetBinary(); } +DbgModule* DebugTarget::CreateDbgModule() +{ +#ifdef BF_PLATFORM_WINDOWS + return new COFF(this); +#else + return new DbgModule(this); +#endif +} + DbgModule* DebugTarget::Init(const StringImpl& launchPath, const StringImpl& targetPath, intptr imageBase) { BP_ZONE("DebugTarget::Init"); @@ -155,14 +167,13 @@ DbgModule* DebugTarget::Init(const StringImpl& launchPath, const StringImpl& tar mTargetPath = targetPath; FileStream fileStream; - fileStream.mFP = _wfopen(UTF8Decode(launchPath).c_str(), L"rb"); - if (fileStream.mFP == NULL) + if (!fileStream.Open(launchPath, "rb")) { mDebugger->OutputMessage(StrFormat("Debugger failed to open binary: %s\n", launchPath.c_str())); return NULL; } - DbgModule* dwarf = new COFF(this); + DbgModule* dwarf = CreateDbgModule(); mLaunchBinary = dwarf; dwarf->mDisplayName = GetFileName(launchPath); dwarf->mFilePath = launchPath; @@ -194,14 +205,13 @@ DbgModule* DebugTarget::HotLoad(const StringImpl& fileName, int hotIdx) AutoDbgTime dbgTime("DebugTarget::HotLoad " + fileName); FileStream fileStream; - fileStream.mFP = _wfopen(UTF8Decode(fileName).c_str(), L"rb"); - if (fileStream.mFP == NULL) + if (!fileStream.Open(fileName, "rb")) { mDebugger->OutputMessage(StrFormat("Debugger failed to open binary: %s\n", fileName.c_str())); return NULL; } - DbgModule* dwarf = new COFF(this); + DbgModule* dwarf = CreateDbgModule(); dwarf->mHotIdx = hotIdx; dwarf->mDisplayName = GetFileName(fileName); dwarf->mFilePath = fileName; @@ -221,7 +231,7 @@ DbgModule* DebugTarget::SetupDyn(const StringImpl& filePath, DataStream* stream, //AutoDbgTime dbgTime("DebugTarget::SetupDyn " + filePath); - DbgModule* dwarf = new COFF(this); + DbgModule* dwarf = CreateDbgModule(); dwarf->mFilePath = filePath; dwarf->mImageBase = (intptr)imageBase; if (!dwarf->ReadCOFF(stream, DbgModuleKind_Module)) @@ -272,7 +282,7 @@ String DebugTarget::UnloadDyn(addr_target imageBase) if (mHotHeapAddr != 0) { BfLogDbg("VirtualFreeEx %p %d\n", mHotHeapAddr, mHotHeapReserveSize); - ::VirtualFreeEx(mDebugger->mProcessInfo.hProcess, (void*)(intptr)mHotHeapAddr, 0, MEM_RELEASE); + mDebugger->ReleaseHotHeapMemory(mHotHeapAddr); mHotHeapAddr = 0; } } @@ -429,7 +439,7 @@ bool DebugTarget::FindSymbolAt(addr_target addr, String* outSymbol, addr_target* if (isExecutable) { - addr_target thunkAddr = mDebugger->mCPU->DecodeThunk(addr, dwSymbol->mDbgModule->mOrigImageData); + addr_target thunkAddr = mDebugger->DecodeThunk(addr, dwSymbol->mDbgModule->mOrigImageData); if (thunkAddr != 0) { if (FindSymbolAt(thunkAddr, outSymbol, outOffset, outDWARF)) @@ -817,7 +827,7 @@ DbgSubprogram* DebugTarget::FindSubProgram(addr_target pc, DbgOnDemandKind onDem if ((dwSubprogram->mLineInfo != NULL) && (dwSubprogram->mLineInfo->mHasInlinees)) { if (dwSubprogram->mNeedLineDataFixup) - mDebugger->FixupLineDataForSubprogram(dwSubprogram); + DbgModule::FixupLineDataForSubprogram(dwSubprogram); DbgSubprogram* inlinedSubprogram = NULL; if (dwSubprogram->FindClosestLine(pc, &inlinedSubprogram) != NULL) @@ -2479,7 +2489,7 @@ bool DebugTarget::DecodeInstruction(addr_target address, CPUInst* inst) auto dwarf = FindDbgModuleForAddress(address); if ((dwarf != NULL) && (dwarf->mOrigImageData != NULL)) { - return mDebugger->mCPU->Decode(address, dwarf->mOrigImageData, inst); + return mDebugger->DecodeInstruction(address, dwarf->mOrigImageData, inst); } return false; } @@ -2489,7 +2499,7 @@ DbgBreakKind DebugTarget::GetDbgBreakKind(addr_target address, CPURegisters* reg auto dwarf = FindDbgModuleForAddress(address); if ((dwarf != NULL) && (dwarf->mOrigImageData != NULL)) { - auto result = mDebugger->mCPU->GetDbgBreakKind(address, dwarf->mOrigImageData, registers->mIntRegsArray, objAddr); + auto result = mDebugger->GetDbgBreakKind(address, dwarf->mOrigImageData, registers->mIntRegsArray, objAddr); return result; } return DbgBreakKind_None; @@ -2564,13 +2574,13 @@ void ReportRadixMap(MemReporter* memReporter, RadixMap64& radixMap) auto mid = radixMap.mRoot[rootIdx]; if (mid != NULL) { - memReporter->Add(sizeof(RadixMap64::Mid)); + memReporter->Add(sizeof(typename RadixMap64::Mid)); for (int midIdx = 0; midIdx < RadixMap64::MID_LENGTH; midIdx++) { auto leaf = mid->mLeafs[midIdx]; if (leaf != NULL) { - memReporter->Add(sizeof(RadixMap64::Leaf)); + memReporter->Add(sizeof(typename RadixMap64::Leaf)); } } } diff --git a/IDEHelper/DebugTarget.h b/IDEHelper/DebugTarget.h index 8aa7bd95a..ca4ed4223 100644 --- a/IDEHelper/DebugTarget.h +++ b/IDEHelper/DebugTarget.h @@ -6,6 +6,7 @@ NS_BF_DBG_BEGIN class HotHeap; +class DbgTargetHost; static const int DBG_MAX_LOOKBACK = 64*1024; @@ -33,7 +34,7 @@ struct FindDbgModuleCacheEntry class DebugTarget { public: - WinDebugger* mDebugger; + DbgTargetHost* mDebugger; DbgRadixMap mSymbolMap; DbgAutoStaticEntryBucketMap mAutoStaticEntryBucketMap; @@ -89,11 +90,12 @@ class DebugTarget bool GetValueByNameInBlock_Helper(DbgSubprogram* dwSubprogram, DbgBlock* dwBlock, String& name, WdStackFrame* stackFrame, intptr* outAddr, DbgType** outType, DbgAddrType* outAddrType); public: - DebugTarget(WinDebugger* debugger); + DebugTarget(DbgTargetHost* debugger); ~DebugTarget(); void ClearFindDbgModuleCache(); void AddDbgModule(DbgModule* dbgModule); + DbgModule* CreateDbgModule(); DbgModule* Init(const StringImpl& launchPath, const StringImpl& targetPath, intptr imageBase = 0); void SetupTargetBinary(); void CheckTargetBinary(DbgModule* module); diff --git a/IDEHelper/MiniDumpDebugger.h b/IDEHelper/MiniDumpDebugger.h index 1b2f892e5..b4408b7b6 100644 --- a/IDEHelper/MiniDumpDebugger.h +++ b/IDEHelper/MiniDumpDebugger.h @@ -30,7 +30,7 @@ class MiniDumpDebugger : public WinDebugger MiniDumpDebugger(DebugManager* debugManager, DbgMiniDump* miniDump); ~MiniDumpDebugger(); - void MapMemory(addr_target addr, void* data, intptr_target size); + virtual void MapMemory(addr_target addr, void* data, intptr_target size) override; MappedFile* MapModule(COFF* dbgModule, const StringImpl& fileName); virtual bool PopulateRegisters(CPURegisters* registers) override; diff --git a/IDEHelper/StrBloomMap.h b/IDEHelper/StrBloomMap.h index 85e8277aa..69daf4938 100644 --- a/IDEHelper/StrBloomMap.h +++ b/IDEHelper/StrBloomMap.h @@ -1,7 +1,7 @@ #pragma once #include "DebugCommon.h" -#include "BeefySysLib/Util/BumpAllocator.h" +#include "BeefySysLib/util/BumpAllocator.h" NS_BF_DBG_BEGIN diff --git a/IDEHelper/WinDebugger.cpp b/IDEHelper/WinDebugger.cpp index 11b0d941b..6e8284b77 100644 --- a/IDEHelper/WinDebugger.cpp +++ b/IDEHelper/WinDebugger.cpp @@ -94,132 +94,6 @@ WdBreakpointCondition::~WdBreakpointCondition() ////////////////////////////////////////////////////////////////////////// -DbgEvaluationContext::DbgEvaluationContext(WinDebugger* winDebugger, DbgModule* dbgModule, const StringImpl& expr, DwFormatInfo* formatInfo, DbgTypedValue contextValue) -{ - Init(winDebugger, dbgModule, expr, formatInfo, contextValue); -} - -DbgEvaluationContext::DbgEvaluationContext(WinDebugger* winDebugger, DbgCompileUnit* dbgCompileUnit, const StringImpl& expr, DwFormatInfo* formatInfo, DbgTypedValue contextValue) -{ - DbgModule* dbgModule = NULL; - if (dbgCompileUnit != NULL) - dbgModule = dbgCompileUnit->mDbgModule; - Init(winDebugger, dbgModule, expr, formatInfo, contextValue); -} - -void DbgEvaluationContext::Init(WinDebugger* winDebugger, DbgModule* dbgModule, const StringImpl& expr, DwFormatInfo* formatInfo, DbgTypedValue contextValue) -{ - if (expr.empty()) - { - mParser = NULL; - mReducer = NULL; - mPassInstance = NULL; - mDbgExprEvaluator = NULL; - mExprNode = NULL; - return; - } - - mParser = new BfParser(winDebugger->mBfSystem); - mParser->mCompatMode = true; - mPassInstance = new BfPassInstance(winDebugger->mBfSystem); - auto terminatedExpr = expr + ";"; - mParser->SetSource(terminatedExpr.c_str(), terminatedExpr.length()); - mParser->Parse(mPassInstance); - - mReducer = new BfReducer(); - mReducer->mAlloc = mParser->mAlloc; - mReducer->mSystem = winDebugger->mBfSystem; - mReducer->mPassInstance = mPassInstance; - mReducer->mVisitorPos = BfReducer::BfVisitorPos(mParser->mRootNode); - mReducer->mVisitorPos.MoveNext(); - mReducer->mCompatMode = mParser->mCompatMode; - mReducer->mSource = mParser; - mExprNode = mReducer->CreateExpression(mParser->mRootNode->GetFirst()); - mParser->Close(); - mDbgExprEvaluator = new DbgExprEvaluator(winDebugger, dbgModule, mPassInstance, -1, -1); - - if ((formatInfo != NULL) && (mExprNode != NULL) && (mExprNode->GetSrcEnd() < (int) expr.length())) - { - String formatFlags = expr.Substring(mExprNode->GetSrcEnd()); - String errorString = "Invalid expression"; - if (!winDebugger->ParseFormatInfo(dbgModule, formatFlags, formatInfo, mPassInstance, NULL, NULL, &errorString, contextValue)) - { - mPassInstance->FailAt(errorString, mParser->mSourceData, mExprNode->GetSrcEnd(), (int)expr.length() - mExprNode->GetSrcEnd()); - formatFlags = ""; - } - } - - if (formatInfo != NULL) - { - mDbgExprEvaluator->mExplicitThis = formatInfo->mExplicitThis; - mDbgExprEvaluator->mCallStackIdx = formatInfo->mCallStackIdx; - mDbgExprEvaluator->mLanguage = formatInfo->mLanguage; - } -} - -bool DbgEvaluationContext::HasExpression() -{ - return mExprNode != NULL; -} - -DbgEvaluationContext::~DbgEvaluationContext() -{ - delete mParser; - delete mReducer; - delete mDbgExprEvaluator; - delete mPassInstance; -} - -DbgTypedValue DbgEvaluationContext::EvaluateInContext(DbgTypedValue contextTypedValue) -{ - if (mExprNode == NULL) - return DbgTypedValue(); - mPassInstance->ClearErrors(); - if (contextTypedValue) - { - mDbgExprEvaluator->mExplicitThis = contextTypedValue; - if ((mDbgExprEvaluator->mExplicitThis.mType->IsPointer()) && (mDbgExprEvaluator->mExplicitThis.mType->mTypeParam->WantsRefThis())) - { - mDbgExprEvaluator->mExplicitThis.mType = mDbgExprEvaluator->mExplicitThis.mType->mTypeParam; - mDbgExprEvaluator->mExplicitThis.mSrcAddress = mDbgExprEvaluator->mExplicitThis.mPtr; - mDbgExprEvaluator->mExplicitThis.mPtr = 0; - } - - if ((mDbgExprEvaluator->mExplicitThis.mType->IsCompositeType()) && (!mDbgExprEvaluator->mExplicitThis.mType->WantsRefThis())) - { - if (mDbgExprEvaluator->mExplicitThis.mSrcAddress != 0) - { - mDbgExprEvaluator->mExplicitThis.mType = mDbgExprEvaluator->mDbgModule->GetPointerType(mDbgExprEvaluator->mExplicitThis.mType); - mDbgExprEvaluator->mExplicitThis.mPtr = mDbgExprEvaluator->mExplicitThis.mSrcAddress; - mDbgExprEvaluator->mExplicitThis.mSrcAddress = 0; - } - } - } - if (contextTypedValue.mType != NULL) - mDbgExprEvaluator->mDbgCompileUnit = contextTypedValue.mType->mCompileUnit; - DbgTypedValue exprResult; - auto result = mDbgExprEvaluator->Resolve(mExprNode); - return result; -} - -bool DbgEvaluationContext::HadError() -{ - return mPassInstance->mFailedIdx != 0; -} - -String DbgEvaluationContext::GetErrorStr() -{ - String errorStr = mPassInstance->mErrors[0]->mError; - if (mExprNode != NULL) - { - errorStr += ": "; - errorStr += mExprNode->ToString(); - } - return errorStr; -} - -////////////////////////////////////////////////////////////////////////// - typedef HRESULT(WINAPI* SetThreadDescription_t)(HANDLE hThread, PCWSTR lpThreadDescription); typedef HRESULT(WINAPI* GetThreadDescription_t)(HANDLE hThread, PWSTR* lpThreadDescription); static SetThreadDescription_t gSetThreadDescription = NULL; @@ -3144,7 +3018,7 @@ DbgLineData* WinDebugger::FindLineDataAtAddress(addr_target address, DbgSubprogr if (dwSubprogram == NULL) return NULL; - FixupLineDataForSubprogram(dwSubprogram); + DbgModule::FixupLineDataForSubprogram(dwSubprogram); auto lineData = dwSubprogram->FindClosestLine(address, outSubProgram, outSrcFile, outLineIdx); return lineData; @@ -3154,7 +3028,7 @@ DbgLineData* WinDebugger::FindLineDataInSubprogram(addr_target address, DbgSubpr { auto dwCompileUnit = dwSubprogram->mCompileUnit; - FixupLineDataForSubprogram(dwSubprogram); + DbgModule::FixupLineDataForSubprogram(dwSubprogram); auto lineData = dwSubprogram->FindClosestLine(address); return lineData; } @@ -3341,7 +3215,7 @@ void WinDebugger::CheckBreakpoint(WdBreakpoint* wdBreakpoint, DbgSrcFile* srcFil if (!hasNear) return; - FixupLineDataForSubprogram(dbgSubprogram); + DbgModule::FixupLineDataForSubprogram(dbgSubprogram); for (int lineIdx = 0; lineIdx < dbgLineInfo->mLines.mSize; lineIdx++) { @@ -3376,7 +3250,7 @@ void WinDebugger::CheckBreakpoint(WdBreakpoint* wdBreakpoint, DbgSrcFile* srcFil auto address = dbgSubprogram->GetLineAddr(*lineData); auto subProgram = mDebugTarget->FindSubProgram(address); if (subProgram->mNeedLineDataFixup) - FixupLineDataForSubprogram(subProgram); + DbgModule::FixupLineDataForSubprogram(subProgram); if (subProgram != NULL) highestHotIdx = BF_MAX(highestHotIdx, subProgram->mCompileUnit->mDbgModule->mHotIdx); @@ -5738,349 +5612,6 @@ String WinDebugger::GetMemberList(DbgType* dbgType, const StringImpl& expr, bool return ""; } -bool WinDebugger::ParseFormatInfo(DbgModule* dbgModule, const StringImpl& formatInfoStr, DwFormatInfo* formatInfo, BfPassInstance* bfPassInstance, int* assignExprOffset, String* assignExprString, String* errorString, DbgTypedValue contextTypedValue) -{ - String formatFlags = formatInfoStr; - if (assignExprOffset != NULL) - *assignExprOffset = -1; - - while (formatFlags.length() > 0) - { - formatFlags = Trim(formatFlags); - if (formatFlags.IsEmpty()) - break; - if (formatFlags[0] != ',') - { - return false; - } - else - { - int nextComma = formatFlags.IndexOf(',', 1); - int quotePos = formatFlags.IndexOf('"', 1); - if ((quotePos != -1) && (quotePos < nextComma)) - { - int nextQuotePos = formatFlags.IndexOf('"', quotePos + 1); - if (nextQuotePos != -1) - nextComma = formatFlags.IndexOf(',', nextQuotePos + 1); - } - if (nextComma == -1) - nextComma = formatFlags.length(); - - String formatCmd = formatFlags.Substring(1, nextComma - 1); - formatCmd = Trim(formatCmd); - bool hadError = false; - - if (strncmp(formatCmd.c_str(), "this=", 5) == 0) - { - formatCmd = formatFlags.Substring(1); - formatCmd = Trim(formatCmd); - String thisExpr = formatCmd.Substring(5); - if (thisExpr.empty()) - break; - DbgEvaluationContext dbgEvaluationContext(this, dbgModule, thisExpr, formatInfo); - formatInfo->mExplicitThis = dbgEvaluationContext.EvaluateInContext(contextTypedValue); - if (dbgEvaluationContext.HadError()) - { - if (errorString != NULL) - *errorString = dbgEvaluationContext.GetErrorStr(); - return false; - } - formatFlags = thisExpr.Substring(dbgEvaluationContext.mExprNode->GetSrcEnd()); - continue; - } - else if (strncmp(formatCmd.c_str(), "count=", 6) == 0) - { - formatCmd = formatFlags.Substring(1); - formatCmd = Trim(formatCmd); - String countExpr = formatCmd.Substring(6); - if (countExpr.empty()) - break; - DbgEvaluationContext dbgEvaluationContext(this, dbgModule, countExpr, formatInfo); - DbgTypedValue countValue = dbgEvaluationContext.EvaluateInContext(contextTypedValue); - if ((countValue) && (countValue.mType->IsInteger())) - formatInfo->mOverrideCount = (intptr)countValue.GetInt64(); - if (dbgEvaluationContext.HadError()) - { - if (errorString != NULL) - *errorString = dbgEvaluationContext.GetErrorStr(); - return false; - } - formatFlags = countExpr.Substring(dbgEvaluationContext.mExprNode->GetSrcEnd()); - continue; - } - else if (strncmp(formatCmd.c_str(), "maxcount=", 9) == 0) - { - formatCmd = formatFlags.Substring(1); - formatCmd = Trim(formatCmd); - String countExpr = formatCmd.Substring(9); - if (countExpr.empty()) - break; - DbgEvaluationContext dbgEvaluationContext(this, dbgModule, countExpr, formatInfo); - DbgTypedValue countValue = dbgEvaluationContext.EvaluateInContext(contextTypedValue); - if ((countValue) && (countValue.mType->IsInteger())) - formatInfo->mMaxCount = (intptr)countValue.GetInt64(); - if (dbgEvaluationContext.HadError()) - { - if (errorString != NULL) - *errorString = dbgEvaluationContext.GetErrorStr(); - return false; - } - formatFlags = countExpr.Substring(dbgEvaluationContext.mExprNode->GetSrcEnd()); - continue; - } - else if (strncmp(formatCmd.c_str(), "arraysize=", 10) == 0) - { - formatCmd = formatFlags.Substring(1); - formatCmd = Trim(formatCmd); - String countExpr = formatCmd.Substring(10); - if (countExpr.empty()) - break; - DbgEvaluationContext dbgEvaluationContext(this, dbgModule, countExpr, formatInfo); - DbgTypedValue countValue = dbgEvaluationContext.EvaluateInContext(contextTypedValue); - if ((countValue) && (countValue.mType->IsInteger())) - formatInfo->mArrayLength = (intptr)countValue.GetInt64(); - if (dbgEvaluationContext.HadError()) - { - if (errorString != NULL) - *errorString = dbgEvaluationContext.GetErrorStr(); - return false; - } - formatFlags = countExpr.Substring(dbgEvaluationContext.mExprNode->GetSrcEnd()); - continue; - } - else if (strncmp(formatCmd.c_str(), "assign=", 7) == 0) - { - formatCmd = formatFlags.Substring(1); - formatCmd = Trim(formatCmd); - String assignExpr = formatCmd.Substring(7); - if (assignExpr.empty()) - break; - DbgEvaluationContext dbgEvaluationContext(this, dbgModule, assignExpr, formatInfo); - if (dbgEvaluationContext.HadError()) - { - if (errorString != NULL) - *errorString = dbgEvaluationContext.GetErrorStr(); - return false; - } - if (assignExprOffset != NULL) - { - //TODO: Keep track of the offset directly, this is a hack - *assignExprOffset = (int)formatInfoStr.IndexOf("assign=") + 7; - } - if (assignExprString != NULL) - *assignExprString = dbgEvaluationContext.mExprNode->ToString(); - formatFlags = assignExpr.Substring(dbgEvaluationContext.mExprNode->GetSrcEnd()); - continue; - } - else if (strncmp(formatCmd.c_str(), "refid=", 6) == 0) - { - formatInfo->mReferenceId = formatCmd.Substring(6); - if ((formatInfo->mReferenceId.mLength >= 2) && (formatInfo->mReferenceId[0] == '\"')) - formatInfo->mReferenceId = formatInfo->mReferenceId.Substring(1, formatInfo->mReferenceId.length() - 2); - } - else if (strncmp(formatCmd.c_str(), "action=", 7) == 0) - { - formatInfo->mAction = formatCmd.Substring(7); - if ((formatInfo->mAction.mLength >= 2) && (formatInfo->mAction[0] == '\"')) - formatInfo->mAction = formatInfo->mReferenceId.Substring(1, formatInfo->mReferenceId.length() - 2); - } - else if (strncmp(formatCmd.c_str(), "_=", 2) == 0) - { - formatInfo->mSubjectExpr = formatCmd.Substring(2); - if ((formatInfo->mSubjectExpr.mLength >= 2) && (formatInfo->mSubjectExpr[0] == '\"')) - formatInfo->mSubjectExpr = formatInfo->mSubjectExpr.Substring(1, formatInfo->mSubjectExpr.length() - 2); - } - else if (strncmp(formatCmd.c_str(), "expectedType=", 13) == 0) - { - formatInfo->mExpectedType = formatCmd.Substring(13); - if ((formatInfo->mExpectedType.mLength >= 2) && (formatInfo->mExpectedType[0] == '\"')) - formatInfo->mExpectedType = formatInfo->mExpectedType.Substring(1, formatInfo->mExpectedType.length() - 2); - } - else if (strncmp(formatCmd.c_str(), "namespaceSearch=", 16) == 0) - { - formatInfo->mNamespaceSearch = formatCmd.Substring(16); - if ((formatInfo->mNamespaceSearch.mLength >= 2) && (formatInfo->mNamespaceSearch[0] == '\"')) - formatInfo->mNamespaceSearch = formatInfo->mNamespaceSearch.Substring(1, formatInfo->mNamespaceSearch.length() - 2); - } - else if (formatCmd == "d") - { - formatInfo->mDisplayType = DwDisplayType_Decimal; - } - else if (formatCmd == "x") - { - formatInfo->mDisplayType = DwDisplayType_HexLower; - } - else if (formatCmd == "X") - { - formatInfo->mDisplayType = DwDisplayType_HexUpper; - } - else if (formatCmd == "s") - { - formatInfo->mHidePointers = true; - formatInfo->mDisplayType = DwDisplayType_Ascii; - } - else if (formatCmd == "s8") - { - formatInfo->mHidePointers = true; - formatInfo->mDisplayType = DwDisplayType_Utf8; - } - else if (formatCmd == "s16") - { - formatInfo->mHidePointers = true; - formatInfo->mDisplayType = DwDisplayType_Utf16; - } - else if (formatCmd == "s32") - { - formatInfo->mHidePointers = true; - formatInfo->mDisplayType = DwDisplayType_Utf32; - } - else if (formatCmd == "nd") - { - formatInfo->mIgnoreDerivedClassInfo = true; - } - else if (formatCmd == "na") - { - formatInfo->mHidePointers = true; - } - else if (formatCmd == "nm") - { - formatInfo->mNoMembers = true; - } - else if (formatCmd == "ne") - { - formatInfo->mNoEdit = true; - } - else if (formatCmd == "nv") - { - formatInfo->mNoVisualizers = true; - } - else if (formatCmd == "rawStr") - { - formatInfo->mRawString = true; - } - else if (((!formatCmd.IsEmpty()) && ((formatCmd[0] >= '0') && (formatCmd[0] <= '9'))) || - (formatCmd.StartsWith("("))) - { - String countExpr = formatCmd; - if (countExpr.empty()) - break; - DbgEvaluationContext dbgEvaluationContext(this, dbgModule, countExpr, formatInfo); - DbgTypedValue countValue = dbgEvaluationContext.EvaluateInContext(contextTypedValue); - if ((countValue) && (countValue.mType->IsInteger())) - formatInfo->mArrayLength = (intptr)countValue.GetInt64(); - if (dbgEvaluationContext.HadError()) - { - if (errorString != NULL) - *errorString = dbgEvaluationContext.GetErrorStr(); - return false; - } - formatFlags = countExpr.Substring(dbgEvaluationContext.mExprNode->GetSrcEnd()); - continue; - } - else - hadError = true; - - if (hadError) - { - if (errorString != NULL) - *errorString = "Invalid format flags"; - return false; - } - - formatFlags = formatFlags.Substring(nextComma); - } - } - return true; -} - -String WinDebugger::MaybeQuoteFormatInfoParam(const StringImpl& str) -{ - bool needsQuote = false; - for (int i = 0; i < (int)str.length(); i++) - { - char c = str[i]; - if (c == ',') - needsQuote = true; - } - if (!needsQuote) - return str; - - String qStr = "\""; - qStr += str; - qStr += "\""; - return qStr; -} - -DbgTypedValue WinDebugger::EvaluateInContext(DbgCompileUnit* dbgCompileUnit, const DbgTypedValue& contextTypedValue, const StringImpl& subExpr, DwFormatInfo* formatInfo, String* outReferenceId, String* outErrors) -{ - DbgEvaluationContext dbgEvaluationContext(this, dbgCompileUnit->mDbgModule, subExpr, formatInfo, contextTypedValue); - if (dbgEvaluationContext.mDbgExprEvaluator == NULL) - return DbgTypedValue(); - dbgEvaluationContext.mDbgExprEvaluator->mDbgCompileUnit = dbgCompileUnit; - if (formatInfo != NULL) - { - dbgEvaluationContext.mDbgExprEvaluator->mLanguage = formatInfo->mLanguage; - dbgEvaluationContext.mDbgExprEvaluator->mSubjectExpr = formatInfo->mSubjectExpr; - } - dbgEvaluationContext.mDbgExprEvaluator->mReferenceId = outReferenceId; - auto result = dbgEvaluationContext.EvaluateInContext(contextTypedValue); - if ((formatInfo != NULL) && (dbgEvaluationContext.mDbgExprEvaluator->mCountResultOverride != -1)) - formatInfo->mOverrideCount = dbgEvaluationContext.mDbgExprEvaluator->mCountResultOverride; - if (dbgEvaluationContext.mPassInstance->HasFailed()) - { - if (outErrors != NULL) - { - int errIdx = 0; - for (auto err : dbgEvaluationContext.mPassInstance->mErrors) - { - if (errIdx > 0) - (*outErrors) += "\n"; - (*outErrors) += err->mError; - errIdx++; - } - } - return DbgTypedValue(); - } - return result; -} - -void WinDebugger::DbgVisFailed(DebugVisualizerEntry* debugVis, const StringImpl& evalString, const StringImpl& errors) -{ - bool onlyMemError = errors.StartsWith("Failed to read") && !errors.Contains('\n'); - if ((!debugVis->mShowedError) && (!onlyMemError)) - { - debugVis->mShowedError = true; - String errStr = StrFormat("DbgVis '%s' failed while evaluating condition '%s'\n", debugVis->mName.c_str(), evalString.c_str()); - String spacedErrors = errors; - spacedErrors.Insert(0, " "); - spacedErrors.Replace("\n", "\n "); - errStr += spacedErrors; - OutputMessage(errStr); - } -} - -bool WinDebugger::EvalCondition(DebugVisualizerEntry* debugVis, DbgCompileUnit* dbgCompileUnit, DbgTypedValue typedVal, DwFormatInfo& formatInfo, const StringImpl& condition, const Array& dbgVisWildcardCaptures, String& errorStr) -{ - DwFormatInfo displayStrFormatInfo = formatInfo; - displayStrFormatInfo.mHidePointers = false; - displayStrFormatInfo.mRawString = false; - - String errors; - const String conditionStr = mDebugManager->mDebugVisualizers->DoStringReplace(condition, dbgVisWildcardCaptures); - DbgTypedValue evalResult = EvaluateInContext(dbgCompileUnit, typedVal, conditionStr, &displayStrFormatInfo, NULL, &errors); - if ((!evalResult) || (!evalResult.mType->IsBoolean())) - { - if (formatInfo.mRawString) - return false; - - errorStr += ""; - DbgVisFailed(debugVis, conditionStr, errors); - return false; - } - - return evalResult.mBool; -} - String WinDebugger::GetArrayItems(DbgCompileUnit* dbgCompileUnit, DebugVisualizerEntry* debugVis, DbgType* valueType, DbgTypedValue& curNode, int& count, String* outContinuationData) { DbgEvaluationContext conditionEvaluationContext(this, dbgCompileUnit, debugVis->mCondition); @@ -6567,25 +6098,6 @@ static String WrapWithModifiers(const StringImpl& origName, DbgType* dbgType, Db } } -DebugVisualizerEntry* WinDebugger::FindVisualizerForType(DbgType* dbgType, Array* wildcardCaptures) -{ - auto entry = mDebugManager->mDebugVisualizers->FindEntryForType(dbgType->ToString(DbgLanguage_Unknown, true), dbgType->mCompileUnit->mDbgModule->mDbgFlavor, wildcardCaptures); - - if (entry == NULL) - { - dbgType = dbgType->GetPrimaryType(); - dbgType->PopulateType(); - for (auto baseTypeEntry : dbgType->mBaseTypes) - { - entry = FindVisualizerForType(baseTypeEntry->mBaseType, wildcardCaptures); - if (entry != NULL) - break; - } - } - - return entry; -} - #define GET_FROM(ptr, T) *((T*)(ptr += sizeof(T)) - 1) String WinDebugger::ReadString(DbgTypeCode charType, intptr addr, bool isLocalAddr, intptr maxLength, DwFormatInfo& formatInfo, bool wantStringView) @@ -11603,7 +11115,7 @@ void WinDebugger::GetCodeAddrInfo(intptr addr, intptr inlineCallAddr, String* ou auto inlinedSubProgram = mDebugTarget->FindSubProgram(inlineCallAddr); if (inlinedSubProgram != 0) { - FixupLineDataForSubprogram(inlinedSubProgram->mInlineeInfo->mRootInliner); + DbgModule::FixupLineDataForSubprogram(inlinedSubProgram->mInlineeInfo->mRootInliner); DbgSubprogram* parentSubprogram = inlinedSubProgram->mInlineeInfo->mInlineParent; // Require it be in the inline parent auto foundLine = parentSubprogram->FindClosestLine(inlinedSubProgram->mBlock.mLowPC, &parentSubprogram); if (foundLine != NULL) @@ -11641,7 +11153,7 @@ void WinDebugger::GetCodeAddrInfo(intptr addr, intptr inlineCallAddr, String* ou *outLine = callingLineData->mLine; *outColumn = callingLineData->mColumn; - FixupLineDataForSubprogram(subProgram); + DbgModule::FixupLineDataForSubprogram(subProgram); DbgLineData* dwStartLineData = NULL; DbgLineData* dwEndLineData = NULL; if (subProgram->mLineInfo != NULL) @@ -11813,7 +11325,7 @@ String WinDebugger::GetStackFrameInfo(int stackFrameIdx, intptr* addr, String* o _SetFlags(subProgram); - FixupLineDataForSubprogram(subProgram->mInlineeInfo->mRootInliner); + DbgModule::FixupLineDataForSubprogram(subProgram->mInlineeInfo->mRootInliner); DbgSubprogram* parentSubprogram = subProgram->mInlineeInfo->mInlineParent; // Require it be in the inline parent auto foundLine = parentSubprogram->FindClosestLine(subProgram->mBlock.mLowPC, &parentSubprogram); if (foundLine != NULL) @@ -11874,7 +11386,7 @@ String WinDebugger::GetStackFrameInfo(int stackFrameIdx, intptr* addr, String* o DbgSrcFile* dwSrcFile = NULL; DbgLineData* dwLineData = NULL; - FixupLineDataForSubprogram(dwSubprogram); + DbgModule::FixupLineDataForSubprogram(dwSubprogram); addr_target findAddress = wdStackFrame->GetSourcePC(); DbgSubprogram* specificSubprogram = dwSubprogram; dwLineData = dwSubprogram->FindClosestLine(findAddress, &specificSubprogram); @@ -12024,7 +11536,7 @@ String WinDebugger::Callstack_GetStackFrameOldFileInfo(int stackFrameIdx) auto subProgram = nextStackFrame->mSubProgram; dbgModule = subProgram->mCompileUnit->mDbgModule; - FixupLineDataForSubprogram(subProgram->mInlineeInfo->mRootInliner); + DbgModule::FixupLineDataForSubprogram(subProgram->mInlineeInfo->mRootInliner); DbgSubprogram* parentSubprogram = subProgram->mInlineeInfo->mInlineParent; // Require it be in the inline parent auto foundLine = parentSubprogram->FindClosestLine(subProgram->mBlock.mLowPC, &parentSubprogram); if (foundLine != NULL) @@ -12040,7 +11552,7 @@ String WinDebugger::Callstack_GetStackFrameOldFileInfo(int stackFrameIdx) DbgSubprogram* dwSubprogram = wdStackFrame->mSubProgram; if (dwSubprogram != NULL) { - FixupLineDataForSubprogram(dwSubprogram); + DbgModule::FixupLineDataForSubprogram(dwSubprogram); addr_target findAddress = wdStackFrame->GetSourcePC(); DbgSubprogram* dbgSubprogram = NULL; @@ -12411,7 +11923,7 @@ String WinDebugger::DisassembleAt(intptr inAddress) DbgSrcFile* dwSrcFile = NULL; - FixupLineDataForSubprogram(dwSubProgram); + DbgModule::FixupLineDataForSubprogram(dwSubProgram); DbgLineData* dwLineData = NULL; if (dwSubProgram->mLineInfo != NULL) @@ -12764,7 +12276,7 @@ String WinDebugger::FindLineCallAddresses(intptr inAddress) PopulateRegisters(®isters); auto inlinerSubprogram = dwSubprogram->GetRootInlineParent(); - FixupLineDataForSubprogram(inlinerSubprogram); + DbgModule::FixupLineDataForSubprogram(inlinerSubprogram); if (inlinerSubprogram->mLineInfo->mLines.mSize == 0) return ""; @@ -13462,75 +12974,6 @@ void WinDebugger::FixupLineData(DbgCompileUnit* compileUnit) compileUnit->mNeedsLineDataFixup = false; } -static int CompareLineData(const void* lineDataP1, const void* lineDataP2) -{ - int cmpResult = (int)(((DbgLineData*)lineDataP1)->mRelAddress - ((DbgLineData*)lineDataP2)->mRelAddress); - if (cmpResult != 0) - return cmpResult; - - // A larger contrib size means it's the 'outer' inlinee - cmpResult = -(((DbgLineData*)lineDataP1)->mContribSize - ((DbgLineData*)lineDataP2)->mContribSize); - if (cmpResult != 0) - return cmpResult; - - return -(((DbgLineData*)lineDataP1)->mCtxIdx - ((DbgLineData*)lineDataP2)->mCtxIdx); -} - -void WinDebugger::FixupLineDataForSubprogram(DbgSubprogram* subProgram) -{ - if ((subProgram == NULL) || (!subProgram->mNeedLineDataFixup)) - return; - - BP_ZONE("FixupLineDataForSubprogram"); - - subProgram->mNeedLineDataFixup = false; - if (subProgram->mInlineeInfo != NULL) - FixupLineDataForSubprogram(subProgram->mInlineeInfo->mRootInliner); - - if ((subProgram->mLineInfo == NULL) || (subProgram->mLineInfo->mLines.mSize == 0)) - return; - - //TODO: I think this was covering up a bug in DWARF line encoding? Figure this out -// if (subProgram->mLineInfo->mLines.mSize >= 2) -// { -// DbgLineData* line0 = &subProgram->mLineInfo->mLines[0]; -// DbgLineData* line1 = &subProgram->mLineInfo->mLines[1]; -// -// -// if ((line0->mRelAddress == line1->mRelAddress) && (!line0->IsStackFrameSetup()) && (line1->IsStackFrameSetup())) -// { -// CPUInst inst; -// if (mCPU->Decode(line0->mAddress, subProgram->mCompileUnit->mDbgModule->mOrigImageData, &inst)) -// line1->mAddress += inst.GetLength(); -// } -// } - - qsort(subProgram->mLineInfo->mLines.mVals, subProgram->mLineInfo->mLines.mSize, sizeof(DbgLineData), CompareLineData); - - // If we have multiple lines with the same line/column/context, merge them - if (!subProgram->mLineInfo->mLines.IsEmpty()) - { - auto prevLine = &subProgram->mLineInfo->mLines[0]; - for (int i = 1; i < subProgram->mLineInfo->mLines.mSize; i++) - { - auto nextLine = &subProgram->mLineInfo->mLines[i]; - - if ((nextLine->mLine == prevLine->mLine) && (nextLine->mColumn == prevLine->mColumn) && (nextLine->mCtxIdx == prevLine->mCtxIdx) && - (nextLine->mRelAddress == prevLine->mRelAddress + prevLine->mContribSize)) - { - prevLine->mContribSize += nextLine->mContribSize; - // This messed up inline cases because mContribSize actually INCLUDES inlined lines so it caused the address to skip too far - //nextLine->mRelAddress += nextLine->mContribSize; - //nextLine->mContribSize = 0; - } - else - { - prevLine = nextLine; - } - } - } -} - void WinDebugger::ReserveHotTargetMemory(int size) { HotTargetMemory hotTargetMemory; @@ -13827,6 +13270,70 @@ addr_target WinDebugger::GetTLSOffset(int tlsIndex) return ReadMemory(tlsTable + tlsIndex * sizeof(addr_target)); } +int WinDebugger::GetActiveThreadId() +{ + return mActiveThread->mThreadId; +} + +String WinDebugger::GetActiveThreadName() +{ + return mActiveThread->mName; +} + +void WinDebugger::ClearExplicitStopThread() +{ + mExplicitStopThread = NULL; +} + +int WinDebugger::GetActiveBreakpointHitCount() +{ + if (mActiveBreakpoint != NULL) + return mActiveBreakpoint->GetHeadBreakpoint()->mHitCount; + return 0; +} + +String WinDebugger::GetActiveBreakpointCondition() +{ + if ((mActiveBreakpoint != NULL) && (mActiveBreakpoint->mCondition != NULL)) + return mActiveBreakpoint->GetHeadBreakpoint()->mCondition->mExpr; + return ""; +} + +int WinDebugger::GetTargetProcessId() +{ + return mProcessInfo.dwProcessId; +} + +bool WinDebugger::WantsHotHeap() +{ + return (mHotSwapEnabled) && (mDbgProcessId == 0); +} + +addr_target WinDebugger::ReserveHotHeapMemory(addr_target address, int size) +{ + return (addr_target)(intptr)::VirtualAllocEx(mProcessInfo.hProcess, (void*)(intptr)address, size, MEM_RESERVE, PAGE_EXECUTE_READWRITE); +} + +void WinDebugger::ReleaseHotHeapMemory(addr_target address) +{ + ::VirtualFreeEx(mProcessInfo.hProcess, (void*)(intptr)address, 0, MEM_RELEASE); +} + +addr_target WinDebugger::DecodeThunk(addr_target address, DbgModuleMemoryCache* memoryCache) +{ + return mCPU->DecodeThunk(address, memoryCache); +} + +bool WinDebugger::DecodeInstruction(addr_target address, DbgModuleMemoryCache* memoryCache, CPUInst* inst) +{ + return mCPU->Decode(address, memoryCache, inst); +} + +DbgBreakKind WinDebugger::GetDbgBreakKind(addr_target address, DbgModuleMemoryCache* memoryCache, intptr_target* regs, intptr_target* outObjectPtr) +{ + return mCPU->GetDbgBreakKind(address, memoryCache, regs, outObjectPtr); +} + bool WinDebugger::WriteInstructions(intptr address, void* src, uint64 length) { SIZE_T dwBytesWritten = 0; diff --git a/IDEHelper/WinDebugger.h b/IDEHelper/WinDebugger.h index 64d7fc65e..ca3413b5a 100644 --- a/IDEHelper/WinDebugger.h +++ b/IDEHelper/WinDebugger.h @@ -5,6 +5,7 @@ #include "DbgSymSrv.h" #include "DebugTarget.h" #include "DbgExprEvaluator.h" +#include "DbgTargetHost.h" #include "Debugger.h" #include "HotHeap.h" #include "COFF.h" @@ -99,28 +100,6 @@ enum BreakpointType BreakpointType_Stepping }; -struct DwFormatInfo; - -class DbgEvaluationContext -{ -public: - BfParser* mParser; - BfReducer* mReducer; - BfPassInstance* mPassInstance; - DbgExprEvaluator* mDbgExprEvaluator; - BfExpression* mExprNode; - -public: - DbgEvaluationContext(WinDebugger* winDebugger, DbgModule* dbgModule, const StringImpl& expr, DwFormatInfo* formatInfo = NULL, DbgTypedValue contextValue = DbgTypedValue()); - DbgEvaluationContext(WinDebugger* winDebugger, DbgCompileUnit* dbgCompileUnit, const StringImpl& expr, DwFormatInfo* formatInfo = NULL, DbgTypedValue contextValue = DbgTypedValue()); - void Init(WinDebugger* winDebugger, DbgModule* dbgModule, const StringImpl& expr, DwFormatInfo* formatInfo = NULL, DbgTypedValue contextValue = DbgTypedValue()); - bool HasExpression(); - ~DbgEvaluationContext(); - DbgTypedValue EvaluateInContext(DbgTypedValue contextTypedValue); - String GetErrorStr(); - bool HadError(); -}; - class WdBreakpointCondition { public: @@ -199,43 +178,6 @@ enum StepType StepType_ToTempBreakpoint }; -class WdStackFrame -{ -public: - CPURegisters mRegisters; - bool mIsStart; - bool mIsEnd; - bool mInInlineMethod; - bool mInInlineCall; // Means the frame above us is inlined - - DbgSubprogram* mSubProgram; - bool mHasGottenSubProgram; - Array mRegForms; - -public: - WdStackFrame() - { - mSubProgram = NULL; - mHasGottenSubProgram = false; - mIsStart = true; - mIsEnd = false; - mInInlineMethod = false; - mInInlineCall = false; - } - - addr_target GetSourcePC() - { - // 'PC' is return address of call in these cases, so subtract 1 for cases where - // we want to bring it back into the calling block range (note that this doesn't - // properly determine the actual starting address of the call instruction, though) - if ((!mIsStart) && (!mInInlineCall)) - return mRegisters.GetPC() - 1; - return mRegisters.GetPC(); - } -}; - -typedef WdStackFrame CPUStackFrame; - struct WdThreadInfo { public: @@ -327,18 +269,6 @@ struct WdMemoryBreakpointBind } }; -struct DbgPendingDebugInfoLoad -{ - DbgModule* mModule; - bool mAllowRemote; - - DbgPendingDebugInfoLoad() - { - mModule = NULL; - mAllowRemote = false; - } -}; - struct WinHotThreadState { CPURegisters mRegisters; @@ -372,7 +302,7 @@ class WinDbgHeapData struct DwFormatInfo; -class WinDebugger : public Debugger +class WinDebugger : public DbgTargetHost { public: SyncEvent mContinueEvent; @@ -382,7 +312,6 @@ class WinDebugger : public Debugger int mActiveHotIdx; volatile bool mShuttingDown; - volatile bool mIsRunning; bool mDestroying; String mLaunchPath; String mTargetPath; @@ -393,7 +322,6 @@ class WinDebugger : public Debugger Array mEnvBlock; DebugTarget* mEmptyDebugTarget; DebugTarget* mDebugTarget; - BfSystem* mBfSystem; CPU* mCPU; PROCESS_INFORMATION mProcessInfo; BfDbgAttachFlags mDbgAttachFlags; @@ -418,7 +346,6 @@ class WinDebugger : public Debugger WdThreadInfo* mExplicitStopThread; // Don't try to show first frame-with-source for this thread (when we hit breakpoint in asm, encounter exception, etc) DEBUG_EVENT mDebugEvent; bool mGotStartupEvent; - int mPageSize; DbgSymSrv mDbgSymSrv; DbgSymRequest* mActiveSymSrvRequest; DWORD mDebuggerThreadId; @@ -429,10 +356,8 @@ class WinDebugger : public Debugger Array mBreakpoints; Dictionary mBreakpointAddrMap; Array mFreeMemoryBreakIndices; - Array mCallStack; Dictionary> mSavedCallStacks; bool mIsPartialCallStack; - int mRequestedStackFrameIdx; // -1 means to show mShowPCOverride, -2 means "auto" stop, -3 means breakpoint - normally 0 but during inlining the address can be ambiguous int mBreakStackFrameIdx; addr_target mShowPCOverride; Dictionary mThreadMap; @@ -453,13 +378,10 @@ class WinDebugger : public Debugger addr_target mStoredReturnValueAddr; addr_target mLastValidStepIntoPC; bool mIsStepIntoSpecific; - CPURegisters mDebugEvalSetRegisters; DbgPendingExpr* mDebugPendingExpr; WdThreadInfo mDebugEvalThreadInfo; // Copy of thread info when eval started Array mPendingImageLoad; - Dictionary mPendingDebugInfoLoad; Array mPendingDebugInfoRequests; - HashSet mLiteralSet; EXCEPTION_RECORD mCurException; bool mIsContinuingFromException; @@ -478,14 +400,14 @@ class WinDebugger : public Debugger uint8 mMemCacheData[WD_MEMCACHE_SIZE]; public: - void Fail(const StringImpl& error); + virtual void Fail(const StringImpl& error) override; void TryGetThreadName(WdThreadInfo* threadInfo); void ThreadRestorePause(WdThreadInfo* onlyPauseThread, WdThreadInfo* dontPauseThread); void ThreadRestoreUnpause(); void UpdateThreadDebugRegisters(WdThreadInfo* threadInfo); void UpdateThreadDebugRegisters(); void ValidateBreakpoints(); - void PhysSetBreakpoint(addr_target address); + virtual void PhysSetBreakpoint(addr_target address) override; void SetBreakpoint(addr_target address, bool fromRehup = false); void SetTempBreakpoint(addr_target address); void PhysRemoveBreakpoint(addr_target address); @@ -505,33 +427,27 @@ class WinDebugger : public Debugger bool IsMemoryBreakpointSizeValid(addr_target addr, int size); bool HasMemoryBreakpoint(addr_target addr, int size); bool PopulateRegisters(CPURegisters* registers, BF_CONTEXT& lcContext); - virtual bool PopulateRegisters(CPURegisters* registers); + virtual bool PopulateRegisters(CPURegisters* registers) override; bool RollBackStackFrame(CPURegisters* registers, bool isStackStart); - bool SetHotJump(DbgSubprogram* oldSubprogram, addr_target newTarget, int newTargetSize); + virtual bool SetHotJump(DbgSubprogram* oldSubprogram, addr_target newTarget, int newTargetSize) override; DbgSubprogram* TryFollowHotJump(DbgSubprogram* subprogram, addr_target addr); - bool ParseFormatInfo(DbgModule* dbgModule, const StringImpl& formatInfoStr, DwFormatInfo* formatInfo, BfPassInstance* bfPassInstance, int* assignExprOffset, String* assignExpr = NULL, String* errorString = NULL, DbgTypedValue contextTypedValue = DbgTypedValue()); - String MaybeQuoteFormatInfoParam(const StringImpl& str); - void DbgVisFailed(DebugVisualizerEntry* debugVis, const StringImpl& evalString, const StringImpl& errors); - DbgTypedValue EvaluateInContext(DbgCompileUnit* dbgCompileUnit, const DbgTypedValue& contextTypedValue, const StringImpl& subExpr, DwFormatInfo* formatInfo = NULL, String* outReferenceId = NULL, String* outErrors = NULL); - bool EvalCondition(DebugVisualizerEntry* debugVis, DbgCompileUnit* dbgCompileUnit, DbgTypedValue typedVal, DwFormatInfo& formatInfo, const StringImpl& condition, const Array& dbgVisWildcardCaptures, String& errorStr); DwDisplayInfo* GetDisplayInfo(const StringImpl& referenceId); - bool ProcessEvalString(DbgCompileUnit* dbgCompileUnit, DbgTypedValue useTypedValue, String& evalStr, String& displayString, DwFormatInfo& formatInfo, DebugVisualizerEntry* debugVis, bool limitLength); + virtual bool ProcessEvalString(DbgCompileUnit* dbgCompileUnit, DbgTypedValue useTypedValue, String& evalStr, String& displayString, DwFormatInfo& formatInfo, DebugVisualizerEntry* debugVis, bool limitLength) override; String ReadString(DbgTypeCode charType, intptr addr, bool isLocalAddr, intptr maxLength, DwFormatInfo& formatInfo, bool wantStringView); String DbgTypedValueToString(const DbgTypedValue& typedValue, const StringImpl& expr, DwFormatInfo& formatFlags, DbgExprEvaluator* optEvaluator, bool fullPrecision = false); bool ShouldShowStaticMember(DbgType* dbgType, DbgVariable* member); String GetMemberList(DbgType* dbgType, const StringImpl& expr, bool isPtr, bool isStatic, bool forceCast = false, bool isSplat = false, bool isReadOnly = false); - DebugVisualizerEntry* FindVisualizerForType(DbgType* dbgType, Array* wildcardCaptures); - void ReserveHotTargetMemory(int size); - addr_target AllocHotTargetMemory(int size, bool canExecute, bool canWrite, int* outAllocSize); - void ReleaseHotTargetMemory(addr_target addr, int size); + virtual void ReserveHotTargetMemory(int size) override; + virtual addr_target AllocHotTargetMemory(int size, bool canExecute, bool canWrite, int* outAllocSize) override; + virtual void ReleaseHotTargetMemory(addr_target addr, int size) override; void CleanupHotHeap(); - int EnableWriting(intptr address, int size); - int SetProtection(intptr address, int size, int prot); + virtual int EnableWriting(intptr address, int size) override; + virtual int SetProtection(intptr address, int size, int prot) override; void EnableMemCache(); void DisableMemCache(); - template T ReadMemory(intptr addr, bool local = false, bool* failed = NULL); - bool WriteInstructions(intptr address, void* src, uint64 length); + using DbgTargetHost::ReadMemory; + virtual bool WriteInstructions(intptr address, void* src, uint64 length) override; template bool WriteMemory(intptr addr, T val); virtual DbgMemoryFlags GetMemoryFlags(intptr address) override; @@ -542,15 +458,15 @@ class WinDebugger : public Debugger void CheckNonDebuggerBreak(); bool HasSteppedIntoCall(); void StepLineTryPause(addr_target address, bool requireExactMatch); - void PushValue(CPURegisters* registers, int64 val); - void PushValue(CPURegisters* registers, const DbgTypedValue& typedValue); - void SetThisRegister(CPURegisters* registers, addr_target val); - void AddParamValue(int paramIdx, bool hadThis, CPURegisters* registers, const DbgTypedValue& typedValue); - bool CheckNeedsSRetArgument(DbgType* retType); - DbgTypedValue ReadReturnValue(CPURegisters* registers, DbgType* type); - bool SetRegisters(CPURegisters* registers); - void SaveAllRegisters(); - void RestoreAllRegisters(); + virtual void PushValue(CPURegisters* registers, int64 val) override; + virtual void PushValue(CPURegisters* registers, const DbgTypedValue& typedValue) override; + virtual void SetThisRegister(CPURegisters* registers, addr_target val) override; + virtual void AddParamValue(int paramIdx, bool hadThis, CPURegisters* registers, const DbgTypedValue& typedValue) override; + virtual bool CheckNeedsSRetArgument(DbgType* retType) override; + virtual DbgTypedValue ReadReturnValue(CPURegisters* registers, DbgType* type) override; + virtual bool SetRegisters(CPURegisters* registers) override; + virtual void SaveAllRegisters() override; + virtual void RestoreAllRegisters() override; String GetArrayItems(DbgCompileUnit* dbgCompileUnit, DebugVisualizerEntry* debugVis, DbgType* valueType, DbgTypedValue& curNode, int& count, String* outContinuationData); String GetLinkedListItems(DbgCompileUnit* dbgCompileUnit, DebugVisualizerEntry* debugVis, addr_target endNodePtr, DbgType* valueType, DbgTypedValue& curNode, int& count, String* outContinuationData); String GetDictionaryItems(DbgCompileUnit* dbgCompileUnit, DebugVisualizerEntry* debugVis, DbgTypedValue dictValue, int bucketIdx, int nodeIdx, int& count, String* outContinuationData); @@ -561,9 +477,8 @@ class WinDebugger : public Debugger void DebugThreadProc(); bool DoOpenFile(const StringImpl& fileName, const StringImpl& args, const StringImpl& workingDir, const Array& envBlock, DbgOpenFileFlags openFileFlags); - DbgTypedValue GetRegister(const StringImpl& regName, DbgLanguage language, CPURegisters* registers, Array* regForms = NULL); + virtual DbgTypedValue GetRegister(const StringImpl& regName, DbgLanguage language, CPURegisters* registers, Array* regForms = NULL) override; void FixupLineData(DbgCompileUnit* compileUnit); - void FixupLineDataForSubprogram(DbgSubprogram* subProgram); DbgModule* GetCallStackDbgModule(int callStackIdx); DbgSubprogram* GetCallStackSubprogram(int callStackIdx); DbgCompileUnit* GetCallStackCompileUnit(int callStackIdx); @@ -624,7 +539,7 @@ class WinDebugger : public Debugger virtual String Evaluate(const StringImpl& expr, int callStackIdx, int cursorPos, int language, DwEvalExpressionFlags expressionFlags) override; virtual String EvaluateToAddress(const StringImpl& expr, int callStackIdx, int cursorPos) override; virtual String EvaluateAtAddress(const StringImpl& expr, intptr atAddr, int cursorPos) override; - virtual bool AssignToReg(int callStackIdx, DbgTypedValue reg, DbgTypedValue value, String& outError); + virtual bool AssignToReg(int callStackIdx, DbgTypedValue reg, DbgTypedValue value, String& outError) override; virtual String GetCollectionContinuation(const StringImpl& continuationData, int callStackIdx, int count) override; virtual String GetAutoExpressions(int callStackIdx, uint64 memoryRangeStart, uint64 memoryRangeLen) override; virtual String GetAutoLocals(int callStackIdx, bool showRegs) override; @@ -644,7 +559,7 @@ class WinDebugger : public Debugger virtual int GetBreakStackFrameIdx() override; virtual bool ReadMemory(intptr address, uint64 length, void* dest, bool local = false) override; virtual bool WriteMemory(intptr address, void* src, uint64 length) override; - addr_target GetTLSOffset(int tlsIndex); + virtual addr_target GetTLSOffset(int tlsIndex) override; virtual void UpdateRegisterUsage(int stackFrameIdx) override; virtual void UpdateCallStackMethod(int stackFrameIdx) override; virtual void GetCodeAddrInfo(intptr addr, intptr inlineCallAddr, String* outFile, int* outHotIdx, int* outDefLineStart, int* outDefLineEnd, int* outLine, int* outColumn) override; @@ -682,7 +597,19 @@ class WinDebugger : public Debugger virtual void ReportMemory(MemReporter* memReporter) override; virtual bool IsOnDemandDebugger() override { return false; } - virtual bool IsMiniDumpDebugger() { return false; } + virtual bool IsMiniDumpDebugger() override { return false; } + virtual int GetActiveThreadId() override; + virtual String GetActiveThreadName() override; + virtual void ClearExplicitStopThread() override; + virtual int GetActiveBreakpointHitCount() override; + virtual String GetActiveBreakpointCondition() override; + virtual int GetTargetProcessId() override; + virtual bool WantsHotHeap() override; + virtual addr_target ReserveHotHeapMemory(addr_target address, int size) override; + virtual void ReleaseHotHeapMemory(addr_target address) override; + virtual addr_target DecodeThunk(addr_target address, DbgModuleMemoryCache* memoryCache) override; + virtual bool DecodeInstruction(addr_target address, DbgModuleMemoryCache* memoryCache, CPUInst* inst) override; + virtual DbgBreakKind GetDbgBreakKind(addr_target address, DbgModuleMemoryCache* memoryCache, intptr_target* regs, intptr_target* outObjectPtr) override; virtual bool GetEmitSource(const StringImpl& filePath, String& outText); }; @@ -692,41 +619,6 @@ template bool WinDebugger::WriteMemory(intptr addr, T val) return WriteProcessMemory(mProcessInfo.hProcess, (void*)(intptr)addr, &val, (SIZE_T)sizeof(T), &dwWriteBytes) != 0; } -template T WinDebugger::ReadMemory(intptr addr, bool local, bool* failed) -{ - bool success = true; - T val; - memset(&val, 0, sizeof(T)); - if (local) - { - if (addr != 0) - { - memcpy(&val, (void*)(intptr)addr, sizeof(T)); - /*__try - { - memcpy(&val, (void*)(intptr)addr, sizeof(T)); - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - success = false; - }*/ - } - else - success = false; - } - else - { - //SIZE_T dwReadBytes; - memset(&val, 0, sizeof(T)); - //success = ReadProcessMemory(mProcessInfo.hProcess, (void*)(intptr)addr, &val, (SIZE_T)sizeof(T), &dwReadBytes) != 0; - success = ReadMemory(addr, (int)sizeof(T), &val); - } - - if (failed != NULL) - *failed = !success; - return val; -} - addr_target DecodeTargetDataPtr(const char*& strRef); NS_BF_DBG_END