From dea13e142de57fe6e7a59432299be49dd3bec3c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Srbeck=C3=BD?= Date: Mon, 12 Jul 2010 21:17:30 +0000 Subject: [PATCH] Rewritten filename -> symbol document resolution git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@6114 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Debugger/Debugger.Core/NDebugger.cs | 8 +- src/AddIns/Debugger/Debugger.Core/Process.cs | 11 +- .../Debugger.Core/SourcecodeSegment.cs | 162 +++++++++--------- 3 files changed, 94 insertions(+), 87 deletions(-) diff --git a/src/AddIns/Debugger/Debugger.Core/NDebugger.cs b/src/AddIns/Debugger/Debugger.Core/NDebugger.cs index 4d506e3409..414c0fc968 100644 --- a/src/AddIns/Debugger/Debugger.Core/NDebugger.cs +++ b/src/AddIns/Debugger/Debugger.Core/NDebugger.cs @@ -6,9 +6,9 @@ // using System; +using System.IO; using System.Text; using System.Threading; - using Debugger.Interop; using Debugger.Interop.CorDebug; using Microsoft.Win32; @@ -199,9 +199,11 @@ namespace Debugger public Process Attach(System.Diagnostics.Process existingProcess) { - InitDebugger(GetProgramVersion(existingProcess.MainModule.FileName)); + string mainModule = existingProcess.MainModule.FileName; + InitDebugger(GetProgramVersion(mainModule)); ICorDebugProcess corDebugProcess = corDebug.DebugActiveProcess((uint)existingProcess.Id, 0); - Process process = new Process(this, corDebugProcess); + // TODO: Can we get the acutal working directory? + Process process = new Process(this, corDebugProcess, Path.GetDirectoryName(mainModule)); this.Processes.Add(process); return process; } diff --git a/src/AddIns/Debugger/Debugger.Core/Process.cs b/src/AddIns/Debugger/Debugger.Core/Process.cs index c9967773be..77094d83ba 100644 --- a/src/AddIns/Debugger/Debugger.Core/Process.cs +++ b/src/AddIns/Debugger/Debugger.Core/Process.cs @@ -28,6 +28,8 @@ namespace Debugger ThreadCollection threads; AppDomainCollection appDomains; + string workingDirectory; + public NDebugger Debugger { get { return debugger; } } @@ -99,10 +101,15 @@ namespace Debugger get { return steppers; } } - internal Process(NDebugger debugger, ICorDebugProcess corProcess) + public string WorkingDirectory { + get { return workingDirectory; } + } + + internal Process(NDebugger debugger, ICorDebugProcess corProcess, string workingDirectory) { this.debugger = debugger; this.corProcess = corProcess; + this.workingDirectory = workingDirectory; this.callbackInterface = new ManagedCallback(this); @@ -149,7 +156,7 @@ namespace Debugger CorDebugCreateProcessFlags.DEBUG_NO_SPECIAL_OPTIONS // debuggingFlags ); - return new Process(debugger, outProcess); + return new Process(debugger, outProcess, workingDirectory); } /// Fired when System.Diagnostics.Trace.WriteLine() is called in debuged process diff --git a/src/AddIns/Debugger/Debugger.Core/SourcecodeSegment.cs b/src/AddIns/Debugger/Debugger.Core/SourcecodeSegment.cs index 3b9da51b3a..6ee3575190 100644 --- a/src/AddIns/Debugger/Debugger.Core/SourcecodeSegment.cs +++ b/src/AddIns/Debugger/Debugger.Core/SourcecodeSegment.cs @@ -79,54 +79,92 @@ namespace Debugger { } - /// "\lowercasename.cs" or absolute path - static string NormalizeFilename(string filename, out bool isRooted) + /// + /// Use the module path to figure out where to look for the source file + /// + static IEnumerable RelocateSymURL(Module module, string symUrl) { - isRooted = Path.IsPathRooted(filename); - if (!isRooted) { - while (filename.StartsWith(@".\")) filename = filename.Substring(2); - if (!filename.StartsWith(@"\")) filename = @"\" + filename; + string modulePath = module.Process.WorkingDirectory; + if (module.IsInMemory || module.IsDynamic) { + // Just use any module with symboles + foreach(Module m in module.Process.Modules) { + if (m.HasSymbols) { + if (!string.IsNullOrEmpty(m.FullPath)) { + modulePath = Path.GetDirectoryName(m.FullPath); + break; + } + } + } + } else { + if (!string.IsNullOrEmpty(module.FullPath)) + modulePath = Path.GetDirectoryName(module.FullPath); + } + if (string.IsNullOrEmpty(modulePath)) { + yield return symUrl; + yield break; + } + + if (Path.IsPathRooted(symUrl)) { + Dictionary returned = new Dictionary(); + + // Try without relocating + returned.Add(symUrl, null); + yield return symUrl; + + // The two paths to combine + string[] moduleDirs = modulePath.Split('\\'); + string[] urlDirs = symUrl.Split('\\'); + + // Join the paths at some point (joining directry must match) + for (int i = 0; i < moduleDirs.Length; i++) { + for (int j = 0; j < urlDirs.Length; j++) { + if (!string.IsNullOrEmpty(moduleDirs[i]) && + !string.IsNullOrEmpty(urlDirs[j]) && + string.Equals(moduleDirs[i], urlDirs[j], StringComparison.OrdinalIgnoreCase)) + { + // Join the paths + string[] joinedDirs = new string[i + (urlDirs.Length - j)]; + Array.Copy(moduleDirs, joinedDirs, i); + Array.Copy(urlDirs, j, joinedDirs, i, urlDirs.Length - j); + string joined = string.Join(@"\", joinedDirs); + + // Return joined path + if (!returned.ContainsKey(joined)) { + returned.Add(joined, null); + yield return joined; + } + } + } + } + } else { + if (symUrl.StartsWith(@".\")) symUrl = symUrl.Substring(2); + if (symUrl.StartsWith(@"\")) symUrl = symUrl.Substring(1); + // Try 0, 1 and 2 levels above the module directory + string dir = modulePath; + if (!string.IsNullOrEmpty(dir)) yield return Path.Combine(dir, symUrl); + dir = Path.GetDirectoryName(dir); + if (!string.IsNullOrEmpty(dir)) yield return Path.Combine(dir, symUrl); + dir = Path.GetDirectoryName(dir); + if (!string.IsNullOrEmpty(dir)) yield return Path.Combine(dir, symUrl); } - return filename.ToLowerInvariant(); } static ISymUnmanagedDocument GetSymDocumentFromFilename(Module module, string filename, byte[] checksum) { if (filename == null) throw new ArgumentNullException("filename"); - ISymUnmanagedDocument[] symDocs = module.SymDocuments; - - // Normalize input - bool filenameRooted; - filename = NormalizeFilename(filename, out filenameRooted); - - // Exact match of all the data that is available - foreach(ISymUnmanagedDocument symDoc in symDocs) { - bool urlRooted; - string url = NormalizeFilename(symDoc.GetURL(), out urlRooted); - - if (filenameRooted && urlRooted) { - if (url == filename) return symDoc; - } else if (filenameRooted && !urlRooted) { - if (filename.EndsWith(url)) return symDoc; - } else if (!filenameRooted && urlRooted) { - if (url.EndsWith(filename)) return symDoc; - } else { - if (url == filename) return symDoc; + if (Path.IsPathRooted(filename)) { + foreach(ISymUnmanagedDocument symDoc in module.SymDocuments) { + foreach (string url in RelocateSymURL(module, symDoc.GetURL())) { + if (string.Equals(url, filename, StringComparison.OrdinalIgnoreCase)) + return symDoc; + } } - } - - // Relaxed matching if we have checksum - if (checksum != null) { - foreach(ISymUnmanagedDocument symDoc in symDocs) { - if (Path.GetFileName(filename).ToLowerInvariant() == Path.GetFileName(symDoc.GetURL()).ToLowerInvariant()) { - byte[] symDocCheckSum = symDoc.GetCheckSum(); - if (symDocCheckSum.Length != checksum.Length) continue; - bool match = true; - for (int i = 0; i < checksum.Length; i++) { - if (symDocCheckSum[i] != checksum[i]) match = false; - } - if (!match) continue; + } else { + foreach(ISymUnmanagedDocument symDoc in module.SymDocuments) { + if (filename.StartsWith(@".\")) filename = filename.Substring(2); + if (filename.StartsWith(@"\")) filename = filename.Substring(1); + if (symDoc.GetURL().ToLowerInvariant().EndsWith(@"\" + filename.ToLowerInvariant())) { return symDoc; } } @@ -182,50 +220,10 @@ namespace Debugger static string GetFilenameFromSymDocument(Module module, ISymUnmanagedDocument symDoc) { - if (File.Exists(symDoc.GetURL())) return symDoc.GetURL(); - - List searchPaths = new List(); - - searchPaths.AddRange(module.Process.Options.SymbolsSearchPaths); - - string modulePath = module.FullPath; - while (true) { - // Get parent directory - int index = modulePath.LastIndexOf('\\'); - if (index == -1) break; - modulePath = modulePath.Substring(0, index); - // Add the directory to search path list - if (modulePath.Length == 2 && modulePath[1] == ':') { - searchPaths.Add(modulePath + '\\'); - } else { - searchPaths.Add(modulePath); - } + foreach (string filename in RelocateSymURL(module, symDoc.GetURL())) { + if (File.Exists(filename)) + return filename; } - - List filenames = new List(); - string filename = symDoc.GetURL(); - while (true) { - // Remove start of the path - int index = filename.IndexOf('\\'); - if (index == -1) break; - filename = filename.Substring(index + 1); - // Add the filename as candidate - filenames.Add(filename); - } - - List candidates = new List(); - foreach(string path in searchPaths) { - foreach(string name in filenames) { - candidates.Add(Path.Combine(path, name)); - } - } - - foreach(string candiate in candidates) { - if (File.Exists(candiate)) { - return candiate; - } - } - return symDoc.GetURL(); }