瀏覽代碼

Improved ability to locate source files from moved PDB

Brian Fiete 2 年之前
父節點
當前提交
d405104757

+ 8 - 0
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;

+ 13 - 0
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);
 			}
 

+ 2 - 1
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);
 				}
 			}
 

+ 28 - 1
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<DbgType>(); \
@@ -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++)
 	{

+ 1 - 0
IDEHelper/COFF.h

@@ -249,6 +249,7 @@ public:
 	CvStreamReader mCvSymbolRecordReader;
 
 	StringT<128> mPDBPath;
+	StringT<128> mOrigPDBPath;
 
 	SafeMemStream* mCvDataStream;
 	CvStringTable mStringTable;

+ 59 - 2
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<DbgModule*> 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)
 	{

+ 3 - 2
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<DbgDeferredSrcFileReference> mDeferredRefs;
 	Array<DbgSubprogram*> mLineDataRefs;
 	Array<HotReplacedLineInfo*> 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);
 };

+ 14 - 2
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;
 }

+ 32 - 0
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

+ 1 - 0
IDEHelper/DebugManager.h

@@ -75,6 +75,7 @@ public:
 	DebugVisualizers* mDebugVisualizers;
 	DwDisplayInfo mDefaultDisplayInfo;
 	Dictionary<String, DwDisplayInfo> mDisplayInfos;
+	Dictionary<String, String> mSourcePathRemap;
 	bool mStepOverExternalFiles;
 
 	NetManager* mNetManager;

+ 1 - 0
IDEHelper/DebugTarget.cpp

@@ -345,6 +345,7 @@ DbgSrcFile* DebugTarget::GetSrcFile(const String& srcFilePath)
 			mSrcFiles.TryGetValue(*origSrcPath, &srcFile);
 		}
 	}
+
 	return srcFile;
 }