Added support for ReadProcessMemory through the server.

This commit is contained in:
Alexandre Julliard 1999-11-12 21:39:14 +00:00
parent ec7bb2391d
commit 8b8828f578
8 changed files with 160 additions and 21 deletions

View File

@ -807,6 +807,16 @@ struct debug_process_request
}; };
/* Read data from a process address space */
struct read_process_memory_request
{
IN int handle; /* process handle */
IN void* addr; /* addr to read from (must be int-aligned) */
IN int len; /* number of ints to read */
OUT unsigned int data[1]; /* result data */
};
/* Everything below this line is generated automatically by tools/make_requests */ /* Everything below this line is generated automatically by tools/make_requests */
/* ### make_requests begin ### */ /* ### make_requests begin ### */
@ -883,6 +893,7 @@ enum request
REQ_SEND_DEBUG_EVENT, REQ_SEND_DEBUG_EVENT,
REQ_CONTINUE_DEBUG_EVENT, REQ_CONTINUE_DEBUG_EVENT,
REQ_DEBUG_PROCESS, REQ_DEBUG_PROCESS,
REQ_READ_PROCESS_MEMORY,
REQ_NB_REQUESTS REQ_NB_REQUESTS
}; };

View File

@ -1065,20 +1065,55 @@ BOOL WINAPI SetProcessPriorityBoost(HANDLE hprocess,BOOL disableboost)
return TRUE; return TRUE;
} }
/*********************************************************************** /***********************************************************************
* ReadProcessMemory (KERNEL32) * ReadProcessMemory (KERNEL32)
* FIXME: check this, if we ever run win32 binaries in different addressspaces
* ... and add a sizecheck
*/ */
BOOL WINAPI ReadProcessMemory( HANDLE hProcess, LPCVOID lpBaseAddress, BOOL WINAPI ReadProcessMemory( HANDLE process, LPCVOID addr, LPVOID buffer, DWORD size,
LPVOID lpBuffer, DWORD nSize, LPDWORD bytes_read )
LPDWORD lpNumberOfBytesRead )
{ {
memcpy(lpBuffer,lpBaseAddress,nSize); struct read_process_memory_request *req = get_req_buffer();
if (lpNumberOfBytesRead) *lpNumberOfBytesRead = nSize; unsigned int offset = (unsigned int)addr % sizeof(int);
return TRUE; unsigned int max = server_remaining( req->data ); /* max length in one request */
unsigned int pos;
if (bytes_read) *bytes_read = size;
/* first time, read total length to check for permissions */
req->handle = process;
req->addr = (char *)addr - offset;
req->len = (size + offset + sizeof(int) - 1) / sizeof(int);
if (server_call( REQ_READ_PROCESS_MEMORY )) goto error;
if (size <= max - offset)
{
memcpy( buffer, (char *)req->data + offset, size );
return TRUE;
}
/* now take care of the remaining data */
memcpy( buffer, (char *)req->data + offset, max - offset );
pos = max - offset;
size -= pos;
while (size)
{
if (max > size) max = size;
req->handle = process;
req->addr = (char *)addr + pos;
req->len = (max + sizeof(int) - 1) / sizeof(int);
if (server_call( REQ_READ_PROCESS_MEMORY )) goto error;
memcpy( (char *)buffer + pos, (char *)req->data, max );
size -= max;
pos += max;
}
return TRUE;
error:
if (bytes_read) *bytes_read = 0;
return FALSE;
} }
/*********************************************************************** /***********************************************************************
* WriteProcessMemory (KERNEL32) * WriteProcessMemory (KERNEL32)
* FIXME: check this, if we ever run win32 binaries in different addressspaces * FIXME: check this, if we ever run win32 binaries in different addressspaces

View File

@ -366,6 +366,7 @@ void file_set_error(void)
case EINVAL: set_error( ERROR_INVALID_PARAMETER ); break; case EINVAL: set_error( ERROR_INVALID_PARAMETER ); break;
case ESPIPE: set_error( ERROR_SEEK ); break; case ESPIPE: set_error( ERROR_SEEK ); break;
case ENOTEMPTY: set_error( ERROR_DIR_NOT_EMPTY ); break; case ENOTEMPTY: set_error( ERROR_DIR_NOT_EMPTY ); break;
case EIO: set_error( ERROR_NOACCESS ); break;
default: perror("file_set_error"); set_error( ERROR_UNKNOWN ); break; default: perror("file_set_error"); set_error( ERROR_UNKNOWN ); break;
} }
} }

View File

@ -5,11 +5,13 @@
*/ */
#include <assert.h> #include <assert.h>
#include <errno.h>
#include <limits.h> #include <limits.h>
#include <signal.h> #include <signal.h>
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <sys/ptrace.h>
#include <sys/time.h> #include <sys/time.h>
#include <unistd.h> #include <unistd.h>
@ -314,6 +316,38 @@ static void set_process_info( struct process *process,
} }
} }
/* read data from a process memory space */
/* len is the total size (in ints), max is the size we can actually store in the input buffer */
/* we read the total size in all cases to check for permissions */
static void read_process_memory( struct process *process, const int *addr, int len,
int max, int *dest )
{
struct thread *thread = process->thread_list;
int pid = thread->unix_pid;
suspend_thread( thread, 0 );
if (thread->attached)
{
while (len-- > 0)
{
int data = ptrace( PT_READ_D, pid, addr );
if ((data == -1) && errno)
{
file_set_error();
break;
}
if (max)
{
*dest++ = data;
max--;
}
addr++;
}
}
else set_error( ERROR_ACCESS_DENIED );
resume_thread( thread );
}
/* take a snapshot of currently running processes */ /* take a snapshot of currently running processes */
struct process_snapshot *process_snap( int *count ) struct process_snapshot *process_snap( int *count )
{ {
@ -440,3 +474,16 @@ DECL_HANDLER(set_process_info)
release_object( process ); release_object( process );
} }
} }
/* read data from a process address space */
DECL_HANDLER(read_process_memory)
{
struct process *process;
if ((process = get_process_from_handle( req->handle, PROCESS_VM_READ )))
{
read_process_memory( process, req->addr, req->len,
get_req_size( req->data, sizeof(int) ), req->data );
release_object( process );
}
}

View File

@ -132,6 +132,7 @@ DECL_HANDLER(wait_debug_event);
DECL_HANDLER(send_debug_event); DECL_HANDLER(send_debug_event);
DECL_HANDLER(continue_debug_event); DECL_HANDLER(continue_debug_event);
DECL_HANDLER(debug_process); DECL_HANDLER(debug_process);
DECL_HANDLER(read_process_memory);
#ifdef WANT_REQUEST_HANDLERS #ifdef WANT_REQUEST_HANDLERS
@ -210,6 +211,7 @@ static const struct handler {
{ (void(*)())req_send_debug_event, sizeof(struct send_debug_event_request) }, { (void(*)())req_send_debug_event, sizeof(struct send_debug_event_request) },
{ (void(*)())req_continue_debug_event, sizeof(struct continue_debug_event_request) }, { (void(*)())req_continue_debug_event, sizeof(struct continue_debug_event_request) },
{ (void(*)())req_debug_process, sizeof(struct debug_process_request) }, { (void(*)())req_debug_process, sizeof(struct debug_process_request) },
{ (void(*)())req_read_process_memory, sizeof(struct read_process_memory_request) },
}; };
#endif /* WANT_REQUEST_HANDLERS */ #endif /* WANT_REQUEST_HANDLERS */

View File

@ -337,18 +337,19 @@ void continue_thread( struct thread *thread )
} }
/* suspend a thread */ /* suspend a thread */
static int suspend_thread( struct thread *thread ) int suspend_thread( struct thread *thread, int check_limit )
{ {
int old_count = thread->suspend; int old_count = thread->suspend;
if (thread->suspend < MAXIMUM_SUSPEND_COUNT) if (thread->suspend < MAXIMUM_SUSPEND_COUNT || !check_limit)
{ {
if (!(thread->process->suspend + thread->suspend++)) stop_thread( thread ); if (!(thread->process->suspend + thread->suspend++)) stop_thread( thread );
} }
else set_error( ERROR_SIGNAL_REFUSED );
return old_count; return old_count;
} }
/* resume a thread */ /* resume a thread */
static int resume_thread( struct thread *thread ) int resume_thread( struct thread *thread )
{ {
int old_count = thread->suspend; int old_count = thread->suspend;
if (thread->suspend > 0) if (thread->suspend > 0)
@ -364,7 +365,7 @@ void suspend_all_threads( void )
struct thread *thread; struct thread *thread;
for ( thread = first_thread; thread; thread = thread->next ) for ( thread = first_thread; thread; thread = thread->next )
if ( thread != current ) if ( thread != current )
suspend_thread( thread ); suspend_thread( thread, 0 );
} }
/* resume all threads but the current */ /* resume all threads but the current */
@ -709,7 +710,7 @@ DECL_HANDLER(suspend_thread)
if ((thread = get_thread_from_handle( req->handle, THREAD_SUSPEND_RESUME ))) if ((thread = get_thread_from_handle( req->handle, THREAD_SUSPEND_RESUME )))
{ {
req->count = suspend_thread( thread ); req->count = suspend_thread( thread, 1 );
release_object( thread ); release_object( thread );
} }
} }

View File

@ -69,6 +69,8 @@ extern struct thread *get_thread_from_handle( int handle, unsigned int access );
extern void wait4_thread( struct thread *thread, int wait ); extern void wait4_thread( struct thread *thread, int wait );
extern void stop_thread( struct thread *thread ); extern void stop_thread( struct thread *thread );
extern void continue_thread( struct thread *thread ); extern void continue_thread( struct thread *thread );
extern int suspend_thread( struct thread *thread, int check_limit );
extern int resume_thread( struct thread *thread );
extern void suspend_all_threads( void ); extern void suspend_all_threads( void );
extern void resume_all_threads( void ); extern void resume_all_threads( void );
extern int add_queue( struct object *obj, struct wait_queue_entry *entry ); extern int add_queue( struct object *obj, struct wait_queue_entry *entry );

View File

@ -11,14 +11,35 @@
#include "request.h" #include "request.h"
/* utility functions */
static void dump_ints( const int *ptr, int len )
{
fputc( '{', stderr );
while (len)
{
fprintf( stderr, "%d", *ptr++ );
if (--len) fputc( ',', stderr );
}
fputc( '}', stderr );
}
static void dump_bytes( const unsigned char *ptr, int len )
{
fputc( '{', stderr );
while (len)
{
fprintf( stderr, "%02x", *ptr++ );
if (--len) fputc( ',', stderr );
}
fputc( '}', stderr );
}
/* dumping for functions for requests that have a variable part */ /* dumping for functions for requests that have a variable part */
static void dump_varargs_select( struct select_request *req ) static void dump_varargs_select( struct select_request *req )
{ {
int i; dump_ints( req->handles, req->count );
for (i = 0; i < req->count; i++)
fprintf( stderr, "%c%d", i ? ',' : '{', req->handles[i] );
fprintf( stderr, "}" );
} }
static void dump_varargs_get_apcs( struct get_apcs_request *req ) static void dump_varargs_get_apcs( struct get_apcs_request *req )
@ -31,10 +52,13 @@ static void dump_varargs_get_apcs( struct get_apcs_request *req )
static void dump_varargs_get_socket_event( struct get_socket_event_request *req ) static void dump_varargs_get_socket_event( struct get_socket_event_request *req )
{ {
int i; dump_ints( req->errors, FD_MAX_EVENTS );
for (i = 0; i < FD_MAX_EVENTS; i++) }
fprintf( stderr, "%c%d", i ? ',' : '{', req->errors[i] );
fprintf( stderr, "}" ); static void dump_varargs_read_process_memory( struct read_process_memory_request *req )
{
int count = MIN( req->len, get_req_size( req->data, sizeof(int) ) );
dump_bytes( (unsigned char *)req->data, count * sizeof(int) );
} }
@ -763,6 +787,19 @@ static void dump_debug_process_request( struct debug_process_request *req )
fprintf( stderr, " pid=%p", req->pid ); fprintf( stderr, " pid=%p", req->pid );
} }
static void dump_read_process_memory_request( struct read_process_memory_request *req )
{
fprintf( stderr, " handle=%d,", req->handle );
fprintf( stderr, " addr=%p,", req->addr );
fprintf( stderr, " len=%d", req->len );
}
static void dump_read_process_memory_reply( struct read_process_memory_request *req )
{
fprintf( stderr, " data=" );
dump_varargs_read_process_memory( req );
}
static const dump_func req_dumpers[REQ_NB_REQUESTS] = { static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_new_process_request, (dump_func)dump_new_process_request,
(dump_func)dump_new_thread_request, (dump_func)dump_new_thread_request,
@ -835,6 +872,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_send_debug_event_request, (dump_func)dump_send_debug_event_request,
(dump_func)dump_continue_debug_event_request, (dump_func)dump_continue_debug_event_request,
(dump_func)dump_debug_process_request, (dump_func)dump_debug_process_request,
(dump_func)dump_read_process_memory_request,
}; };
static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
@ -909,6 +947,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_send_debug_event_reply, (dump_func)dump_send_debug_event_reply,
(dump_func)0, (dump_func)0,
(dump_func)0, (dump_func)0,
(dump_func)dump_read_process_memory_reply,
}; };
static const char * const req_names[REQ_NB_REQUESTS] = { static const char * const req_names[REQ_NB_REQUESTS] = {
@ -983,6 +1022,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"send_debug_event", "send_debug_event",
"continue_debug_event", "continue_debug_event",
"debug_process", "debug_process",
"read_process_memory",
}; };
/* ### make_requests end ### */ /* ### make_requests end ### */