Browse Source

Rewritten filename -> symbol document resolution

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@6114 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
pull/1/head
David Srbecký 15 years ago
parent
commit
dea13e142d
  1. 8
      src/AddIns/Debugger/Debugger.Core/NDebugger.cs
  2. 11
      src/AddIns/Debugger/Debugger.Core/Process.cs
  3. 154
      src/AddIns/Debugger/Debugger.Core/SourcecodeSegment.cs

8
src/AddIns/Debugger/Debugger.Core/NDebugger.cs

@ -6,9 +6,9 @@
// </file> // </file>
using System; using System;
using System.IO;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using Debugger.Interop; using Debugger.Interop;
using Debugger.Interop.CorDebug; using Debugger.Interop.CorDebug;
using Microsoft.Win32; using Microsoft.Win32;
@ -199,9 +199,11 @@ namespace Debugger
public Process Attach(System.Diagnostics.Process existingProcess) 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); 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); this.Processes.Add(process);
return process; return process;
} }

11
src/AddIns/Debugger/Debugger.Core/Process.cs

@ -28,6 +28,8 @@ namespace Debugger
ThreadCollection threads; ThreadCollection threads;
AppDomainCollection appDomains; AppDomainCollection appDomains;
string workingDirectory;
public NDebugger Debugger { public NDebugger Debugger {
get { return debugger; } get { return debugger; }
} }
@ -99,10 +101,15 @@ namespace Debugger
get { return steppers; } 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.debugger = debugger;
this.corProcess = corProcess; this.corProcess = corProcess;
this.workingDirectory = workingDirectory;
this.callbackInterface = new ManagedCallback(this); this.callbackInterface = new ManagedCallback(this);
@ -149,7 +156,7 @@ namespace Debugger
CorDebugCreateProcessFlags.DEBUG_NO_SPECIAL_OPTIONS // debuggingFlags CorDebugCreateProcessFlags.DEBUG_NO_SPECIAL_OPTIONS // debuggingFlags
); );
return new Process(debugger, outProcess); return new Process(debugger, outProcess, workingDirectory);
} }
/// <summary> Fired when System.Diagnostics.Trace.WriteLine() is called in debuged process </summary> /// <summary> Fired when System.Diagnostics.Trace.WriteLine() is called in debuged process </summary>

154
src/AddIns/Debugger/Debugger.Core/SourcecodeSegment.cs

@ -79,54 +79,92 @@ namespace Debugger
{ {
} }
/// <returns> "\lowercasename.cs" or absolute path </returns> /// <summary>
static string NormalizeFilename(string filename, out bool isRooted) /// Use the module path to figure out where to look for the source file
/// </summary>
static IEnumerable<string> RelocateSymURL(Module module, string symUrl)
{ {
isRooted = Path.IsPathRooted(filename); string modulePath = module.Process.WorkingDirectory;
if (!isRooted) { if (module.IsInMemory || module.IsDynamic) {
while (filename.StartsWith(@".\")) filename = filename.Substring(2); // Just use any module with symboles
if (!filename.StartsWith(@"\")) filename = @"\" + filename; foreach(Module m in module.Process.Modules) {
if (m.HasSymbols) {
if (!string.IsNullOrEmpty(m.FullPath)) {
modulePath = Path.GetDirectoryName(m.FullPath);
break;
} }
return filename.ToLowerInvariant(); }
}
} else {
if (!string.IsNullOrEmpty(module.FullPath))
modulePath = Path.GetDirectoryName(module.FullPath);
}
if (string.IsNullOrEmpty(modulePath)) {
yield return symUrl;
yield break;
} }
static ISymUnmanagedDocument GetSymDocumentFromFilename(Module module, string filename, byte[] checksum) if (Path.IsPathRooted(symUrl)) {
{ Dictionary<string, object> returned = new Dictionary<string, object>();
if (filename == null) throw new ArgumentNullException("filename");
ISymUnmanagedDocument[] symDocs = module.SymDocuments; // Try without relocating
returned.Add(symUrl, null);
yield return symUrl;
// Normalize input // The two paths to combine
bool filenameRooted; string[] moduleDirs = modulePath.Split('\\');
filename = NormalizeFilename(filename, out filenameRooted); string[] urlDirs = symUrl.Split('\\');
// Exact match of all the data that is available // Join the paths at some point (joining directry must match)
foreach(ISymUnmanagedDocument symDoc in symDocs) { for (int i = 0; i < moduleDirs.Length; i++) {
bool urlRooted; for (int j = 0; j < urlDirs.Length; j++) {
string url = NormalizeFilename(symDoc.GetURL(), out urlRooted); 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);
if (filenameRooted && urlRooted) { // Return joined path
if (url == filename) return symDoc; if (!returned.ContainsKey(joined)) {
} else if (filenameRooted && !urlRooted) { returned.Add(joined, null);
if (filename.EndsWith(url)) return symDoc; yield return joined;
} else if (!filenameRooted && urlRooted) { }
if (url.EndsWith(filename)) return symDoc; }
}
}
} else { } else {
if (url == filename) return symDoc; 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);
} }
} }
// Relaxed matching if we have checksum static ISymUnmanagedDocument GetSymDocumentFromFilename(Module module, string filename, byte[] checksum)
if (checksum != null) { {
foreach(ISymUnmanagedDocument symDoc in symDocs) { if (filename == null) throw new ArgumentNullException("filename");
if (Path.GetFileName(filename).ToLowerInvariant() == Path.GetFileName(symDoc.GetURL()).ToLowerInvariant()) {
byte[] symDocCheckSum = symDoc.GetCheckSum(); if (Path.IsPathRooted(filename)) {
if (symDocCheckSum.Length != checksum.Length) continue; foreach(ISymUnmanagedDocument symDoc in module.SymDocuments) {
bool match = true; foreach (string url in RelocateSymURL(module, symDoc.GetURL())) {
for (int i = 0; i < checksum.Length; i++) { if (string.Equals(url, filename, StringComparison.OrdinalIgnoreCase))
if (symDocCheckSum[i] != checksum[i]) match = false; return symDoc;
}
} }
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; return symDoc;
} }
} }
@ -182,50 +220,10 @@ namespace Debugger
static string GetFilenameFromSymDocument(Module module, ISymUnmanagedDocument symDoc) static string GetFilenameFromSymDocument(Module module, ISymUnmanagedDocument symDoc)
{ {
if (File.Exists(symDoc.GetURL())) return symDoc.GetURL(); foreach (string filename in RelocateSymURL(module, symDoc.GetURL())) {
if (File.Exists(filename))
List<string> searchPaths = new List<string>(); return filename;
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);
}
} }
List<string> filenames = new List<string>();
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<string> candidates = new List<string>();
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(); return symDoc.GetURL();
} }

Loading…
Cancel
Save