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 @@ @@ -6,9 +6,9 @@
// </file>
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 @@ -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;
}

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

@ -28,6 +28,8 @@ namespace Debugger @@ -28,6 +28,8 @@ namespace Debugger
ThreadCollection threads;
AppDomainCollection appDomains;
string workingDirectory;
public NDebugger Debugger {
get { return debugger; }
}
@ -99,10 +101,15 @@ namespace 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 @@ -149,7 +156,7 @@ namespace Debugger
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>

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

@ -79,54 +79,92 @@ namespace Debugger @@ -79,54 +79,92 @@ namespace Debugger
{
}
/// <returns> "\lowercasename.cs" or absolute path </returns>
static string NormalizeFilename(string filename, out bool isRooted)
/// <summary>
/// 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);
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;
}
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 (filename == null) throw new ArgumentNullException("filename");
if (Path.IsPathRooted(symUrl)) {
Dictionary<string, object> returned = new Dictionary<string, object>();
ISymUnmanagedDocument[] symDocs = module.SymDocuments;
// Try without relocating
returned.Add(symUrl, null);
yield return symUrl;
// Normalize input
bool filenameRooted;
filename = NormalizeFilename(filename, out filenameRooted);
// The two paths to combine
string[] moduleDirs = modulePath.Split('\\');
string[] urlDirs = symUrl.Split('\\');
// Exact match of all the data that is available
foreach(ISymUnmanagedDocument symDoc in symDocs) {
bool urlRooted;
string url = NormalizeFilename(symDoc.GetURL(), out urlRooted);
// 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);
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;
// Return joined path
if (!returned.ContainsKey(joined)) {
returned.Add(joined, null);
yield return joined;
}
}
}
}
} 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
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;
static ISymUnmanagedDocument GetSymDocumentFromFilename(Module module, string filename, byte[] checksum)
{
if (filename == null) throw new ArgumentNullException("filename");
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;
}
}
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 @@ -182,50 +220,10 @@ namespace Debugger
static string GetFilenameFromSymDocument(Module module, ISymUnmanagedDocument symDoc)
{
if (File.Exists(symDoc.GetURL())) return symDoc.GetURL();
List<string> searchPaths = new List<string>();
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<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();
}

Loading…
Cancel
Save