Author: martin
Date: 2007-10-31 10:44:36 -0500 (Wed, 31 Oct 2007)
New Revision: 88565

Added:
   trunk/debugger/backend/arch/Instruction_I386.cs
   trunk/debugger/backend/arch/Instruction_X86_64.cs
   trunk/debugger/backend/arch/Opcodes.cs
   trunk/debugger/backend/arch/X86_Opcodes.cs
Modified:
   trunk/debugger/ChangeLog
   trunk/debugger/backend/arch/Architecture.cs
   trunk/debugger/backend/arch/Architecture_I386.cs
   trunk/debugger/backend/arch/Architecture_X86_64.cs
   trunk/debugger/backend/arch/Bfd.cs
   trunk/debugger/backend/arch/BfdContainer.cs
   trunk/debugger/backend/arch/CoreFile.cs
   trunk/debugger/backend/arch/Instruction.cs
   trunk/debugger/backend/arch/X86_Instruction.cs
   trunk/debugger/languages/mono/MonoLanguageBackend.cs
   trunk/debugger/languages/mono/MonoSymbolFile.cs
Log:
2007-10-31  Martin Baulig  <[EMAIL PROTECTED]>

        Merged the Plophos branch.

        * backend/arch/Architecture.cs
        (CallTargetType): Removed.
        (Architecture.ReadInstruction): New method.
        (Architecture.IsTrampoline): Removed.
        (Architecture.IsCall): Removed.
        (Architecture.GetCallTarget): Removed.
        (Architecture.DoGetMonoTrampoline): Removed.

        * backend/arch/Opcodes.cs: New file.
        (Opcodes): New abstract internal class.

        * backend/arch/X86_Opcodes.cs: New file.
        (X86_Opcodes): Implementation for i386 and x86_64.

        * backend/arch/Instruction.cs: New file.
        (Instruction): New abstract internal class.

        * backend/arch/X86_Instruction.cs: New file.
        (X86_Instruction): Abstract implementation for i386 and x86_64.

        * backend/arch/Instruction_I386.cs: New file.
        (Instruction_I386): i386-specific part.

        * backend/arch/Instruction_X86_64.cs: New file.
        (Instruction_X86_64): x86_64-specific part.

        * languages/mono/MonoLanguageBackend.cs
        (MonoLanguageBackend.IsTrampolineAddress): New public method.
        (MonoLanguageBackend.GetTrampoline): FIXME:  temporarily broken.



Modified: trunk/debugger/ChangeLog
===================================================================
--- trunk/debugger/ChangeLog    2007-10-31 15:27:13 UTC (rev 88564)
+++ trunk/debugger/ChangeLog    2007-10-31 15:44:36 UTC (rev 88565)
@@ -1,3 +1,37 @@
+2007-10-31  Martin Baulig  <[EMAIL PROTECTED]>
+
+       Merged the Plophos branch.
+
+       * backend/arch/Architecture.cs
+       (CallTargetType): Removed.
+       (Architecture.ReadInstruction): New method.
+       (Architecture.IsTrampoline): Removed.
+       (Architecture.IsCall): Removed.
+       (Architecture.GetCallTarget): Removed.
+       (Architecture.DoGetMonoTrampoline): Removed.
+
+       * backend/arch/Opcodes.cs: New file.
+       (Opcodes): New abstract internal class.
+
+       * backend/arch/X86_Opcodes.cs: New file.
+       (X86_Opcodes): Implementation for i386 and x86_64.
+
+       * backend/arch/Instruction.cs: New file.
+       (Instruction): New abstract internal class.
+
+       * backend/arch/X86_Instruction.cs: New file.
+       (X86_Instruction): Abstract implementation for i386 and x86_64.
+
+       * backend/arch/Instruction_I386.cs: New file.
+       (Instruction_I386): i386-specific part.
+
+       * backend/arch/Instruction_X86_64.cs: New file.
+       (Instruction_X86_64): x86_64-specific part.
+
+       * languages/mono/MonoLanguageBackend.cs
+       (MonoLanguageBackend.IsTrampolineAddress): New public method.
+       (MonoLanguageBackend.GetTrampoline): FIXME:  temporarily broken.
+
 2007-10-15  Martin Baulig  <[EMAIL PROTECTED]>
 
        HEADS UP: The debugger currently doesn't work with the latest mono

Modified: trunk/debugger/backend/arch/Architecture.cs
===================================================================
--- trunk/debugger/backend/arch/Architecture.cs 2007-10-31 15:27:13 UTC (rev 
88564)
+++ trunk/debugger/backend/arch/Architecture.cs 2007-10-31 15:44:36 UTC (rev 
88565)
@@ -4,15 +4,6 @@
 
 namespace Mono.Debugger.Backends
 {
-       internal enum CallTargetType {
-               None,
-               Call,
-               Jump,
-               NativeTrampoline,
-               NativeTrampolineStart,
-               MonoTrampoline
-       }
-
        // <summary>
        //   Architecture-dependent interface.
        // </summary>
@@ -22,6 +13,7 @@
                protected readonly TargetInfo TargetInfo;
 
                BfdDisassembler disassembler;
+               X86_Opcodes opcodes;
 
                protected Architecture (ProcessServant process, TargetInfo info)
                {
@@ -29,6 +21,7 @@
                        this.TargetInfo = info;
 
                        disassembler = new BfdDisassembler (process, 
info.TargetAddressSize == 8);
+                       opcodes = new X86_Opcodes (process, 
info.TargetAddressSize == 8);
                }
 
                internal Disassembler Disassembler {
@@ -103,110 +96,11 @@
                internal abstract bool IsSyscallInstruction (TargetMemoryAccess 
memory,
                                                             TargetAddress 
address);
 
-               public static bool IsTrampoline (CallTargetType type)
+               internal Instruction ReadInstruction (TargetMemoryAccess 
memory, TargetAddress address)
                {
-                       return (type == CallTargetType.NativeTrampoline) ||
-                               (type == CallTargetType.NativeTrampolineStart) 
||
-                               (type == CallTargetType.MonoTrampoline);
+                       return opcodes.ReadInstruction (memory, address);
                }
 
-               public static bool IsCall (CallTargetType type)
-               {
-                       return (type == CallTargetType.Call) ||
-                               (type == CallTargetType.NativeTrampoline) ||
-                               (type == CallTargetType.NativeTrampolineStart) 
||
-                               (type == CallTargetType.MonoTrampoline);
-               }
-
-               internal CallTargetType GetCallTarget (TargetMemoryAccess 
memory,
-                                                      TargetAddress address,
-                                                      out TargetAddress target,
-                                                      out int insn_size)
-               {
-                       CallTargetType type = DoGetCallTarget (memory, address, 
out target, out insn_size);
-                       Console.WriteLine ("GET CALL TARGET: {0} {1} {2} {3}",
-                                          address, type, target, insn_size);
-                       if (type == CallTargetType.None)
-                               return CallTargetType.None;
-
-                       if (type == CallTargetType.Jump) {
-                               bool is_start;
-                               TargetAddress trampoline;
-                               if (process.BfdContainer.GetTrampoline (
-                                           memory, address, target, out 
trampoline, out is_start)) {
-                                       target = trampoline;
-                                       return is_start ? 
-                                               
CallTargetType.NativeTrampolineStart :
-                                               CallTargetType.NativeTrampoline;
-                               }
-                       }
-
-                       if (process.IsManagedApplication) {
-                               TargetAddress trampoline;
-                               if (DoGetMonoTrampoline (memory, address, 
target, out trampoline)) {
-                                       target = trampoline;
-                                       return CallTargetType.MonoTrampoline;
-                               }
-                       }
-
-                       return type;
-               }
-
-               protected CallTargetType DoGetCallTarget (TargetMemoryAccess 
memory,
-                                                         TargetAddress address,
-                                                         out TargetAddress 
target,
-                                                         out int insn_size)
-               {
-                       if (address.Address == 0xffffe002) {
-                               insn_size = 0;
-                               target = TargetAddress.Null;
-                               return CallTargetType.None;
-                       }
-
-                       Instruction insn = X86_Instruction.DecodeInstruction 
(memory, address);
-                       if ((insn == null) || (insn.InstructionType == 
Instruction.Type.Unknown)) {
-                               insn_size = 0;
-                               target = TargetAddress.Null;
-                               return CallTargetType.None;
-                       }
-
-                       switch (insn.InstructionType) {
-                       case Instruction.Type.Unknown:
-                               insn_size = -1;
-                               target = TargetAddress.Null;
-                               return CallTargetType.None;
-
-                       case Instruction.Type.Jump:
-                       case Instruction.Type.ConditionalJump:
-                               insn_size = insn.InstructionSize;
-                               target = insn.GetEffectiveAddress (memory);
-                               return CallTargetType.Jump;
-
-                       case Instruction.Type.Call:
-                               insn_size = insn.InstructionSize;
-                               target = insn.GetEffectiveAddress (memory);
-                               return CallTargetType.Call;
-
-                       case Instruction.Type.IndirectCall:
-                               insn_size = insn.InstructionSize;
-                               target = insn.GetEffectiveAddress (memory);
-                               return CallTargetType.Call;
-
-                       case Instruction.Type.IndirectJump:
-                               insn_size = insn.InstructionSize;
-                               target = insn.GetEffectiveAddress (memory);
-                               return CallTargetType.Jump;
-
-                       default:
-                               throw new InvalidOperationException ();
-                       }
-               }
-
-               protected abstract bool DoGetMonoTrampoline (TargetMemoryAccess 
memory,
-                                                            TargetAddress 
call_site,
-                                                            TargetAddress 
call_target,
-                                                            out TargetAddress 
trampoline);
-
                internal abstract int MaxPrologueSize {
                        get;
                }

Modified: trunk/debugger/backend/arch/Architecture_I386.cs
===================================================================
--- trunk/debugger/backend/arch/Architecture_I386.cs    2007-10-31 15:27:13 UTC 
(rev 88564)
+++ trunk/debugger/backend/arch/Architecture_I386.cs    2007-10-31 15:44:36 UTC 
(rev 88565)
@@ -56,40 +56,6 @@
                        }
                }
 
-               protected override bool DoGetMonoTrampoline (TargetMemoryAccess 
memory,
-                                                            TargetAddress 
call_site,
-                                                            TargetAddress 
call_target,
-                                                            out TargetAddress 
trampoline)
-               {
-                       TargetBinaryReader reader = memory.ReadMemory 
(call_target, 10).GetReader ();
-
-                       byte opcode = reader.ReadByte ();
-                       if (opcode != 0x68) {
-                               trampoline = TargetAddress.Null;
-                               return false;
-                       }
-
-                       int method_info = reader.ReadInt32 ();
-
-                       opcode = reader.ReadByte ();
-                       if (opcode != 0xe9) {
-                               trampoline = TargetAddress.Null;
-                               return false;
-                       }
-
-                       int call_disp = reader.ReadInt32 ();
-
-                       foreach (TargetAddress address in 
process.MonoLanguage.Trampolines) {
-                               if (call_target + call_disp + 10 == address) {
-                                       trampoline = new TargetAddress 
(memory.AddressDomain, method_info);
-                                       return true;
-                               }
-                       }
-
-                       trampoline = TargetAddress.Null;
-                       return false;
-               }
-
                public override string[] RegisterNames {
                        get {
                                return registers;

Modified: trunk/debugger/backend/arch/Architecture_X86_64.cs
===================================================================
--- trunk/debugger/backend/arch/Architecture_X86_64.cs  2007-10-31 15:27:13 UTC 
(rev 88564)
+++ trunk/debugger/backend/arch/Architecture_X86_64.cs  2007-10-31 15:44:36 UTC 
(rev 88565)
@@ -42,6 +42,9 @@
        // </summary>
        internal class Architecture_X86_64 : Architecture
        {
+               protected const int MONO_FAKE_IMT_METHOD = -1;
+               protected const int MONO_FAKE_VTABLE_METHOD = -2;
+
                internal Architecture_X86_64 (ProcessServant process, 
TargetInfo info)
                        : base (process, info)
                { }
@@ -63,40 +66,6 @@
                        }
                }
 
-               protected override bool DoGetMonoTrampoline (TargetMemoryAccess 
memory,
-                                                            TargetAddress 
call_site,
-                                                            TargetAddress 
call_target,
-                                                            out TargetAddress 
trampoline)
-               {
-                       TargetBinaryReader reader = memory.ReadMemory 
(call_target, 19).GetReader ();
-                       reader.Position = 9;
-
-                       byte opcode = reader.ReadByte ();
-                       if (opcode != 0x68) {
-                               trampoline = TargetAddress.Null;
-                               return false;
-                       }
-
-                       int method_info = reader.ReadInt32 ();
-
-                       opcode = reader.ReadByte ();
-                       if (opcode != 0xe9) {
-                               trampoline = TargetAddress.Null;
-                               return false;
-                       }
-
-                       int call_disp = reader.ReadInt32 ();
-                       foreach (TargetAddress address in 
process.MonoLanguage.Trampolines) {
-                               if (call_target + call_disp + 19 == address) {
-                                       trampoline = new TargetAddress 
(memory.AddressDomain, method_info);
-                                       return true;
-                               }
-                       }
-
-                       trampoline = TargetAddress.Null;
-                       return false;
-               }
-
                public override string[] RegisterNames {
                        get {
                                return registers;

Modified: trunk/debugger/backend/arch/Bfd.cs
===================================================================
--- trunk/debugger/backend/arch/Bfd.cs  2007-10-31 15:27:13 UTC (rev 88564)
+++ trunk/debugger/backend/arch/Bfd.cs  2007-10-31 15:44:36 UTC (rev 88565)
@@ -919,22 +919,35 @@
                        }
                }
 
-               internal bool GetTrampoline (TargetMemoryAccess memory,
-                                            TargetAddress call_site,
-                                            TargetAddress call_target,
-                                            out TargetAddress trampoline,
-                                            out bool is_start)
+               internal bool GetTrampoline (TargetMemoryAccess memory, 
TargetAddress address,
+                                            out TargetAddress trampoline, out 
bool is_start)
                {
-                       if (!has_got || (call_site < plt_start) || (call_site > 
plt_end)) {
+                       if (!has_got || (address < plt_start) || (address > 
plt_end)) {
                                is_start = false;
                                trampoline = TargetAddress.Null;
                                return false;
                        }
 
-                       TargetAddress method = memory.ReadAddress (call_target);
-                       if (method != call_site + 6) {
+                       Instruction target_insn = 
container.Architecture.ReadInstruction (
+                               memory, address);
+                       if ((target_insn == null) || 
!target_insn.HasInstructionSize ||
+                           ((target_insn.InstructionType != 
Instruction.Type.Jump) &&
+                            (target_insn.InstructionType != 
Instruction.Type.IndirectJump))) {
                                is_start = false;
-                               trampoline = method;
+                               trampoline = TargetAddress.Null;
+                               return false;
+                       }
+
+                       TargetAddress call_target = 
target_insn.GetEffectiveAddress (memory);
+                       if (call_target.IsNull) {
+                               is_start = false;
+                               trampoline = TargetAddress.Null;
+                               return false;
+                       }
+
+                       if (call_target != address + 
target_insn.InstructionSize) {
+                               is_start = false;
+                               trampoline = call_target;
                                return true;
                        }
 

Modified: trunk/debugger/backend/arch/BfdContainer.cs
===================================================================
--- trunk/debugger/backend/arch/BfdContainer.cs 2007-10-31 15:27:13 UTC (rev 
88564)
+++ trunk/debugger/backend/arch/BfdContainer.cs 2007-10-31 15:44:36 UTC (rev 
88565)
@@ -126,15 +126,11 @@
                        return null;
                }
 
-               public bool GetTrampoline (TargetMemoryAccess memory,
-                                          TargetAddress call_site,
-                                          TargetAddress call_target,
-                                          out TargetAddress trampoline,
-                                          out bool is_start)
+               public bool GetTrampoline (TargetMemoryAccess memory, 
TargetAddress address,
+                                          out TargetAddress trampoline, out 
bool is_start)
                {
                        foreach (Bfd bfd in bfd_hash.Values) {
-                               if (bfd.GetTrampoline (memory, call_site, 
call_target,
-                                                      out trampoline, out 
is_start))
+                               if (bfd.GetTrampoline (memory, address, out 
trampoline, out is_start))
                                        return true;
                        }
 

Modified: trunk/debugger/backend/arch/CoreFile.cs
===================================================================
--- trunk/debugger/backend/arch/CoreFile.cs     2007-10-31 15:27:13 UTC (rev 
88564)
+++ trunk/debugger/backend/arch/CoreFile.cs     2007-10-31 15:44:36 UTC (rev 
88565)
@@ -592,12 +592,6 @@
                                throw new InvalidOperationException ();
                        }
 
-                       public override CommandResult CallMethod (TargetAddress 
method,
-                                                                 TargetAddress 
arg)
-                       {
-                               throw new InvalidOperationException ();
-                       }
-
                        public override CommandResult Return (bool run_finally)
                        {
                                throw new InvalidOperationException ();

Modified: trunk/debugger/backend/arch/Instruction.cs
===================================================================
--- trunk/debugger/backend/arch/Instruction.cs  2007-10-31 15:27:13 UTC (rev 
88564)
+++ trunk/debugger/backend/arch/Instruction.cs  2007-10-31 15:44:36 UTC (rev 
88565)
@@ -1,5 +1,7 @@
 using System;
 
+using Mono.Debugger.Backends;
+
 namespace Mono.Debugger.Architectures
 {
        internal abstract class Instruction : DebuggerMarshalByRefObject
@@ -11,13 +13,37 @@
                        IndirectCall,
                        Call,
                        IndirectJump,
-                       Jump
+                       Jump,
+                       Ret
                }
 
+               public enum TrampolineType
+               {
+                       None,
+                       NativeTrampolineStart,
+                       NativeTrampoline,
+                       MonoTrampoline
+               }
+
+               public abstract TargetAddress Address {
+                       get;
+               }
+
                public abstract Type InstructionType {
                        get;
                }
 
+               public abstract bool IsIpRelative {
+                       get;
+               }
+
+               public bool IsCall {
+                       get {
+                               return (InstructionType == Type.Call) ||
+                                       (InstructionType == Type.IndirectCall);
+                       }
+               }
+
                public abstract bool HasInstructionSize {
                        get;
                }
@@ -26,6 +52,15 @@
                        get;
                }
 
+               public abstract byte[] Code {
+                       get;
+               }
+
                public abstract TargetAddress GetEffectiveAddress 
(TargetMemoryAccess memory);
+
+               public abstract TrampolineType CheckTrampoline 
(TargetMemoryAccess memory,
+                                                               out 
TargetAddress trampoline);
+
+               public abstract bool InterpretInstruction (Inferior inferior);
        }
 }

Added: trunk/debugger/backend/arch/Instruction_I386.cs
===================================================================
--- trunk/debugger/backend/arch/Instruction_I386.cs     2007-10-31 15:27:13 UTC 
(rev 88564)
+++ trunk/debugger/backend/arch/Instruction_I386.cs     2007-10-31 15:44:36 UTC 
(rev 88565)
@@ -0,0 +1,53 @@
+using System;
+using Mono.Debugger.Backends;
+
+namespace Mono.Debugger.Architectures
+{
+       internal class Instruction_I386 : X86_Instruction
+       {
+               internal Instruction_I386 (Opcodes_X86 opcodes, TargetAddress 
address)
+                       : base (opcodes, address)
+               { }
+
+               public override bool Is64BitMode {
+                       get { return false; }
+               }
+
+               protected override int DecodeRegister (int register)
+               {
+                       switch (register) {
+                       case 0: /* eax */
+                               return (int) I386Register.EAX;
+                       case 1: /* ecx */
+                               return (int) I386Register.ECX;
+                       case 2: /* edx */
+                               return (int) I386Register.EDX;
+                       case 3: /* ebx */
+                               return (int) I386Register.EBX;
+                       case 4: /* esp */
+                               return (int) I386Register.ESP;
+                       case 5: /* ebp */
+                               return (int) I386Register.EBP;
+                       case 6: /* esi */
+                               return (int) I386Register.ESI;
+                       case 7: /* edi */
+                               return (int) I386Register.EDI;
+                       default:
+                               /* can never happen */
+                               throw new InvalidOperationException ();
+                       }
+               }
+
+               public override bool InterpretInstruction (Inferior inferior)
+               {
+                       return false;
+               }
+
+               public override TrampolineType CheckTrampoline 
(TargetMemoryAccess memory,
+                                                               out 
TargetAddress trampoline)
+               {
+                       trampoline = TargetAddress.Null;
+                       return TrampolineType.None;
+               }
+       }
+}

Added: trunk/debugger/backend/arch/Instruction_X86_64.cs
===================================================================
--- trunk/debugger/backend/arch/Instruction_X86_64.cs   2007-10-31 15:27:13 UTC 
(rev 88564)
+++ trunk/debugger/backend/arch/Instruction_X86_64.cs   2007-10-31 15:44:36 UTC 
(rev 88565)
@@ -0,0 +1,182 @@
+using System;
+using Mono.Debugger.Backends;
+
+namespace Mono.Debugger.Architectures
+{
+       internal class Instruction_X86_64 : X86_Instruction
+       {
+               internal Instruction_X86_64 (Opcodes_X86 opcodes, TargetAddress 
address)
+                       : base (opcodes, address)
+               { }
+
+               public override bool Is64BitMode {
+                       get { return true; }
+               }
+
+               protected override int DecodeRegister (int register)
+               {
+                       switch (register) {
+                       case 0: /* rax */
+                               return (int) X86_64_Register.RAX;
+                       case 1: /* rcx */
+                               return (int) X86_64_Register.RCX;
+                       case 2: /* rdx */
+                               return (int) X86_64_Register.RDX;
+                       case 3: /* rbx */
+                               return (int) X86_64_Register.RBX;
+                       case 4: /* rsp */
+                               return (int) X86_64_Register.RSP;
+                       case 5: /* rbp */
+                               return (int) X86_64_Register.RBP;
+                       case 6: /* rsi */
+                               return (int) X86_64_Register.RSI;
+                       case 7: /* rdi */
+                               return (int) X86_64_Register.RDI;
+                       case 8: /* r8 */
+                               return (int) X86_64_Register.R8;
+                       case 9: /* r9 */
+                               return (int) X86_64_Register.R9;
+                       case 10: /* r10 */
+                               return (int) X86_64_Register.R10;
+                       case 11: /* r11 */
+                               return (int) X86_64_Register.R11;
+                       case 12: /* r12 */
+                               return (int) X86_64_Register.R12;
+                       case 13: /* r13 */
+                               return (int) X86_64_Register.R13;
+                       case 14: /* r14 */
+                               return (int) X86_64_Register.R14;
+                       case 15: /* r15 */
+                               return (int) X86_64_Register.R15;
+                       default:
+                               /* can never happen */
+                               throw new InvalidOperationException ();
+                       }
+               }
+
+               public override bool InterpretInstruction (Inferior inferior)
+               {
+                       Console.WriteLine ("INTERPRET INSTRUCTION: {0}", 
InstructionType);
+
+                       switch (InstructionType) {
+                       case Type.IndirectJump:
+                       case Type.Jump: {
+                               TargetAddress target = GetEffectiveAddress 
(inferior);
+                               Console.WriteLine ("INTERPRET JUMP: {0}", 
target);
+                               Registers regs = inferior.GetRegisters ();
+                               regs [(int) X86_64_Register.RIP].SetValue 
(target);
+                               inferior.SetRegisters (regs);
+                               return true;
+                       }
+
+                       case Type.IndirectCall:
+                       case Type.Call: {
+                               TargetAddress target = GetEffectiveAddress 
(inferior);
+                               Console.WriteLine ("INTERPRET CALL: {0}", 
target);
+                               Registers regs = inferior.GetRegisters ();
+
+                               TargetAddress rip = new TargetAddress (
+                                       inferior.AddressDomain, regs [(int) 
X86_64_Register.RIP].Value);
+                               TargetAddress rsp = new TargetAddress (
+                                       inferior.AddressDomain, regs [(int) 
X86_64_Register.RSP].Value);
+
+                               Console.WriteLine ("INTERPRET CALL #1: {0} {1} 
{2} {3}",
+                                                  rip, rsp, CallTarget, 
InstructionSize);
+
+                               inferior.WriteAddress (rsp - 8, rip + 
InstructionSize);
+
+                               regs [(int) X86_64_Register.RSP].SetValue (rsp 
- 8);
+                               regs [(int) X86_64_Register.RIP].SetValue 
(target);
+                               inferior.SetRegisters (regs);
+                               return true;
+                       }
+
+                       case Type.Ret: {
+                               Console.WriteLine ("INTERPRET RET: {0}", 
Displacement);
+
+                               Registers regs = inferior.GetRegisters ();
+
+                               TargetAddress rsp = new TargetAddress (
+                                       inferior.AddressDomain, regs [(int) 
X86_64_Register.RSP].Value);
+
+                               TargetAddress rip = inferior.ReadAddress (rsp);
+                               rsp += 8 + Displacement;
+
+                               regs [(int) X86_64_Register.RSP].SetValue (rsp);
+                               regs [(int) X86_64_Register.RIP].SetValue (rip);
+                               inferior.SetRegisters (regs);
+                               return true;
+                       }
+
+                       default:
+                               return false;
+                       }
+               }
+
+               protected bool GetMonoTrampoline (TargetMemoryAccess memory,
+                                                 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) {
+                               trampoline = TargetAddress.Null;
+                               return false;
+                       }
+
+                       TargetAddress call = call_target + reader.ReadInt32 () 
+ 5;
+                       Console.WriteLine ("GET MONO TRAMPOLINE: {0}", call);
+                       if (!Opcodes.Process.MonoLanguage.IsTrampolineAddress 
(call)) {
+                               trampoline = TargetAddress.Null;
+                               return false;
+                       }
+
+                       long method;
+                       if (reader.ReadByte () == 0x04)
+                               method = reader.ReadInt32 ();
+                       else
+                               method = reader.ReadInt64 ();
+
+                       Console.WriteLine ("GET MONO TRAMPOLINE #1: {0:x}", 
method);
+                       trampoline = call_target;
+                       return true;
+               }
+
+               public override TrampolineType CheckTrampoline 
(TargetMemoryAccess memory,
+                                                               out 
TargetAddress trampoline)
+               {
+                       Console.WriteLine ("CHECK TRAMPOLINE: {0} {1}", 
Address, InstructionType);
+
+                       if (InstructionType == Type.Call) {
+                               TargetAddress target = GetEffectiveAddress 
(memory);
+                               if (target.IsNull) {
+                                       trampoline = TargetAddress.Null;
+                                       return TrampolineType.None;
+                               }
+
+                               bool is_start;
+                               if (Opcodes.Process.BfdContainer.GetTrampoline (
+                                           memory, target, out trampoline, out 
is_start)) {
+                                       target = trampoline;
+                                       return is_start ? 
+                                               
TrampolineType.NativeTrampolineStart :
+                                               TrampolineType.NativeTrampoline;
+                               }
+                       }
+
+                       if (Opcodes.Process.IsManagedApplication) {
+                               if (GetMonoTrampoline (memory, out trampoline))
+                                       return TrampolineType.MonoTrampoline;
+                       }
+
+                       trampoline = TargetAddress.Null;
+                       return TrampolineType.None;
+               }
+       }
+}

Added: trunk/debugger/backend/arch/Opcodes.cs
===================================================================
--- trunk/debugger/backend/arch/Opcodes.cs      2007-10-31 15:27:13 UTC (rev 
88564)
+++ trunk/debugger/backend/arch/Opcodes.cs      2007-10-31 15:44:36 UTC (rev 
88565)
@@ -0,0 +1,54 @@
+using System;
+using Mono.Debugger.Backends;
+
+namespace Mono.Debugger.Architectures
+{
+       internal abstract class Opcodes : DebuggerMarshalByRefObject, 
IDisposable
+       {
+               internal abstract Instruction ReadInstruction 
(TargetMemoryAccess memory,
+                                                              TargetAddress 
address);
+
+               //
+               // IDisposable
+               //
+
+               private bool disposed = false;
+
+               private void check_disposed ()
+               {
+                       if (disposed)
+                               throw new ObjectDisposedException ("Opcodes");
+               }
+
+               protected virtual void DoDispose ()
+               {
+               }
+
+               private void Dispose (bool disposing)
+               {
+                       // Check to see if Dispose has already been called.
+                       lock (this) {
+                               if (disposed)
+                                       return;
+
+                               disposed = true;
+                       }
+
+                       // If this is a call to Dispose, dispose all managed 
resources.
+                       if (disposing)
+                               DoDispose ();
+               }
+
+               public void Dispose ()
+               {
+                       Dispose (true);
+                       // Take yourself off the Finalization queue
+                       GC.SuppressFinalize (this);
+               }
+
+               ~Opcodes ()
+               {
+                       Dispose (false);
+               }
+       }
+}

Modified: trunk/debugger/backend/arch/X86_Instruction.cs
===================================================================
--- trunk/debugger/backend/arch/X86_Instruction.cs      2007-10-31 15:27:13 UTC 
(rev 88564)
+++ trunk/debugger/backend/arch/X86_Instruction.cs      2007-10-31 15:44:36 UTC 
(rev 88565)
@@ -3,19 +3,22 @@
 
 namespace Mono.Debugger.Architectures
 {
-       internal class X86_Instruction : Instruction
+       internal abstract class X86_Instruction : Instruction
        {
                public const int MaxInstructionLength = 15;
 
-               public readonly bool Is64BitMode;
-               public readonly TargetAddress Address;
+               public abstract bool Is64BitMode {
+                       get;
+               }
 
-               protected X86_Instruction (TargetAddress address, bool 
is_64bit_mode)
+               protected X86_Instruction (Opcodes_X86 opcodes, TargetAddress 
address)
                {
-                       this.Address = address;
-                       this.Is64BitMode = is_64bit_mode;
+                       this.Opcodes = opcodes;
+                       this.address = address;
                }
 
+               protected readonly Opcodes_X86 Opcodes;
+
                public X86_Prefix Prefix;
                public X86_REX_Prefix RexPrefix;
 
@@ -28,14 +31,33 @@
                public int Displacement;
                public bool DereferenceAddress;
 
+               readonly TargetAddress address;
                Type type = Type.Unknown;
 
+               public override TargetAddress Address {
+                       get { return address; }
+               }
+
                public override Type InstructionType {
                        get { return type; }
                }
 
-               public bool IsIpRelative;
+               public override bool IsIpRelative {
+                       get {
+                               switch (type) {
+                               case Type.ConditionalJump:
+                               case Type.IndirectCall:
+                               case Type.Call:
+                               case Type.IndirectJump:
+                               case Type.Jump:
+                                       return true;
 
+                               default:
+                                       return is_ip_relative;
+                               }
+                       }
+               }
+
                public override bool HasInstructionSize {
                        get { return has_insn_size; }
                }
@@ -49,17 +71,20 @@
                        }
                }
 
-               internal void SetInstructionSize (int size)
-               {
-                       this.insn_size = size;
-                       this.has_insn_size = true;
+               public override byte[] Code {
+                       get {
+                               if (!has_insn_size)
+                                       throw new InvalidOperationException ();
+
+                               return code;
+                       }
                }
 
+               bool is_ip_relative;
                bool has_insn_size;
                int insn_size;
+               byte[] code;
 
-               public bool InsnSize;
-
                public TargetAddress CallTarget = TargetAddress.Null;
 
                [Flags]
@@ -260,77 +285,14 @@
                        return false;
                }
 
-               protected int DecodeRegister (int register)
-               {
-                       if (Is64BitMode) {
-                               switch (register) {
-                               case 0: /* rax */
-                                       return (int) X86_64_Register.RAX;
-                               case 1: /* rcx */
-                                       return (int) X86_64_Register.RCX;
-                               case 2: /* rdx */
-                                       return (int) X86_64_Register.RDX;
-                               case 3: /* rbx */
-                                       return (int) X86_64_Register.RBX;
-                               case 4: /* rsp */
-                                       return (int) X86_64_Register.RSP;
-                               case 5: /* rbp */
-                                       return (int) X86_64_Register.RBP;
-                               case 6: /* rsi */
-                                       return (int) X86_64_Register.RSI;
-                               case 7: /* rdi */
-                                       return (int) X86_64_Register.RDI;
-                               case 8: /* r8 */
-                                       return (int) X86_64_Register.R8;
-                               case 9: /* r9 */
-                                       return (int) X86_64_Register.R9;
-                               case 10: /* r10 */
-                                       return (int) X86_64_Register.R10;
-                               case 11: /* r11 */
-                                       return (int) X86_64_Register.R11;
-                               case 12: /* r12 */
-                                       return (int) X86_64_Register.R12;
-                               case 13: /* r13 */
-                                       return (int) X86_64_Register.R13;
-                               case 14: /* r14 */
-                                       return (int) X86_64_Register.R14;
-                               case 15: /* r15 */
-                                       return (int) X86_64_Register.R15;
-                               default:
-                                       /* can never happen */
-                                       throw new InvalidOperationException ();
-                               }
-                       } else {
-                               switch (register) {
-                               case 0: /* eax */
-                                       return (int) I386Register.EAX;
-                               case 1: /* ecx */
-                                       return (int) I386Register.ECX;
-                               case 2: /* edx */
-                                       return (int) I386Register.EDX;
-                               case 3: /* ebx */
-                                       return (int) I386Register.EBX;
-                               case 4: /* esp */
-                                       return (int) I386Register.ESP;
-                               case 5: /* ebp */
-                                       return (int) I386Register.EBP;
-                               case 6: /* esi */
-                                       return (int) I386Register.ESI;
-                               case 7: /* edi */
-                                       return (int) I386Register.EDI;
-                               default:
-                                       /* can never happen */
-                                       throw new InvalidOperationException ();
-                               }
-                       }
-               }
+               protected abstract int DecodeRegister (int register);
 
                protected void DecodeModRM (TargetReader reader)
                {
                        ModRM = new X86_ModRM (this, reader.ReadByte ());
 
                        if (Is64BitMode && (ModRM.Mod == 0) && ((ModRM.R_M & 
0x07) == 0x06)) {
-                               IsIpRelative = true;
+                               is_ip_relative = true;
                        }
                }
 
@@ -364,6 +326,11 @@
                        } else if (opcode == 0xeb) {
                                CallTarget = Address + reader.ReadByte () + 2;
                                type = Type.Jump;
+                       } else if (opcode == 0xc3) {
+                               type = Type.Ret;
+                       } else if (opcode == 0xc2) {
+                               Displacement = reader.BinaryReader.ReadInt16 ();
+                               type = Type.Ret;
                        } else if (opcode == 0xff) {
                                DecodeGroup5 (reader);
                        }
@@ -415,8 +382,8 @@
                                if (ModRM.Mod == 0) {
                                        if (Is64BitMode) {
                                                displacement = 
reader.BinaryReader.ReadInt32 ();
-                                               register = (int) 
X86_64_Register.RIP;
-                                               IsIpRelative = true;
+                                               register = -1;
+                                               is_ip_relative = true;
                                        } else {
                                                CallTarget = reader.ReadAddress 
();
                                                return;
@@ -485,8 +452,13 @@
                                effective_displacement += index;
                        }
 
-                       TargetAddress effective_address = new TargetAddress (
-                               memory.AddressDomain, regs [Register].GetValue 
());
+                       TargetAddress effective_address;
+                       if (is_ip_relative)
+                               effective_address = Address + InstructionSize;
+                       else
+                               effective_address = new TargetAddress (
+                                       memory.AddressDomain, regs 
[Register].GetValue ());
+
                        effective_address += effective_displacement;
 
                        if (DereferenceAddress)
@@ -495,24 +467,29 @@
                        return effective_address;
                }
 
-               public static X86_Instruction DecodeInstruction 
(TargetMemoryAccess memory,
+               public static X86_Instruction DecodeInstruction (Opcodes_X86 
opcodes,
+                                                                
TargetMemoryAccess memory,
                                                                 TargetAddress 
address)
                {
                        try {
-                               TargetReader reader = new TargetReader (
-                                       memory.ReadMemory (address, 
MaxInstructionLength));
-
-                               bool is_64bit_mode = 
memory.TargetMemoryInfo.TargetAddressSize == 8;
-                               X86_Instruction insn = new X86_Instruction 
(address, is_64bit_mode);
-                               insn.DecodeInstruction (reader);
+                               X86_Instruction insn;
+                               if (memory.TargetMemoryInfo.TargetAddressSize 
== 8)
+                                       insn = new Instruction_X86_64 (opcodes, 
address);
+                               else
+                                       insn = new Instruction_I386 (opcodes, 
address);
+                               insn.DoDecodeInstruction (memory, address);
                                return insn;
                        } catch {
                                return null;
                        }
                }
 
-               protected void DecodeInstruction (TargetReader reader)
+               protected void DoDecodeInstruction (TargetMemoryAccess memory,
+                                                   TargetAddress address)
                {
+                       TargetReader reader = new TargetReader (
+                               memory.ReadMemory (address, 
MaxInstructionLength));
+
                        while (CheckPrefix (reader))
                                reader.Offset++;
 
@@ -523,8 +500,24 @@
                        else
                                OneByteOpcode (reader, opcode);
 
-                       if (InstructionType != Type.Unknown)
-                               SetInstructionSize ((int) reader.Offset);
+                       if (InstructionType != Type.Unknown) {
+                               insn_size = (int) reader.Offset;
+                               has_insn_size = true;
+                       } else {
+                               insn_size = 
Opcodes.Disassembler.GetInstructionSize (memory, address);
+                               has_insn_size = true;
+                       }
+
+                       if (has_insn_size) {
+                               code = new byte [insn_size];
+                               Array.Copy (reader.Contents, 0, code, 0, 
insn_size);
+                       }
                }
+
+               public override string ToString ()
+               {
+                       return String.Format ("Instruction ({0}:{1}:{2})", 
Address, InstructionType,
+                                             insn_size);
+               }
        }
 }

Added: trunk/debugger/backend/arch/X86_Opcodes.cs
===================================================================
--- trunk/debugger/backend/arch/X86_Opcodes.cs  2007-10-31 15:27:13 UTC (rev 
88564)
+++ trunk/debugger/backend/arch/X86_Opcodes.cs  2007-10-31 15:44:36 UTC (rev 
88565)
@@ -0,0 +1,45 @@
+using System;
+using System.Runtime.InteropServices;
+
+using Mono.Debugger.Backends;
+
+namespace Mono.Debugger.Architectures
+{
+       internal class X86_Opcodes : Opcodes
+       {
+               public readonly bool Is64BitMode;
+
+               ProcessServant process;
+               BfdDisassembler disassembler;
+
+               internal X86_Opcodes (ProcessServant process, bool is_64bit)
+               {
+                       this.process = process;
+                       this.Is64BitMode = is_64bit;
+
+                       disassembler = new BfdDisassembler (null, is_64bit);
+               }
+
+               internal Disassembler Disassembler {
+                       get { return disassembler; }
+               }
+
+               internal ProcessServant Process {
+                       get { return process; }
+               }
+
+               protected override void DoDispose ()
+               {
+                       if (disassembler != null) {
+                               disassembler.Dispose ();
+                               disassembler = null;
+                       }
+               }
+
+               internal override Instruction ReadInstruction 
(TargetMemoryAccess memory,
+                                                              TargetAddress 
address)
+               {
+                       return X86_Instruction.DecodeInstruction (this, memory, 
address);
+               }
+       }
+}

Modified: trunk/debugger/languages/mono/MonoLanguageBackend.cs
===================================================================
--- trunk/debugger/languages/mono/MonoLanguageBackend.cs        2007-10-31 
15:27:13 UTC (rev 88564)
+++ trunk/debugger/languages/mono/MonoLanguageBackend.cs        2007-10-31 
15:44:36 UTC (rev 88565)
@@ -255,6 +255,16 @@
                        get { return trampolines; }
                }
 
+               internal bool IsTrampolineAddress (TargetAddress address)
+               {
+                       foreach (TargetAddress trampoline in trampolines) {
+                               if (address == trampoline)
+                                       return true;
+                       }
+
+                       return false;
+               }
+
                internal bool TryFindImage (Thread thread, string filename)
                {
                        Cecil.AssemblyDefinition ass = 
Cecil.AssemblyFactory.GetAssembly (filename);
@@ -917,6 +927,7 @@
                public MethodSource GetTrampoline (TargetMemoryAccess memory,
                                                   TargetAddress address)
                {
+#if FIXME
                        int insn_size;
                        TargetAddress target;
                        CallTargetType type = memory.Architecture.GetCallTarget 
(
@@ -934,6 +945,7 @@
 
                                return file.GetMethodByToken (token);
                        }
+#endif
 
                        return null;
                }

Modified: trunk/debugger/languages/mono/MonoSymbolFile.cs
===================================================================
--- trunk/debugger/languages/mono/MonoSymbolFile.cs     2007-10-31 15:27:13 UTC 
(rev 88564)
+++ trunk/debugger/languages/mono/MonoSymbolFile.cs     2007-10-31 15:44:36 UTC 
(rev 88565)
@@ -1072,7 +1072,11 @@
                        internal override MethodSource GetTrampoline 
(TargetMemoryAccess memory,
                                                                      
TargetAddress address)
                        {
+#if FIXME
                                return file.MonoLanguage.GetTrampoline (memory, 
address);
+#else
+                               return null;
+#endif
                        }
 
                        public override string[] GetNamespaces ()

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

Reply via email to