Author: martin
Date: 2007-10-31 10:51:19 -0500 (Wed, 31 Oct 2007)
New Revision: 88566

Modified:
   trunk/debugger/ChangeLog
   trunk/debugger/backend/server/breakpoints.h
   trunk/debugger/backend/server/i386-arch.c
   trunk/debugger/backend/server/library.c
   trunk/debugger/backend/server/server.h
   trunk/debugger/backend/server/x86-arch.h
   trunk/debugger/backend/server/x86-ptrace.c
   trunk/debugger/backend/server/x86_64-arch.c
Log:
2007-10-31  Martin Baulig  <[EMAIL PROTECTED]>

        Merged the Plophos branch.

        * backend/server/breakpoints.h
        (BreakpointInfo): Added `runtime_table_slot'.

        * server.h
        (MonoRuntimeInfo): New typedef.
        (ServerHandle): Added `MonoRuntimeInfo *mono_runtime'
        (InferiorVTable): Added `set_runtime_info' and
        `execute_instruction'; removed `set_notification'; `call_method_2'
        now takes additional `data_size' and 'data_buffer' arguments.
        (mono_debugger_server_set_runtime_info): New function.
        (mono_debugger_server_execute_instruction): New function.
        (mono_debugger_server_set_notification): Removed.
        (mono_debugger_server_initialize_mono_runtime): New function.

        * x86-ptrace.c
        (InferiorHandle): Removed `notification_address', this is now in
        the new `MonoRuntimeInfo'.

        * x86_64-arch.c
        (runtime_info_enable/disable_breakpoint): New static methods.

        * i386-arch.c
        (runtime_info_enable/disable_breakpoint): New static methods.



Modified: trunk/debugger/ChangeLog
===================================================================
--- trunk/debugger/ChangeLog    2007-10-31 15:44:36 UTC (rev 88565)
+++ trunk/debugger/ChangeLog    2007-10-31 15:51:19 UTC (rev 88566)
@@ -2,6 +2,30 @@
 
        Merged the Plophos branch.
 
+       * backend/server/breakpoints.h
+       (BreakpointInfo): Added `runtime_table_slot'.
+
+       * server.h
+       (MonoRuntimeInfo): New typedef.
+       (ServerHandle): Added `MonoRuntimeInfo *mono_runtime'
+       (InferiorVTable): Added `set_runtime_info' and
+       `execute_instruction'; removed `set_notification'; `call_method_2'
+       now takes additional `data_size' and 'data_buffer' arguments.
+       (mono_debugger_server_set_runtime_info): New function.
+       (mono_debugger_server_execute_instruction): New function.
+       (mono_debugger_server_set_notification): Removed.
+       (mono_debugger_server_initialize_mono_runtime): New function.
+
+       * x86-ptrace.c
+       (InferiorHandle): Removed `notification_address', this is now in
+       the new `MonoRuntimeInfo'.
+
+       * x86_64-arch.c
+       (runtime_info_enable/disable_breakpoint): New static methods.
+
+       * i386-arch.c
+       (runtime_info_enable/disable_breakpoint): New static methods.
+
        * backend/arch/Architecture.cs
        (CallTargetType): Removed.
        (Architecture.ReadInstruction): New method.

Modified: trunk/debugger/backend/server/breakpoints.h
===================================================================
--- trunk/debugger/backend/server/breakpoints.h 2007-10-31 15:44:36 UTC (rev 
88565)
+++ trunk/debugger/backend/server/breakpoints.h 2007-10-31 15:51:19 UTC (rev 
88566)
@@ -26,6 +26,7 @@
        int is_hardware_bpt;
        int dr_index;
        char saved_insn;
+       int runtime_table_slot;
        guint64 address;
 } BreakpointInfo;
 

Modified: trunk/debugger/backend/server/i386-arch.c
===================================================================
--- trunk/debugger/backend/server/i386-arch.c   2007-10-31 15:44:36 UTC (rev 
88565)
+++ trunk/debugger/backend/server/i386-arch.c   2007-10-31 15:51:19 UTC (rev 
88566)
@@ -411,7 +411,8 @@
        if (stopsig == SIGSTOP)
                return STOP_ACTION_INTERRUPTED;
 
-       if ((guint32) INFERIOR_REG_EIP (arch->current_regs) - 1 == 
inferior->notification_address) {
+       if (handle->mono_runtime &&
+           ((guint32) INFERIOR_REG_EIP (arch->current_regs) - 1 == 
handle->mono_runtime->notification_address)) {
                guint32 addr = (guint32) INFERIOR_REG_ESP (arch->current_regs) 
+ 4;
                guint64 data [3];
 
@@ -587,7 +588,81 @@
        return COMMAND_ERROR_NONE;
 }
 
+static int
+find_breakpoint_table_slot (MonoRuntimeInfo *runtime)
+{
+       int i;
+
+       for (i = 0; i < runtime->breakpoint_table_size; i++) {
+               if (runtime->breakpoint_table_bitfield [i])
+                       continue;
+
+               runtime->breakpoint_table_bitfield [i] = 1;
+               return i;
+       }
+
+       return -1;
+}
+
 static ServerCommandError
+runtime_info_enable_breakpoint (ServerHandle *handle, BreakpointInfo 
*breakpoint)
+{
+       MonoRuntimeInfo *runtime;
+       ServerCommandError result;
+       guint64 table_address, index_address;
+       int slot;
+
+       runtime = handle->mono_runtime;
+       g_assert (runtime);
+
+       slot = find_breakpoint_table_slot (runtime);
+       if (slot < 0)
+               return COMMAND_ERROR_INTERNAL_ERROR;
+
+       breakpoint->runtime_table_slot = slot;
+
+       table_address = runtime->breakpoint_info_area + 8 * slot;
+       index_address = runtime->breakpoint_table + 4 * slot;
+
+       result = server_ptrace_poke_word (handle, table_address, 
breakpoint->address);
+       if (result != COMMAND_ERROR_NONE)
+               return result;
+
+       result = server_ptrace_poke_word (handle, table_address + 4, (gsize) 
breakpoint->saved_insn);
+       if (result != COMMAND_ERROR_NONE)
+               return result;
+
+       result = server_ptrace_poke_word (handle, index_address, (gsize) 
table_address);
+       if (result != COMMAND_ERROR_NONE)
+               return result;
+
+       return COMMAND_ERROR_NONE;
+}
+
+static ServerCommandError
+runtime_info_disable_breakpoint (ServerHandle *handle, BreakpointInfo 
*breakpoint)
+{
+       MonoRuntimeInfo *runtime;
+       ServerCommandError result;
+       guint64 index_address;
+       int slot;
+
+       runtime = handle->mono_runtime;
+       g_assert (runtime);
+
+       slot = breakpoint->runtime_table_slot;
+       index_address = runtime->breakpoint_table + runtime->address_size * 
slot;
+
+       result = server_ptrace_poke_word (handle, index_address, 0);
+       if (result != COMMAND_ERROR_NONE)
+               return result;
+
+       runtime->breakpoint_table_bitfield [slot] = 0;
+
+       return COMMAND_ERROR_NONE;
+}
+
+static ServerCommandError
 do_enable (ServerHandle *handle, BreakpointInfo *breakpoint)
 {
        ServerCommandError result;
@@ -623,6 +698,12 @@
                if (result != COMMAND_ERROR_NONE)
                        return result;
 
+               if (handle->mono_runtime) {
+                       result = runtime_info_enable_breakpoint (handle, 
breakpoint);
+                       if (result != COMMAND_ERROR_NONE)
+                               return result;
+               }
+
                result = server_ptrace_write_memory (handle, address, 1, 
&bopcode);
                if (result != COMMAND_ERROR_NONE)
                        return result;
@@ -664,6 +745,12 @@
                result = server_ptrace_write_memory (handle, address, 1, 
&breakpoint->saved_insn);
                if (result != COMMAND_ERROR_NONE)
                        return result;
+
+               if (handle->mono_runtime) {
+                       result = runtime_info_disable_breakpoint (handle, 
breakpoint);
+                       if (result != COMMAND_ERROR_NONE)
+                               return result;
+               }
        }
 
        return COMMAND_ERROR_NONE;

Modified: trunk/debugger/backend/server/library.c
===================================================================
--- trunk/debugger/backend/server/library.c     2007-10-31 15:44:36 UTC (rev 
88565)
+++ trunk/debugger/backend/server/library.c     2007-10-31 15:51:19 UTC (rev 
88566)
@@ -103,9 +103,11 @@
 
 ServerStatusMessageType
 mono_debugger_server_dispatch_event (ServerHandle *handle, guint32 status, 
guint64 *arg,
-                                    guint64 *data1, guint64 *data2)
+                                    guint64 *data1, guint64 *data2, guint32 
*opt_data_size,
+                                    gpointer *opt_data)
 {
-       return (*global_vtable->dispatch_event) (handle, status, arg, data1, 
data2);
+       return (*global_vtable->dispatch_event) (
+               handle, status, arg, data1, data2, opt_data_size, opt_data);
 }
 
 ServerCommandError
@@ -219,13 +221,14 @@
 
 ServerCommandError
 mono_debugger_server_call_method_2 (ServerHandle *handle, guint64 
method_address,
-                                   guint64 method_argument, guint64 
callback_argument)
+                                   guint32 data_size, gconstpointer 
data_buffer,
+                                   guint64 callback_argument)
 {
        if (!global_vtable->call_method_2)
                return COMMAND_ERROR_NOT_IMPLEMENTED;
 
        return (* global_vtable->call_method_2) (
-               handle, method_address, method_argument, callback_argument);
+               handle, method_address, data_size, data_buffer, 
callback_argument);
 }
 
 ServerCommandError
@@ -244,6 +247,18 @@
 }
 
 ServerCommandError
+mono_debugger_server_execute_instruction (ServerHandle *handle, const guint8 
*instruction,
+                                         guint32 orig_insn_size, guint32 
insn_size,
+                                         gboolean push_retaddr)
+{
+       if (!global_vtable->execute_instruction)
+               return COMMAND_ERROR_NOT_IMPLEMENTED;
+
+       return (* global_vtable->execute_instruction) (
+               handle, instruction, orig_insn_size, insn_size, push_retaddr);
+}
+
+ServerCommandError
 mono_debugger_server_mark_rti_frame (ServerHandle *handle)
 {
        if (!global_vtable->mark_rti_frame)
@@ -372,10 +387,10 @@
 }
 
 void
-mono_debugger_server_set_notification (ServerHandle *handle, guint64 
notification)
+mono_debugger_server_set_runtime_info (ServerHandle *handle, MonoRuntimeInfo 
*mono_runtime)
 {
-       if (global_vtable->set_notification)
-               return (* global_vtable->set_notification) 
(handle,notification);
+       if (global_vtable->set_runtime_info)
+               return (* global_vtable->set_runtime_info) (handle, 
mono_runtime);
 }
 
 ServerCommandError

Modified: trunk/debugger/backend/server/server.h
===================================================================
--- trunk/debugger/backend/server/server.h      2007-10-31 15:44:36 UTC (rev 
88565)
+++ trunk/debugger/backend/server/server.h      2007-10-31 15:51:19 UTC (rev 
88566)
@@ -61,6 +61,25 @@
        guint64 frame_address;
 } StackFrame;
 
+#define EXECUTABLE_CODE_CHUNK_SIZE             16
+
+typedef struct
+{
+       guint32 address_size;
+       guint64 notification_address;
+       guint64 executable_code_buffer;
+       guint32 executable_code_buffer_size;
+       guint32 executable_code_chunk_size;
+       guint32 executable_code_total_chunks;
+       guint64 breakpoint_info_area;
+       guint64 breakpoint_table;
+       guint32 breakpoint_table_size;
+
+       /* Private */
+       guint8 *breakpoint_table_bitfield;
+       guint8 *executable_code_bitfield;
+} MonoRuntimeInfo;
+
 /* This is an opaque data structure which the backend may use to store stuff. 
*/
 typedef struct InferiorVTable InferiorVTable;
 typedef struct InferiorHandle InferiorHandle;
@@ -93,6 +112,7 @@
 struct ServerHandle {
        ArchInfo *arch;
        InferiorHandle *inferior;
+       MonoRuntimeInfo *mono_runtime;
        BreakpointManager *bpm;
 };
 
@@ -106,6 +126,9 @@
        ServerCommandError    (* initialize_thread)   (ServerHandle       
*handle,
                                                       guint32             pid);
 
+       void                  (* set_runtime_info)    (ServerHandle       
*handle,
+                                                      MonoRuntimeInfo    
*mono_runtime_info);
+
        ServerCommandError    (* spawn)               (ServerHandle       
*handle,
                                                       const gchar        
*working_directory,
                                                       const gchar       **argv,
@@ -131,7 +154,9 @@
                                                       guint32              
status,
                                                       guint64             *arg,
                                                       guint64             
*data1,
-                                                      guint64             
*data2);
+                                                      guint64             
*data2,
+                                                      guint32             
*opt_data_size,
+                                                      gpointer            
*opt_data);
 
        /* Get sizeof (int), sizeof (long) and sizeof (void *) from the target. 
*/
        ServerCommandError    (* get_target_info)     (guint32            
*target_int_size,
@@ -216,7 +241,8 @@
 
        ServerCommandError    (* call_method_2)       (ServerHandle     *handle,
                                                       guint64           method,
-                                                      guint64           
method_argument,
+                                                      guint32           
data_size,
+                                                      gconstpointer     
data_buffer,
                                                       guint64           
callback_argument);
 
        ServerCommandError    (* call_method_invoke)  (ServerHandle     *handle,
@@ -230,6 +256,12 @@
                                                       guint64           
callback_argument,
                                                       gboolean          debug);
 
+       ServerCommandError    (* execute_instruction) (ServerHandle     *handle,
+                                                      const guint8     
*instruction,
+                                                      guint32           
orig_size,
+                                                      guint32           size,
+                                                      gboolean          
push_retaddr);
+
        ServerCommandError    (* mark_rti_frame)      (ServerHandle     
*handle);
 
        ServerCommandError    (* abort_invoke)        (ServerHandle     *handle,
@@ -316,9 +348,6 @@
        ServerCommandError    (* get_signal_info)     (ServerHandle     *handle,
                                                       SignalInfo      **sinfo);
 
-       void                  (* set_notification)    (ServerHandle     *handle,
-                                                      guint64           
notification);
-
        ServerCommandError    (* get_threads)         (ServerHandle     *handle,
                                                       guint32          *count,
                                                       guint32         
**threads);
@@ -390,7 +419,9 @@
                                           guint32                  status,
                                           guint64                 *arg,
                                           guint64                 *data1,
-                                          guint64                 *data2);
+                                          guint64                 *data2,
+                                          guint32                 
*opt_data_size,
+                                          gpointer                *opt_data);
 
 ServerCommandError
 mono_debugger_server_get_target_info      (guint32            *target_int_size,
@@ -450,7 +481,8 @@
 ServerCommandError
 mono_debugger_server_call_method_2        (ServerHandle       *handle,
                                           guint64             method_address,
-                                          guint64             method_argument,
+                                          guint32             data_size,
+                                          gconstpointer       data_buffer,
                                           guint64             
callback_argument);
 
 ServerCommandError
@@ -466,6 +498,13 @@
                                           gboolean            debug);
 
 ServerCommandError
+mono_debugger_execute_instruction         (ServerHandle        *handle,
+                                          const guint8        *instruction,
+                                          guint32              
original_instruction_size,
+                                          guint32              
instruction_size,
+                                          gboolean             push_retaddr);
+
+ServerCommandError
 mono_debugger_mark_rti_framenvoke        (ServerHandle        *handle);
 
 ServerCommandError
@@ -524,8 +563,8 @@
                                          SignalInfo         **sinfo);
 
 void
-mono_debugger_server_set_notification    (ServerHandle        *handle,
-                                         guint64              notification);
+mono_debugger_server_set_runtime_info    (ServerHandle        *handle,
+                                         MonoRuntimeInfo     *mono_runtime);
 
 ServerCommandError
 mono_debugger_server_get_threads         (ServerHandle        *handle,
@@ -555,6 +594,15 @@
                                          gboolean             exact_match,
                                          guint64             *registers);
 
+MonoRuntimeInfo *
+mono_debugger_server_initialize_mono_runtime (guint32 address_size,
+                                             guint64 notification_address,
+                                             guint64 executable_code_buffer,
+                                             guint32 
executable_code_buffer_size,
+                                             guint64 breakpoint_info_area,
+                                             guint64 breakpoint_table,
+                                             guint32 breakpoint_table_size);
+
 /* POSIX semaphores */
 
 void mono_debugger_server_sem_init (void);

Modified: trunk/debugger/backend/server/x86-arch.h
===================================================================
--- trunk/debugger/backend/server/x86-arch.h    2007-10-31 15:44:36 UTC (rev 
88565)
+++ trunk/debugger/backend/server/x86-arch.h    2007-10-31 15:51:19 UTC (rev 
88566)
@@ -29,7 +29,8 @@
 
 static ChildStoppedAction
 x86_arch_child_stopped (ServerHandle *handle, int stopsig,
-                       guint64 *callback_arg, guint64 *retval, guint64 
*retval2);
+                       guint64 *callback_arg, guint64 *retval, guint64 
*retval2,
+                       guint32 *opt_data_size, gpointer *opt_data);
 
 static ServerCommandError
 x86_arch_get_registers (ServerHandle *handle);

Modified: trunk/debugger/backend/server/x86-ptrace.c
===================================================================
--- trunk/debugger/backend/server/x86-ptrace.c  2007-10-31 15:44:36 UTC (rev 
88565)
+++ trunk/debugger/backend/server/x86-ptrace.c  2007-10-31 15:51:19 UTC (rev 
88566)
@@ -21,8 +21,10 @@
 #include <string.h>
 #include <fcntl.h>
 #include <errno.h>
-#include <mono/metadata/threads.h>
 
+#include <mono/metadata/appdomain.h>
+#include <mono/metadata/object.h>
+
 /*
  * NOTE:  The manpage is wrong about the POKE_* commands - the last argument
  *        is the data (a word) to be written, not a pointer to it.
@@ -53,7 +55,6 @@
        int last_signal;
        int output_fd [2], error_fd [2];
        int is_thread, is_initialized;
-       guint64 notification_address;
 };
 
 typedef struct
@@ -62,6 +63,34 @@
        ChildOutputFunc stdout_handler, stderr_handler;
 } IOThreadData;
 
+MonoRuntimeInfo *
+mono_debugger_server_initialize_mono_runtime (guint32 address_size,
+                                             guint64 notification_address,
+                                             guint64 executable_code_buffer,
+                                             guint32 
executable_code_buffer_size,
+                                             guint64 breakpoint_info_area,
+                                             guint64 breakpoint_table,
+                                             guint32 breakpoint_table_size)
+{
+       MonoRuntimeInfo *runtime = g_new0 (MonoRuntimeInfo, 1);
+
+       runtime->address_size = address_size;
+       runtime->notification_address = notification_address;
+       runtime->executable_code_buffer = executable_code_buffer;
+       runtime->executable_code_buffer_size = executable_code_buffer_size;
+       runtime->executable_code_chunk_size = EXECUTABLE_CODE_CHUNK_SIZE;
+       runtime->executable_code_total_chunks = executable_code_buffer_size / 
EXECUTABLE_CODE_CHUNK_SIZE;
+
+       runtime->breakpoint_info_area = breakpoint_info_area;
+       runtime->breakpoint_table = breakpoint_table;
+       runtime->breakpoint_table_size = breakpoint_table_size;
+
+       runtime->breakpoint_table_bitfield = g_malloc0 (breakpoint_table_size);
+       runtime->executable_code_bitfield = g_malloc0 
(runtime->executable_code_total_chunks);
+
+       return runtime;
+}
+
 static void
 server_ptrace_finalize (ServerHandle *handle)
 {
@@ -154,11 +183,22 @@
        memcpy (&temp, ptr, size);
 
        return server_ptrace_write_memory (handle, addr, sizeof (long), &temp);
-}      
+}
 
+static ServerCommandError
+server_ptrace_poke_word (ServerHandle *handle, guint64 addr, gsize value)
+{
+       errno = 0;
+       if (ptrace (PT_WRITE_D, handle->inferior->pid, GSIZE_TO_POINTER (addr), 
value) != 0)
+               return _server_ptrace_check_errno (handle->inferior);
+
+       return COMMAND_ERROR_NONE;
+}
+
 static ServerStatusMessageType
 server_ptrace_dispatch_event (ServerHandle *handle, guint32 status, guint64 
*arg,
-                             guint64 *data1, guint64 *data2)
+                             guint64 *data1, guint64 *data2, guint32 
*opt_data_size,
+                             gpointer *opt_data)
 {
        if (status >> 16) {
                switch (status >> 16) {
@@ -226,7 +266,7 @@
                }
 
                action = x86_arch_child_stopped (
-                       handle, stopsig, &callback_arg, &retval, &retval2);
+                       handle, stopsig, &callback_arg, &retval, &retval2, 
opt_data_size, opt_data);
 
                if (action != STOP_ACTION_STOPPED)
                        handle->inferior->last_signal = 0;
@@ -473,9 +513,9 @@
 }
 
 static void
-server_ptrace_set_notification (ServerHandle *handle, guint64 addr)
+server_ptrace_set_runtime_info (ServerHandle *handle, MonoRuntimeInfo 
*mono_runtime)
 {
-       handle->inferior->notification_address = addr;
+       handle->mono_runtime = mono_runtime;
 }
 
 extern void GC_start_blocking (void);
@@ -502,6 +542,7 @@
        server_ptrace_create_inferior,
        server_ptrace_initialize_process,
        server_ptrace_initialize_thread,
+       server_ptrace_set_runtime_info,
        server_ptrace_spawn,
        server_ptrace_attach,
        server_ptrace_detach,
@@ -521,6 +562,7 @@
        server_ptrace_call_method_1,
        server_ptrace_call_method_2,
        server_ptrace_call_method_invoke,
+       server_ptrace_execute_instruction,
        server_ptrace_mark_rti_frame,
        server_ptrace_abort_invoke,
        server_ptrace_insert_breakpoint,
@@ -535,7 +577,6 @@
        server_ptrace_set_signal,
        server_ptrace_kill,
        server_ptrace_get_signal_info,
-       server_ptrace_set_notification,
        server_ptrace_get_threads,
        server_ptrace_get_application,
        server_ptrace_init_after_fork,

Modified: trunk/debugger/backend/server/x86_64-arch.c
===================================================================
--- trunk/debugger/backend/server/x86_64-arch.c 2007-10-31 15:44:36 UTC (rev 
88565)
+++ trunk/debugger/backend/server/x86_64-arch.c 2007-10-31 15:51:19 UTC (rev 
88566)
@@ -15,11 +15,22 @@
 
 #define AMD64_RED_ZONE_SIZE 128
 
+typedef struct
+{
+       int slot;
+       int insn_size;
+       int orig_insn_size;
+       gboolean pushed_retaddr;
+       guint64 code_address;
+       guint64 original_rip;
+} CodeBufferData;
+
 struct ArchInfo
 {
        INFERIOR_REGS_TYPE current_regs;
        INFERIOR_FPREGS_TYPE current_fpregs;
        GPtrArray *callback_stack;
+       CodeBufferData *code_buffer;
        guint64 dr_control, dr_status;
        guint64 pushed_regs_rsp;
        int dr_regs [DR_NADDR];
@@ -35,6 +46,9 @@
        guint64 rti_frame;
        guint64 exc_address;
        int saved_signal;
+       guint64 pushed_registers;
+       guint64 data_pointer;
+       guint32 data_size;
        gboolean debug;
 } CallbackData;
 
@@ -158,10 +172,12 @@
 
 ChildStoppedAction
 x86_arch_child_stopped (ServerHandle *handle, int stopsig,
-                       guint64 *callback_arg, guint64 *retval, guint64 
*retval2)
+                       guint64 *callback_arg, guint64 *retval, guint64 
*retval2,
+                       guint32 *opt_data_size, gpointer *opt_data)
 {
        ArchInfo *arch = handle->arch;
        InferiorHandle *inferior = handle->inferior;
+       CodeBufferData *cbuffer = NULL;
        CallbackData *cdata;
        guint64 code;
        int i;
@@ -171,7 +187,8 @@
        if (stopsig == SIGSTOP)
                return STOP_ACTION_INTERRUPTED;
 
-       if (INFERIOR_REG_RIP (arch->current_regs) - 1 == 
inferior->notification_address) {
+       if (handle->mono_runtime &&
+           (INFERIOR_REG_RIP (arch->current_regs) - 1 == 
handle->mono_runtime->notification_address)) {
                *callback_arg = INFERIOR_REG_RDI (arch->current_regs);
                *retval = INFERIOR_REG_RSI (arch->current_regs);
                *retval2 = INFERIOR_REG_RDX (arch->current_regs);
@@ -196,6 +213,27 @@
 
        cdata = get_callback_data (arch);
        if (cdata && (cdata->call_address == INFERIOR_REG_RIP 
(arch->current_regs))) {
+               if (cdata->pushed_registers) {
+                       guint64 pushed_regs [13];
+
+                       if (_server_ptrace_read_memory (handle, 
cdata->pushed_registers, 104, &pushed_regs))
+                               g_error (G_STRLOC ": Can't restore registers 
after returning from a call");
+
+                       INFERIOR_REG_RAX (cdata->saved_regs) = pushed_regs [0];
+                       INFERIOR_REG_RBX (cdata->saved_regs) = pushed_regs [1];
+                       INFERIOR_REG_RCX (cdata->saved_regs) = pushed_regs [2];
+                       INFERIOR_REG_RDX (cdata->saved_regs) = pushed_regs [3];
+                       INFERIOR_REG_RBP (cdata->saved_regs) = pushed_regs [4];
+                       INFERIOR_REG_RSP (cdata->saved_regs) = pushed_regs [5];
+                       INFERIOR_REG_RSI (cdata->saved_regs) = pushed_regs [6];
+                       INFERIOR_REG_RDI (cdata->saved_regs) = pushed_regs [7];
+                       INFERIOR_REG_RIP (cdata->saved_regs) = pushed_regs [8];
+                       INFERIOR_REG_R12 (cdata->saved_regs) = pushed_regs [9];
+                       INFERIOR_REG_R13 (cdata->saved_regs) = pushed_regs [10];
+                       INFERIOR_REG_R14 (cdata->saved_regs) = pushed_regs [11];
+                       INFERIOR_REG_R15 (cdata->saved_regs) = pushed_regs [12];
+               }
+
                if (_server_ptrace_set_registers (inferior, &cdata->saved_regs) 
!= COMMAND_ERROR_NONE)
                        g_error (G_STRLOC ": Can't restore registers after 
returning from a call");
 
@@ -205,6 +243,18 @@
                *callback_arg = cdata->callback_argument;
                *retval = INFERIOR_REG_RAX (arch->current_regs);
 
+               if (cdata->data_pointer) {
+                       *opt_data_size = cdata->data_size;
+                       *opt_data = g_malloc0 (cdata->data_size);
+
+                       if (_server_ptrace_read_memory (
+                                   handle, cdata->data_pointer, 
cdata->data_size, *opt_data))
+                               g_error (G_STRLOC ": Can't read data buffer 
after returning from a call");
+               } else {
+                       *opt_data_size = 0;
+                       *opt_data = NULL;
+               }
+
                if (cdata->exc_address &&
                    (server_ptrace_peek_word (handle, cdata->exc_address, 
retval2) != COMMAND_ERROR_NONE))
                        g_error (G_STRLOC ": Can't get exc object");
@@ -224,6 +274,37 @@
                return STOP_ACTION_CALLBACK;
        }
 
+       cbuffer = arch->code_buffer;
+       if (cbuffer) {
+               g_message (G_STRLOC ": %p,%d - %Lx - %d,%d - %Lx,%Lx", cbuffer, 
cbuffer->pushed_retaddr,
+                          cbuffer->original_rip, cbuffer->orig_insn_size, 
cbuffer->insn_size,
+                          cbuffer->code_address, INFERIOR_REG_RIP 
(arch->current_regs));
+
+               if (cbuffer->pushed_retaddr) {
+                       g_free (cbuffer);
+                       arch->code_buffer = NULL;
+                       return STOP_ACTION_STOPPED;
+               }
+
+               if (cbuffer->code_address + cbuffer->insn_size != 
INFERIOR_REG_RIP (arch->current_regs)) {
+                       g_warning (G_STRLOC ": %Lx,%d - %Lx - %Lx",
+                                  cbuffer->code_address, cbuffer->insn_size,
+                                  cbuffer->code_address + cbuffer->insn_size,
+                                  INFERIOR_REG_RIP (arch->current_regs));
+                       return STOP_ACTION_STOPPED;
+               }
+
+               INFERIOR_REG_RIP (arch->current_regs) = cbuffer->original_rip + 
cbuffer->orig_insn_size;
+               if (_server_ptrace_set_registers (inferior, 
&arch->current_regs) != COMMAND_ERROR_NONE) {
+                       g_error (G_STRLOC ": Can't restore registers");
+               }
+
+               g_free (cbuffer);
+               arch->code_buffer = NULL;
+               g_message (G_STRLOC ": %Lx", INFERIOR_REG_RIP 
(arch->current_regs));
+               return STOP_ACTION_STOPPED;
+       }
+
 #if defined(__linux__) || defined(__FreeBSD__)
        if (stopsig != SIGTRAP)
                return STOP_ACTION_STOPPED;
@@ -371,7 +452,83 @@
        return COMMAND_ERROR_NONE;
 }
 
+static int
+find_breakpoint_table_slot (MonoRuntimeInfo *runtime)
+{
+       int i;
+
+       for (i = 0; i < runtime->breakpoint_table_size; i++) {
+               if (runtime->breakpoint_table_bitfield [i])
+                       continue;
+
+               runtime->breakpoint_table_bitfield [i] = 1;
+               return i;
+       }
+
+       return -1;
+}
+
 static ServerCommandError
+runtime_info_enable_breakpoint (ServerHandle *handle, BreakpointInfo 
*breakpoint)
+{
+       MonoRuntimeInfo *runtime;
+       ServerCommandError result;
+       guint64 table_address, index_address;
+       int slot;
+
+       runtime = handle->mono_runtime;
+       g_assert (runtime);
+
+       slot = find_breakpoint_table_slot (runtime);
+       if (slot < 0)
+               return COMMAND_ERROR_INTERNAL_ERROR;
+
+       breakpoint->runtime_table_slot = slot;
+
+       table_address = runtime->breakpoint_info_area + 16 * slot;
+       index_address = runtime->breakpoint_table + 8 * slot;
+
+       result = server_ptrace_poke_word (handle, table_address, 
breakpoint->address);
+       if (result != COMMAND_ERROR_NONE)
+               return result;
+
+       result = server_ptrace_poke_word (handle, table_address + 8, (gsize) 
breakpoint->saved_insn);
+       if (result != COMMAND_ERROR_NONE)
+               return result;
+
+       result = server_ptrace_poke_word (handle, index_address, (gsize) 
table_address);
+       if (result != COMMAND_ERROR_NONE)
+               return result;
+
+       return COMMAND_ERROR_NONE;
+}
+
+static ServerCommandError
+runtime_info_disable_breakpoint (ServerHandle *handle, BreakpointInfo 
*breakpoint)
+{
+       MonoRuntimeInfo *runtime;
+       ServerCommandError result;
+       guint64 index_address;
+       int slot;
+
+       runtime = handle->mono_runtime;
+       g_assert (runtime);
+
+       return COMMAND_ERROR_NONE;
+
+       slot = breakpoint->runtime_table_slot;
+       index_address = runtime->breakpoint_table + runtime->address_size * 
slot;
+
+       result = server_ptrace_poke_word (handle, index_address, 0);
+       if (result != COMMAND_ERROR_NONE)
+               return result;
+
+       runtime->breakpoint_table_bitfield [slot] = 0;
+
+       return COMMAND_ERROR_NONE;
+}
+
+static ServerCommandError
 do_enable (ServerHandle *handle, BreakpointInfo *breakpoint)
 {
        ServerCommandError result;
@@ -412,6 +569,12 @@
                if (result != COMMAND_ERROR_NONE)
                        return result;
 
+               if (handle->mono_runtime) {
+                       result = runtime_info_enable_breakpoint (handle, 
breakpoint);
+                       if (result != COMMAND_ERROR_NONE)
+                               return result;
+               }
+
                result = server_ptrace_write_memory (handle, address, 1, 
&bopcode);
                if (result != COMMAND_ERROR_NONE)
                        return result;
@@ -453,6 +616,12 @@
                result = server_ptrace_write_memory (handle, address, 1, 
&breakpoint->saved_insn);
                if (result != COMMAND_ERROR_NONE)
                        return result;
+
+               if (handle->mono_runtime) {
+                       result = runtime_info_disable_breakpoint (handle, 
breakpoint);
+                       if (result != COMMAND_ERROR_NONE)
+                               return result;
+               }
        }
 
        return COMMAND_ERROR_NONE;
@@ -797,14 +966,15 @@
 
 static ServerCommandError
 server_ptrace_call_method_2 (ServerHandle *handle, guint64 method_address,
-                            guint64 method_argument, guint64 callback_argument)
+                            guint32 data_size, gconstpointer data_buffer,
+                            guint64 callback_argument)
 {
        ServerCommandError result = COMMAND_ERROR_NONE;
        ArchInfo *arch = handle->arch;
        CallbackData *cdata;
        long new_rsp;
 
-       int size = 116;
+       int size = 120 + data_size;
        guint8 *code = g_malloc0 (size);
 
        new_rsp = INFERIOR_REG_RSP (arch->current_regs) - AMD64_RED_ZONE_SIZE - 
size - 16;
@@ -824,7 +994,7 @@
        *((guint64 *) (code+88)) = INFERIOR_REG_R13 (arch->current_regs);
        *((guint64 *) (code+96)) = INFERIOR_REG_R14 (arch->current_regs);
        *((guint64 *) (code+104)) = INFERIOR_REG_R15 (arch->current_regs);
-       *((guint8 *) (code+112)) = 0xcc;
+       *((guint8 *) (code+data_size+116)) = 0xcc;
 
        cdata = g_new0 (CallbackData, 1);
        memcpy (&cdata->saved_regs, &arch->current_regs, sizeof 
(arch->current_regs));
@@ -834,8 +1004,15 @@
        cdata->exc_address = 0;
        cdata->callback_argument = callback_argument;
        cdata->saved_signal = handle->inferior->last_signal;
+       cdata->pushed_registers = new_rsp + 8;
        handle->inferior->last_signal = 0;
 
+       if (data_size > 0) {
+               memcpy (code+112, data_buffer, data_size);
+               cdata->data_pointer = new_rsp + 112;
+               cdata->data_size = data_size;
+       }
+
        server_ptrace_write_memory (handle, (unsigned long) new_rsp, size, 
code);
        g_free (code);
        if (result != COMMAND_ERROR_NONE)
@@ -843,7 +1020,7 @@
 
        INFERIOR_REG_RIP (arch->current_regs) = method_address;
        INFERIOR_REG_RDI (arch->current_regs) = new_rsp + 8;
-       INFERIOR_REG_RSI (arch->current_regs) = method_argument;
+       INFERIOR_REG_RSI (arch->current_regs) = new_rsp + 112;
        INFERIOR_REG_RSP (arch->current_regs) = new_rsp;
 
        g_ptr_array_add (arch->callback_stack, cdata);
@@ -927,7 +1104,83 @@
        return server_ptrace_continue (handle);
 }
 
+static int
+find_code_buffer_slot (MonoRuntimeInfo *runtime)
+{
+       int i;
+
+       for (i = 0; i < runtime->executable_code_total_chunks; i++) {
+               if (runtime->executable_code_bitfield [i])
+                       continue;
+
+               runtime->executable_code_bitfield [i] = 1;
+               return i;
+       }
+
+       return -1;
+}
+
 static ServerCommandError
+server_ptrace_execute_instruction (ServerHandle *handle, const guint8 
*instruction,
+                                  guint32 orig_size, guint32 size, gboolean 
push_retaddr)
+{
+       MonoRuntimeInfo *runtime;
+       ServerCommandError result;
+       CodeBufferData *data;
+       guint64 code_address;
+       int slot;
+
+       runtime = handle->mono_runtime;
+       g_assert (runtime);
+
+       slot = find_code_buffer_slot (runtime);
+       if (slot < 0)
+               return COMMAND_ERROR_INTERNAL_ERROR;
+
+       if (size > runtime->executable_code_chunk_size)
+               return COMMAND_ERROR_INTERNAL_ERROR;
+       if (handle->arch->code_buffer)
+               return COMMAND_ERROR_INTERNAL_ERROR;
+
+       code_address = runtime->executable_code_buffer + slot * 
runtime->executable_code_chunk_size;
+
+       g_message (G_STRLOC ": %d - %Lx - %d - %p", slot, code_address, size, 
instruction);
+
+       data = g_new0 (CodeBufferData, 1);
+       data->slot = slot;
+       data->insn_size = size;
+       data->orig_insn_size = orig_size;
+       data->pushed_retaddr = push_retaddr;
+       data->original_rip = INFERIOR_REG_RIP (handle->arch->current_regs);
+       data->code_address = code_address;
+
+       handle->arch->code_buffer = data;
+
+       result = server_ptrace_write_memory (handle, code_address, size, 
instruction);
+       if (result != COMMAND_ERROR_NONE)
+               return result;
+
+       if (push_retaddr) {
+               long old_rsp = INFERIOR_REG_RSP (handle->arch->current_regs);
+               long retaddr = INFERIOR_REG_RIP (handle->arch->current_regs) + 
orig_size;
+
+               result = server_ptrace_write_memory (handle, old_rsp - 8, 8, 
&retaddr);
+               if (result != COMMAND_ERROR_NONE)
+                       return result;
+
+               INFERIOR_REG_RSP (handle->arch->current_regs) -= 8;
+       }
+
+       INFERIOR_REG_RIP (handle->arch->current_regs) = code_address;
+
+       result = _server_ptrace_set_registers (handle->inferior, 
&handle->arch->current_regs);
+       if (result != COMMAND_ERROR_NONE)
+               return result;
+
+       return server_ptrace_step (handle);
+}
+
+static ServerCommandError
 server_ptrace_mark_rti_frame (ServerHandle *handle)
 {
        CallbackData *cdata;

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

Reply via email to