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