Author: martin
Date: 2007-11-22 05:24:51 -0500 (Thu, 22 Nov 2007)
New Revision: 90138

Modified:
   trunk/debugger/ChangeLog
   trunk/debugger/backend/SingleSteppingEngine.cs
   trunk/debugger/backend/arch/Instruction.cs
   trunk/debugger/backend/arch/Instruction_X86_64.cs
   trunk/debugger/languages/mono/MonoLanguageBackend.cs
   trunk/debugger/test/testsuite/TestDelegate.cs
Log:
2007-11-22  Martin Baulig  <[EMAIL PROTECTED]>

        * backend/SingleSteppingEngine.cs
        (OperationDelegateInvoke): New operation; step through a delegate
        invocation trampoline.

        * backend/arch/Instruction.cs
        (Instruction.TrampolineType): Added `DelegateInvoke'.



Modified: trunk/debugger/ChangeLog
===================================================================
--- trunk/debugger/ChangeLog    2007-11-22 10:21:00 UTC (rev 90137)
+++ trunk/debugger/ChangeLog    2007-11-22 10:24:51 UTC (rev 90138)
@@ -1,3 +1,12 @@
+2007-11-22  Martin Baulig  <[EMAIL PROTECTED]>
+
+       * backend/SingleSteppingEngine.cs
+       (OperationDelegateInvoke): New operation; step through a delegate
+       invocation trampoline.
+
+       * backend/arch/Instruction.cs
+       (Instruction.TrampolineType): Added `DelegateInvoke'.
+
 2007-11-20  Martin Baulig  <[EMAIL PROTECTED]>
 
        * test/testsuite/TestDelegate.cs: Temporarily disable this.

Modified: trunk/debugger/backend/SingleSteppingEngine.cs
===================================================================
--- trunk/debugger/backend/SingleSteppingEngine.cs      2007-11-22 10:21:00 UTC 
(rev 90137)
+++ trunk/debugger/backend/SingleSteppingEngine.cs      2007-11-22 10:24:51 UTC 
(rev 90138)
@@ -1260,6 +1260,9 @@
                                PushOperation (new OperationMonoTrampoline (
                                        this, instruction, trampoline, 
handler));
                                return true;
+                       } else if (type == 
Instruction.TrampolineType.DelegateInvoke) {
+                               PushOperation (new OperationDelegateInvoke 
(this));
+                               return true;
                        }
 
                        return false;
@@ -3635,6 +3638,61 @@
                }
        }
 
+       protected class OperationDelegateInvoke : OperationStepBase
+       {
+               public OperationDelegateInvoke (SingleSteppingEngine sse)
+                       : base (sse, null)
+               { }
+
+               public override bool IsSourceOperation {
+                       get { return true; }
+               }
+
+               protected override void DoExecute ()
+               {
+                       sse.do_step_native ();
+               }
+
+               bool finished;
+
+               protected override bool DoProcessEvent ()
+               {
+                       TargetAddress current_frame = inferior.CurrentFrame;
+
+                       Report.Debug (DebugFlags.SSE, "{0} delegate impl 
stopped at {1}",
+                                     sse, current_frame);
+
+                       if (finished)
+                               return true;
+
+                       /*
+                        * If this is not a call instruction, continue stepping 
until we leave
+                        * the current method.
+                        */
+                       Instruction instruction = 
inferior.Architecture.ReadInstruction (
+                               inferior, current_frame);
+                       if ((instruction == null) || 
!instruction.HasInstructionSize) {
+                               sse.do_step_native ();
+                               return false;
+                       }
+
+                       Report.Debug (DebugFlags.SSE, "{0} delegate impl 
stopped at {1}: {2}",
+                                     sse, current_frame, instruction);
+
+                       if ((instruction.InstructionType == 
Instruction.Type.IndirectJump) ||
+                           (instruction.InstructionType == 
Instruction.Type.IndirectCall))
+                               finished = true;
+
+                       sse.do_step_native ();
+                       return false;
+               }
+
+               protected override bool TrampolineHandler (Method method)
+               {
+                       return false;
+               }
+       }
+
        protected class OperationReturn : OperationCallback
        {
                public readonly MonoLanguageBackend Language;

Modified: trunk/debugger/backend/arch/Instruction.cs
===================================================================
--- trunk/debugger/backend/arch/Instruction.cs  2007-11-22 10:21:00 UTC (rev 
90137)
+++ trunk/debugger/backend/arch/Instruction.cs  2007-11-22 10:24:51 UTC (rev 
90138)
@@ -23,7 +23,8 @@
                        None,
                        NativeTrampolineStart,
                        NativeTrampoline,
-                       MonoTrampoline
+                       MonoTrampoline,
+                       DelegateInvoke
                }
 
                public abstract TargetAddress Address {

Modified: trunk/debugger/backend/arch/Instruction_X86_64.cs
===================================================================
--- trunk/debugger/backend/arch/Instruction_X86_64.cs   2007-11-22 10:21:00 UTC 
(rev 90137)
+++ trunk/debugger/backend/arch/Instruction_X86_64.cs   2007-11-22 10:24:51 UTC 
(rev 90138)
@@ -142,16 +142,9 @@
                        }
                }
 
-               protected bool GetMonoTrampoline (TargetMemoryAccess memory,
+               protected bool GetMonoTrampoline (TargetMemoryAccess memory, 
TargetAddress call_target,
                                                  out TargetAddress trampoline)
                {
-                       if ((InstructionType != Type.Call) && (InstructionType 
!= Type.IndirectCall)) {
-                               trampoline = TargetAddress.Null;
-                               return false;
-                       }
-
-                       TargetAddress call_target = GetEffectiveAddress 
(memory);
-
                        TargetBinaryReader reader = memory.ReadMemory 
(call_target, 14).GetReader ();
                        byte opcode = reader.ReadByte ();
                        if (opcode != 0xe8) {
@@ -189,8 +182,24 @@
                                }
                        }
 
+                       if ((InstructionType != Type.Call) && (InstructionType 
!= Type.IndirectCall)) {
+                               trampoline = TargetAddress.Null;
+                               return TrampolineType.None;
+                       }
+
                        if (Opcodes.Process.IsManagedApplication) {
-                               if (GetMonoTrampoline (memory, out trampoline))
+                               TargetAddress target = GetEffectiveAddress 
(memory);
+                               if (target.IsNull) {
+                                       trampoline = TargetAddress.Null;
+                                       return TrampolineType.None;
+                               }
+
+                               if 
(Opcodes.Process.MonoLanguage.IsDelegateTrampoline (target)) {
+                                       trampoline = target;
+                                       return TrampolineType.DelegateInvoke;
+                               }
+
+                               if (GetMonoTrampoline (memory, target, out 
trampoline))
                                        return TrampolineType.MonoTrampoline;
                        }
 

Modified: trunk/debugger/languages/mono/MonoLanguageBackend.cs
===================================================================
--- trunk/debugger/languages/mono/MonoLanguageBackend.cs        2007-11-22 
10:21:00 UTC (rev 90137)
+++ trunk/debugger/languages/mono/MonoLanguageBackend.cs        2007-11-22 
10:24:51 UTC (rev 90138)
@@ -108,22 +108,27 @@
        internal abstract class MonoDataTable
        {
                public readonly TargetAddress TableAddress;
-               public readonly TargetAddress FirstChunk;
+               TargetAddress first_chunk;
                TargetAddress current_chunk;
                int last_offset;
 
                protected MonoDataTable (TargetAddress address, TargetAddress 
first_chunk)
                {
-                       this.TableAddress  =address;
-                       this.FirstChunk = first_chunk;
-
-                       current_chunk = first_chunk;
+                       this.TableAddress = address;
+                       this.first_chunk = first_chunk;
+                       this.current_chunk = first_chunk;
                }
 
                public void Read (TargetMemoryAccess memory)
                {
-                       int header_size = 16 + 
memory.TargetMemoryInfo.TargetAddressSize;
+                       int address_size = 
memory.TargetMemoryInfo.TargetAddressSize;
+                       int header_size = 16 + address_size;
 
+                       if (first_chunk.IsNull) {
+                               first_chunk = memory.ReadAddress (TableAddress 
+ address_size);
+                               current_chunk = first_chunk;
+                       }
+
                again:
                        TargetReader reader = new TargetReader (
                                memory.ReadMemory (current_chunk, header_size));
@@ -174,7 +179,8 @@
                protected enum DataItemType {
                        Unknown         = 0,
                        Class,
-                       Method
+                       Method,
+                       DelegateInvoke
                }
 
                protected abstract void ReadDataItem (TargetMemoryAccess 
memory, DataItemType type,
@@ -188,7 +194,7 @@
                public override string ToString ()
                {
                        return String.Format ("{0} ({1}:{2}:{3}{4})", GetType 
(), TableAddress,
-                                             FirstChunk, current_chunk, 
MyToString ());
+                                             first_chunk, current_chunk, 
MyToString ());
                }
        }
 
@@ -208,6 +214,7 @@
                MonoFunctionType main_method;
 
                Hashtable data_tables;
+               GlobalDataTable global_data_table;
 
                ProcessServant process;
                MonoDebuggerInfo info;
@@ -265,6 +272,14 @@
                        return false;
                }
 
+               internal bool IsDelegateTrampoline (TargetAddress address)
+               {
+                       if (global_data_table == null)
+                               return false;
+
+                       return global_data_table.IsDelegateInvoke (address);
+               }
+
                internal bool TryFindImage (Thread thread, string filename)
                {
                        Cecil.AssemblyDefinition ass = 
Cecil.AssemblyFactory.GetAssembly (filename);
@@ -421,6 +436,7 @@
                                table.Read (target);
                        foreach (MonoSymbolFile symfile in 
symfile_by_index.Values)
                                symfile.TypeTable.Read (target);
+                       global_data_table.Read (target);
                        data_table_time += DateTime.Now - start;
                }
 
@@ -530,9 +546,9 @@
                                        "expected {1}.", total_size, 
info.SymbolTableSize);
 
                        TargetAddress corlib_address = header.ReadAddress ();
+                       TargetAddress global_data_table_ptr = 
header.ReadAddress ();
+                       TargetAddress data_table_list = header.ReadAddress ();
 
-                       TargetAddress data_table = header.ReadAddress ();
-
                        TargetAddress symfile_by_index = header.ReadAddress ();
 
                        if (corlib_address.IsNull)
@@ -551,7 +567,7 @@
                                load_symfile (memory, address);
                        }
 
-                       ptr = data_table;
+                       ptr = data_table_list;
                        while (!ptr.IsNull) {
                                TargetAddress next_ptr = memory.ReadAddress 
(ptr);
                                TargetAddress address = memory.ReadAddress (
@@ -560,6 +576,8 @@
                                ptr = next_ptr;
                                add_data_table (memory, address);
                        }
+
+                       global_data_table = new GlobalDataTable (this, 
global_data_table_ptr);
                }
 
                void add_data_table (TargetMemoryAccess memory, TargetAddress 
ptr)
@@ -621,6 +639,54 @@
                        }
                }
 
+               protected class GlobalDataTable : MonoDataTable
+               {
+                       public readonly MonoLanguageBackend Mono;
+                       ArrayList delegate_impl_list;
+
+                       public GlobalDataTable (MonoLanguageBackend mono, 
TargetAddress address)
+                               : base (address, TargetAddress.Null)
+                       {
+                               this.Mono = mono;
+
+                               delegate_impl_list = new ArrayList ();
+                       }
+
+                       protected override void ReadDataItem 
(TargetMemoryAccess memory,
+                                                             DataItemType 
type, TargetReader reader)
+                       {
+                               if (type != DataItemType.DelegateInvoke)
+                                       throw new InternalError (
+                                               "Got unknown data item: {0}", 
type);
+
+                               TargetAddress code = reader.ReadAddress ();
+                               int size = reader.BinaryReader.ReadInt32 ();
+                               Report.Debug (DebugFlags.JitSymtab, "READ 
DELEGATE IMPL: {0} {1}",
+                                             code, size);
+                               delegate_impl_list.Add (new DelegateInvokeEntry 
(code, size));
+                       }
+
+                       public bool IsDelegateInvoke (TargetAddress address)
+                       {
+                               foreach (DelegateInvokeEntry entry in 
delegate_impl_list)
+                                       if ((address >= entry.Code) && (address 
< entry.Code + entry.Size))
+                                               return true;
+
+                               return false;
+                       }
+
+                       struct DelegateInvokeEntry {
+                               public readonly TargetAddress Code;
+                               public readonly int Size;
+
+                               public DelegateInvokeEntry (TargetAddress code, 
int size)
+                               {
+                                       this.Code = code;
+                                       this.Size = size;
+                               }
+                       }
+               }
+
                static int manual_update_count;
                static int full_update_count;
                static int update_count;

Modified: trunk/debugger/test/testsuite/TestDelegate.cs
===================================================================
--- trunk/debugger/test/testsuite/TestDelegate.cs       2007-11-22 10:21:00 UTC 
(rev 90137)
+++ trunk/debugger/test/testsuite/TestDelegate.cs       2007-11-22 10:24:51 UTC 
(rev 90138)
@@ -15,7 +15,7 @@
                { }
 
                [Test]
-               [Category("NotWorking")]
+               [Category("ManagedTypes")]
                public void Main ()
                {
                        Process process = Start ();

_______________________________________________
Mono-patches maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches

Reply via email to