Browse Source

In .NET 4.0, we use the LoadClass callback to load dynamic modules because it always works - UpdateModuleSymbols does not.

- Simple dynamic code generation seems to trigger both callbacks.
  - IronPython for some reason causes just the LoadClass callback so we choose to rely on it out of the two.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@6111 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
pull/1/head
David Srbecký 15 years ago
parent
commit
61d67819c3
  1. 6
      src/AddIns/Debugger/Debugger.AddIn/Pads/LoadedModulesPad.cs
  2. 2
      src/AddIns/Debugger/Debugger.Core/AppDomain.cs
  3. 25
      src/AddIns/Debugger/Debugger.Core/ManagedCallback.cs
  4. 130
      src/AddIns/Debugger/Debugger.Core/Module.cs
  5. 3
      src/AddIns/Debugger/Debugger.Core/ModuleCollection.cs
  6. 2
      src/AddIns/Debugger/Debugger.Core/NDebugger.cs
  7. 4
      src/AddIns/Debugger/Debugger.Core/SourcecodeSegment.cs
  8. 2
      src/AddIns/Debugger/Debugger.Tests/DebuggerTestsBase.cs

6
src/AddIns/Debugger/Debugger.AddIn/Pads/LoadedModulesPad.cs

@ -141,7 +141,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -141,7 +141,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
ListViewItem newItem = new ListViewItem();
newItem.Tag = module;
RefreshItem(newItem);
module.SymbolsLoaded += delegate { RefreshItem(newItem); };
module.SymbolsUpdated += delegate { RefreshItem(newItem); };
loadedModulesList.Items.Add(newItem);
}
@ -151,9 +151,9 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -151,9 +151,9 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
item.SubItems.Clear();
item.SubItems.AddRange(
new string[] {
module.Filename,
module.Name,
String.Format("{0:X8}", module.BaseAdress),
module.FullPath,
module.IsDynamic ? "(dynamic)" : module.IsInMemory ? "(in memory)" : module.FullPath,
module.OrderOfLoading.ToString(),
"",
"",

2
src/AddIns/Debugger/Debugger.Core/AppDomain.cs

@ -36,7 +36,7 @@ namespace Debugger @@ -36,7 +36,7 @@ namespace Debugger
get {
if (mscorlib != null) return mscorlib;
foreach(Module m in Process.Modules) {
if (m.Filename == "mscorlib.dll" &&
if (m.Name == "mscorlib.dll" &&
m.AppDomain == this) {
mscorlib = m;
return mscorlib;

25
src/AddIns/Debugger/Debugger.Core/ManagedCallback.cs

@ -300,13 +300,16 @@ namespace Debugger @@ -300,13 +300,16 @@ namespace Debugger
{
EnterCallback(PausedReason.Other, "UpdateModuleSymbols", pAppDomain);
foreach (Module module in process.Modules) {
if (module.CorModule == pModule) {
process.TraceMessage("UpdateModuleSymbols: Found module: " + pModule.GetName());
module.UpdateSymbolsFromStream(pSymbolStream);
process.Debugger.Breakpoints.SetInModule(module);
break;
}
Module module = process.Modules[pModule];
if (module.CorModule is ICorDebugModule3 && module.IsDynamic) {
// In .NET 4.0, we use the LoadClass callback to load dynamic modules
// because it always works - UpdateModuleSymbols does not.
// - Simple dynamic code generation seems to trigger both callbacks.
// - IronPython for some reason causes just the LoadClass callback
// so we choose to rely on it out of the two.
} else {
// In .NET 2.0, this is the the only method and it works fine
module.LoadSymbolsFromMemory(pSymbolStream);
}
ExitCallback();
@ -346,7 +349,8 @@ namespace Debugger @@ -346,7 +349,8 @@ namespace Debugger
{
EnterCallback(PausedReason.Other, "LoadModule " + pModule.GetName(), pAppDomain);
process.Modules.Add(new Module(process.AppDomains[pAppDomain], pModule));
Module module = new Module(process.AppDomains[pAppDomain], pModule);
process.Modules.Add(module);
ExitCallback();
}
@ -390,6 +394,11 @@ namespace Debugger @@ -390,6 +394,11 @@ namespace Debugger
{
EnterCallback(PausedReason.Other, "LoadClass", pAppDomain);
Module module = process.Modules[c.GetModule()];
// Dynamic module has been extended - reload symbols to inlude new class
module.LoadSymbolsDynamic();
ExitCallback();
}

130
src/AddIns/Debugger/Debugger.Core/Module.cs

@ -23,7 +23,8 @@ namespace Debugger @@ -23,7 +23,8 @@ namespace Debugger
Process process;
bool unloaded = false;
string fullPath;
string name;
string fullPath = string.Empty;
int orderOfLoading = 0;
ICorDebugModule corModule;
@ -32,14 +33,10 @@ namespace Debugger @@ -32,14 +33,10 @@ namespace Debugger
internal Dictionary<string, DebugType> LoadedDebugTypes = new Dictionary<string, DebugType>();
public event EventHandler<ModuleEventArgs> SymbolsLoaded;
protected virtual void OnSymbolsLoaded(ModuleEventArgs e)
{
if (SymbolsLoaded != null) {
SymbolsLoaded(this, e);
}
}
/// <summary>
/// Occurs when symbols are loaded or unloaded (for memory modules)
/// </summary>
public event EventHandler<ModuleEventArgs> SymbolsUpdated;
public AppDomain AppDomain {
get { return appDomain; }
@ -120,6 +117,12 @@ namespace Debugger @@ -120,6 +117,12 @@ namespace Debugger
}
}
public string Name {
get {
return name;
}
}
[Debugger.Tests.Ignore]
public string FullPath {
get {
@ -127,13 +130,6 @@ namespace Debugger @@ -127,13 +130,6 @@ namespace Debugger
}
}
public string Filename {
get {
if (IsDynamic || IsInMemory) return String.Empty;
return System.IO.Path.GetFileName(FullPath);
}
}
[Debugger.Tests.Ignore]
public string DirectoryName {
get {
@ -188,38 +184,96 @@ namespace Debugger @@ -188,38 +184,96 @@ namespace Debugger
metaData = new MetaDataImport(corModule);
fullPath = corModule.GetName();
LoadSymbols(process.Options.SymbolsSearchPaths);
if (IsDynamic || IsInMemory) {
name = corModule.GetName();
} else {
fullPath = corModule.GetName();
name = System.IO.Path.GetFileName(FullPath);
}
LoadSymbolsFromDisk(process.Options.SymbolsSearchPaths);
ResetJustMyCodeStatus();
}
/// <summary> Try to load the debugging symbols (.pdb) from the given path </summary>
public void LoadSymbols(string[] searchPath)
public void UnloadSymbols()
{
if (symReader == null) {
symReader = metaData.GetSymReader(fullPath, string.Join("; ", searchPath ?? new string[0]));
if (symReader != null) {
OnSymbolsLoaded(new ModuleEventArgs(this));
ResetJustMyCodeStatus();
if (symReader != null) {
((ISymUnmanagedDispose)symReader).Destroy();
symReader = null;
}
}
/// <summary>
/// Load symblos for on-disk module
/// </summary>
public void LoadSymbolsFromDisk(string[] searchPath)
{
if (!IsDynamic && !IsInMemory) {
if (symReader == null) {
symReader = metaData.GetSymReader(fullPath, string.Join("; ", searchPath ?? new string[0]));
if (symReader != null) {
process.TraceMessage("Loaded symbols from disk for " + this.Name);
OnSymbolsUpdated();
}
}
}
}
public void UpdateSymbolsFromStream(IStream pSymbolStream)
/// <summary>
/// Load symbols for in-memory module
/// </summary>
public void LoadSymbolsFromMemory(IStream pSymbolStream)
{
if (symReader != null) {
((ISymUnmanagedDispose)symReader).Destroy();
if (this.IsInMemory) {
UnloadSymbols();
symReader = metaData.GetSymReader(pSymbolStream);
if (symReader != null) {
process.TraceMessage("Loaded symbols from memory for " + this.Name);
} else {
process.TraceMessage("Failed to load symbols from memory");
}
OnSymbolsUpdated();
}
symReader = metaData.GetSymReader(pSymbolStream);
if (symReader != null) {
OnSymbolsLoaded(new ModuleEventArgs(this));
}
/// <summary>
/// Load symbols for dynamic module
/// (as of .NET 4.0)
/// </summary>
public void LoadSymbolsDynamic()
{
if (this.CorModule is ICorDebugModule3 && this.IsDynamic) {
Guid guid = new Guid(0, 0, 0, 0xc0, 0, 0, 0, 0, 0, 0, 70);
symReader = (ISymUnmanagedReader)((ICorDebugModule3)this.CorModule).CreateReaderForInMemorySymbols(guid);
TrackedComObjects.Track(symReader);
process.TraceMessage("Loaded dynamic symbols for " + this.Name);
OnSymbolsUpdated();
}
}
void OnSymbolsUpdated()
{
SetBreakpoints();
ResetJustMyCodeStatus();
if (SymbolsUpdated != null) {
SymbolsUpdated(this, new ModuleEventArgs(this));
}
}
void SetBreakpoints()
{
if (this.HasSymbols) {
// This is in case that the client modifies the collection as a response to set breakpoint
// NB: If client adds new breakpoint, it will be set directly as a result of his call, not here (because module is already loaded)
List<Breakpoint> collection = new List<Breakpoint>();
collection.AddRange(this.Debugger.Breakpoints);
foreach (Breakpoint b in collection) {
b.SetBreakpoint(this);
}
}
}
/// <summary> Sets all code as being 'my code'. The code will be gradually
@ -251,17 +305,15 @@ namespace Debugger @@ -251,17 +305,15 @@ namespace Debugger
public void Dispose()
{
UnloadSymbols();
metaData.Dispose();
if (symReader != null) {
((ISymUnmanagedDispose)symReader).Destroy();
}
unloaded = true;
}
public override string ToString()
{
return string.Format("{0}", this.Filename);
return string.Format("{0}", this.Name);
}
}

3
src/AddIns/Debugger/Debugger.Core/ModuleCollection.cs

@ -19,7 +19,7 @@ namespace Debugger @@ -19,7 +19,7 @@ namespace Debugger
public Module this[string filename] {
get {
foreach(Module module in this) {
if (module.Filename == filename) {
if (module.Name == filename) {
return module;
}
}
@ -42,7 +42,6 @@ namespace Debugger @@ -42,7 +42,6 @@ namespace Debugger
{
module.OrderOfLoading = lastAssignedModuleOrderOfLoading;
lastAssignedModuleOrderOfLoading++;
this.Debugger.Breakpoints.SetInModule(module);
base.OnAdded(module);
}

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

@ -245,7 +245,7 @@ namespace Debugger @@ -245,7 +245,7 @@ namespace Debugger
{
foreach(Process process in this.Processes) {
foreach(Module module in process.Modules) {
module.LoadSymbols(process.Options.SymbolsSearchPaths);
module.LoadSymbolsFromDisk(process.Options.SymbolsSearchPaths);
}
}
TraceMessage("Reloaded symbols");

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

@ -123,9 +123,11 @@ namespace Debugger @@ -123,9 +123,11 @@ namespace Debugger
if (!symDoc.GetURL().ToLower().EndsWith(filename)) continue;
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]) continue;
if (symDocCheckSum[i] != checksum[i]) match = false;
}
if (!match) continue;
return symDoc;
}
return null; // Not found

2
src/AddIns/Debugger/Debugger.Tests/DebuggerTestsBase.cs

@ -205,7 +205,7 @@ namespace Debugger.Tests @@ -205,7 +205,7 @@ namespace Debugger.Tests
LogEvent("LogMessage", e.Message.Replace("\r",@"\r").Replace("\n",@"\n"));
};
process.Modules.Added += delegate(object sender, CollectionItemEventArgs<Module> e) {
LogEvent("ModuleLoaded", e.Item.Filename + (e.Item.HasSymbols ? " (Has symbols)" : " (No symbols)"));
LogEvent("ModuleLoaded", e.Item.Name + (e.Item.HasSymbols ? " (Has symbols)" : " (No symbols)"));
};
process.Paused += delegate(object sender, ProcessEventArgs e) {
LogEvent("DebuggingPaused", e.Process.PauseSession.PausedReason.ToString() + " " + e.Process.SelectedStackFrame.NextStatement.ToString());

Loading…
Cancel
Save