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