diff --git a/IDE/src/Debugger/DebugManager.bf b/IDE/src/Debugger/DebugManager.bf index 48f5b15f..0edd48d6 100644 --- a/IDE/src/Debugger/DebugManager.bf +++ b/IDE/src/Debugger/DebugManager.bf @@ -340,6 +340,9 @@ namespace IDE.Debugger [CallingConvention(.Stdcall),CLink] static extern void Debugger_SetSymSrvOptions(char8* symCacheDir, char8* symSrvStr, int32 flags); + [CallingConvention(.Stdcall),CLink] + static extern void Debugger_SetSourcePathRemap(char8* remapStr); + [CallingConvention(.Stdcall),CLink] static extern void Debugger_CancelSymSrv(); @@ -469,6 +472,11 @@ namespace IDE.Debugger Debugger_SetSymSrvOptions(symCacheDir, symSrvStr, (int32)symSrvFlags); } + public void SetSourcePathRemap(String remapStr) + { + Debugger_SetSourcePathRemap(remapStr); + } + public bool OpenMiniDump(String file) { mIsComptimeDebug = false; diff --git a/IDE/src/Settings.bf b/IDE/src/Settings.bf index 5323cfb1..40d5c598 100644 --- a/IDE/src/Settings.bf +++ b/IDE/src/Settings.bf @@ -250,6 +250,19 @@ namespace IDE } gApp.mDebugger.SetSymSrvOptions(mSymCachePath, symbolServerPath, .None); + String remapStr = scope .(); + for (var entry in mAutoFindPaths) + { + if (entry.Contains('@')) + { + if (!remapStr.IsEmpty) + remapStr.Append("\n"); + remapStr.Append(entry); + } + } + remapStr.Replace('@', '='); + gApp.mDebugger.SetSourcePathRemap(remapStr); + mProfileSampleRate = Math.Clamp(mProfileSampleRate, 10, 10000); } diff --git a/IDE/src/ui/SourceViewPanel.bf b/IDE/src/ui/SourceViewPanel.bf index 1112ce42..7cbbe0f3 100644 --- a/IDE/src/ui/SourceViewPanel.bf +++ b/IDE/src/ui/SourceViewPanel.bf @@ -320,7 +320,8 @@ namespace IDE.ui { for (let searchPath in gApp.mSettings.mDebuggerSettings.mAutoFindPaths) { - SearchPath(searchPath); + if (!searchPath.Contains('@')) + SearchPath(searchPath); } } diff --git a/IDEHelper/COFF.cpp b/IDEHelper/COFF.cpp index 33256b89..aa443f61 100644 --- a/IDEHelper/COFF.cpp +++ b/IDEHelper/COFF.cpp @@ -48,6 +48,22 @@ static const char* DataGetString(uint8*& data) return prevVal; } +static const char* SafeDataGetString(uint8*& data, uint8* dataEnd) +{ + if (data >= dataEnd) + return NULL; + + const char* prevVal = (const char*)data; + while (*data != 0) + { + data++; + if (data >= dataEnd) + return NULL; + } + data++; + return prevVal; +} + #define CREATE_PRIMITIVE(pdbTypeCode, dwTypeCode, typeName, type) \ BP_ALLOC_T(DbgType); \ dbgType = mAlloc.Alloc(); \ @@ -5230,7 +5246,9 @@ bool COFF::CvParseDBI(int wantAge) while (data < dataEnd) { int offset = (int)(data - dataStart); - const char* fileName = DataGetString(data); + const char* fileName = SafeDataGetString(data, dataEnd); + if (fileName == NULL) + break; //DbgSrcFile* srcFile = AddSrcFile(mMasterCompileUnit, fileName); //fileTable.insert(std::make_pair(offset, srcFile)); }*/ @@ -5249,6 +5267,15 @@ bool COFF::CvParseDBI(int wantAge) uint8* strTabData = data; data += strTabSize; + int pdbNameIdx = -1; + for (auto moduleInfo : mCvModuleInfo) + { + if (moduleInfo->mCompilerNameCount > 0) + pdbNameIdx = moduleInfo->mCompilerNameCount; + } + if ((pdbNameIdx > 0) && (pdbNameIdx < strTabSize)) + mOrigPDBPath = (const char*)strTabData + pdbNameIdx; + GET_INTO(int32, strTabEntryCount); for (int entryIdx = 0; entryIdx < strTabEntryCount; entryIdx++) { diff --git a/IDEHelper/COFF.h b/IDEHelper/COFF.h index 71b4f6c5..a403d9ca 100644 --- a/IDEHelper/COFF.h +++ b/IDEHelper/COFF.h @@ -249,6 +249,7 @@ public: CvStreamReader mCvSymbolRecordReader; StringT<128> mPDBPath; + StringT<128> mOrigPDBPath; SafeMemStream* mCvDataStream; CvStringTable mStringTable; diff --git a/IDEHelper/DbgModule.cpp b/IDEHelper/DbgModule.cpp index 7898d073..d98b318b 100644 --- a/IDEHelper/DbgModule.cpp +++ b/IDEHelper/DbgModule.cpp @@ -879,7 +879,6 @@ void DbgSrcFile::RemoveLines(DbgModule* debugModule) { // Fast-out case mLineDataRefs.Clear(); - mFirstLineDataDbgModule = NULL; return; } @@ -927,8 +926,63 @@ void DbgSrcFile::RehupLineData() } } +void DbgSrcFile::VerifyPath() +{ + if (mVerifiedPath) + return; + + if (mLineDataRefs.IsEmpty()) + return; + + if (!::FileExists(mFilePath)) + { + bool didReplace = false; + for (auto& kv : gDebugManager->mSourcePathRemap) + { + if (mFilePath.StartsWith(kv.mKey, StringImpl::CompareKind_OrdinalIgnoreCase)) + { + mFilePath.Remove(0, kv.mKey.mLength); + mFilePath.Insert(0, kv.mValue); + didReplace = true; + } + } + + if (!didReplace) + { + HashSet checkedModules; + for (auto& lineDataRef : mLineDataRefs) + { + auto dbgModule = lineDataRef->mCompileUnit->mDbgModule; + if (checkedModules.Add(dbgModule)) + { + if (dbgModule->mDbgFlavor == DbgFlavor_MS) + { + COFF* coff = (COFF*)dbgModule; + + if ((!coff->mOrigPDBPath.IsEmpty()) && (!coff->mOrigPDBPath.Equals(coff->mPDBPath, StringImpl::CompareKind_OrdinalIgnoreCase))) + { + String relFilePath = GetRelativePath(mFilePath, coff->mOrigPDBPath); + String checkActualFilePath = GetAbsPath(relFilePath, coff->mPDBPath); + + if (FileExists(checkActualFilePath)) + { + mFilePath = checkActualFilePath; + break; + } + } + } + } + } + } + } + + mVerifiedPath = true; +} + const String& DbgSrcFile::GetLocalPath() { + if (!mVerifiedPath) + VerifyPath(); return (!mLocalPath.IsEmpty()) ? mLocalPath : mFilePath; } @@ -4931,6 +4985,7 @@ addr_target DbgModule::GetHotTargetAddress(DbgHotTargetSection* hotTargetSection if (hotTargetSection->mNoTargetAlloc) return 0; + BfLogDbg("DbgModule::GetHotTargetAddress %p %p\n", this, hotTargetSection); hotTargetSection->mTargetSectionAddr = mDebugger->AllocHotTargetMemory(hotTargetSection->mDataSize, hotTargetSection->mCanExecute, hotTargetSection->mCanWrite, &hotTargetSection->mTargetSectionSize); hotTargetSection->mImageOffset = (int)mImageSize; @@ -5207,6 +5262,8 @@ void DbgModule::ParseHotTargetSections(DataStream* stream, addr_target* resolved void DbgModule::CommitHotTargetSections() { + BfLogDbg("DbgModule::CommitHotTargetSections %p\n", this); + for (int sectNum = 0; sectNum < (int)mHotTargetSections.size(); sectNum++) { if (mHotTargetSections[sectNum] != NULL) @@ -5580,7 +5637,7 @@ bool DbgModule::ReadCOFF(DataStream* stream, DbgModuleKind moduleKind) //if (this == mDebugTarget->mTargetBinary) //mMemReporter = new MemReporter(); - BfLogDbg("DbgModule::ReadCOFF %s\n", mFilePath.c_str()); + BfLogDbg("DbgModule::ReadCOFF %p %s\n", this, mFilePath.c_str()); if (mMemReporter != NULL) { diff --git a/IDEHelper/DbgModule.h b/IDEHelper/DbgModule.h index edd59a56..c2dd9eda 100644 --- a/IDEHelper/DbgModule.h +++ b/IDEHelper/DbgModule.h @@ -729,11 +729,11 @@ public: String mLocalPath; bool mHadLineData; bool mHasLineDataFromMultipleModules; + bool mVerifiedPath; DbgFileExistKind mFileExistKind; int mStepFilterVersion; DbgHashKind mHashKind; uint8 mHash[32]; - DbgModule* mFirstLineDataDbgModule; // Just used to detect mHasLineDataFromMultipleModules Array mDeferredRefs; Array mLineDataRefs; Array mHotReplacedDbgLineInfo; // Indexing starts at -1 @@ -742,8 +742,8 @@ public: DbgSrcFile() { mHasLineDataFromMultipleModules = false; - mFirstLineDataDbgModule = NULL; mHadLineData = false; + mVerifiedPath = false; mHashKind = DbgHashKind_None; mFileExistKind = DbgFileExistKind_NotChecked; mStepFilterVersion = 0; @@ -759,6 +759,7 @@ public: void RemoveLines(DbgModule* debugModule); void RemoveLines(DbgModule* debugModule, DbgSubprogram* dbgSubprogram, bool isHotReplaced); void RehupLineData(); + void VerifyPath(); const String& GetLocalPath(); void GetHash(String& hashStr); }; diff --git a/IDEHelper/DbgSymSrv.cpp b/IDEHelper/DbgSymSrv.cpp index bb8d8517..01a622f7 100644 --- a/IDEHelper/DbgSymSrv.cpp +++ b/IDEHelper/DbgSymSrv.cpp @@ -132,11 +132,11 @@ void DbgSymRequest::SearchLocal() return; } + uint8 outGuid[16]; + int32 outAge; if (mPDBRequested.IndexOf('\\') != -1) // Do we have an absolute path at all? System dlls won't. { // Check actual path - uint8 outGuid[16]; - int32 outAge; if (CheckPDBData(mPDBRequested, outGuid, outAge)) { mFinalPDBPath = mPDBRequested; @@ -156,6 +156,18 @@ void DbgSymRequest::SearchLocal() } } } + else + { + String checkPath = ::GetFileDir(mModulePath); + checkPath += "\\"; + checkPath += mPDBRequested; + + if (CheckPDBData(checkPath, outGuid, outAge)) + { + mFinalPDBPath = checkPath; + return; + } + } mMayBeOld = true; } diff --git a/IDEHelper/DebugManager.cpp b/IDEHelper/DebugManager.cpp index 09cf16a1..eb8b72f2 100644 --- a/IDEHelper/DebugManager.cpp +++ b/IDEHelper/DebugManager.cpp @@ -826,6 +826,38 @@ BF_EXPORT void BF_CALLTYPE Debugger_SetSymSrvOptions(const char* symCacheDir, co gDebugManager->SetSourceServerCacheDir(); } +BF_EXPORT void BF_CALLTYPE Debugger_SetSourcePathRemap(const char* remapStr) +{ + AutoCrit autoCrit(gDebugManager->mCritSect); + + gDebugManager->mSourcePathRemap.Clear(); + + const char* startStr = remapStr; + for (const char* cPtr = remapStr; true; cPtr++) + { + if ((*cPtr == '\n') || (*cPtr == 0)) + { + String remapStr = String(startStr, cPtr - startStr); + remapStr.Trim(); + + int eqPos = (int)remapStr.IndexOf('='); + if (eqPos != -1) + { + auto keyStr = remapStr.Substring(0, eqPos); + keyStr.Trim(); + auto valueStr = remapStr.Substring(eqPos + 1); + valueStr.Trim(); + gDebugManager->mSourcePathRemap[keyStr] = valueStr; + } + + startStr = cPtr; + } + + if (*cPtr == 0) + break; + } +} + BF_EXPORT bool BF_CALLTYPE Debugger_OpenMiniDump(const char* fileName) { #ifdef BF_PLATFORM_WINDOWS diff --git a/IDEHelper/DebugManager.h b/IDEHelper/DebugManager.h index 2c3ce576..97b0a6ea 100644 --- a/IDEHelper/DebugManager.h +++ b/IDEHelper/DebugManager.h @@ -75,6 +75,7 @@ public: DebugVisualizers* mDebugVisualizers; DwDisplayInfo mDefaultDisplayInfo; Dictionary mDisplayInfos; + Dictionary mSourcePathRemap; bool mStepOverExternalFiles; NetManager* mNetManager; diff --git a/IDEHelper/DebugTarget.cpp b/IDEHelper/DebugTarget.cpp index f79a26ae..9c8ba8f4 100644 --- a/IDEHelper/DebugTarget.cpp +++ b/IDEHelper/DebugTarget.cpp @@ -345,6 +345,7 @@ DbgSrcFile* DebugTarget::GetSrcFile(const String& srcFilePath) mSrcFiles.TryGetValue(*origSrcPath, &srcFile); } } + return srcFile; }