Added support for ReadProcessMemory through the server.

oldstable
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 */
/* ### make_requests begin ### */
@ -883,6 +893,7 @@ enum request
REQ_SEND_DEBUG_EVENT,
REQ_CONTINUE_DEBUG_EVENT,
REQ_DEBUG_PROCESS,
REQ_READ_PROCESS_MEMORY,
REQ_NB_REQUESTS
};

View File

@ -1065,20 +1065,55 @@ BOOL WINAPI SetProcessPriorityBoost(HANDLE hprocess,BOOL disableboost)
return TRUE;
}
/***********************************************************************
* 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,
LPVOID lpBuffer, DWORD nSize,
LPDWORD lpNumberOfBytesRead )
BOOL WINAPI ReadProcessMemory( HANDLE process, LPCVOID addr, LPVOID buffer, DWORD size,
LPDWORD bytes_read )
{
memcpy(lpBuffer,lpBaseAddress,nSize);
if (lpNumberOfBytesRead) *lpNumberOfBytesRead = nSize;
return TRUE;
struct read_process_memory_request *req = get_req_buffer();
unsigned int offset = (unsigned int)addr % sizeof(int);
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)
* 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 ESPIPE: set_error( ERROR_SEEK ); 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;
}
}

View File

@ -5,11 +5,13 @@
*/
#include <assert.h>
#include <errno.h>
#include <limits.h>
#include <signal.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ptrace.h>
#include <sys/time.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 */
struct process_snapshot *process_snap( int *count )
{
@ -440,3 +474,16 @@ DECL_HANDLER(set_process_info)
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(continue_debug_event);
DECL_HANDLER(debug_process);
DECL_HANDLER(read_process_memory);
#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_continue_debug_event, sizeof(struct continue_debug_event_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 */

View File

@ -337,18 +337,19 @@ void continue_thread( struct thread *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;
if (thread->suspend < MAXIMUM_SUSPEND_COUNT)
if (thread->suspend < MAXIMUM_SUSPEND_COUNT || !check_limit)
{
if (!(thread->process->suspend + thread->suspend++)) stop_thread( thread );
}
else set_error( ERROR_SIGNAL_REFUSED );
return old_count;
}
/* resume a thread */
static int resume_thread( struct thread *thread )
int resume_thread( struct thread *thread )
{
int old_count = thread->suspend;
if (thread->suspend > 0)
@ -364,7 +365,7 @@ void suspend_all_threads( void )
struct thread *thread;
for ( thread = first_thread; thread; thread = thread->next )
if ( thread != current )
suspend_thread( thread );
suspend_thread( thread, 0 );
}
/* 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 )))
{
req->count = suspend_thread( thread );
req->count = suspend_thread( thread, 1 );
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 stop_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 resume_all_threads( void );
extern int add_queue( struct object *obj, struct wait_queue_entry *entry );

View File

@ -11,14 +11,35 @@
#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 */
static void dump_varargs_select( struct select_request *req )
{
int i;
for (i = 0; i < req->count; i++)
fprintf( stderr, "%c%d", i ? ',' : '{', req->handles[i] );
fprintf( stderr, "}" );
dump_ints( req->handles, req->count );
}
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 )
{
int i;
for (i = 0; i < FD_MAX_EVENTS; i++)
fprintf( stderr, "%c%d", i ? ',' : '{', req->errors[i] );
fprintf( stderr, "}" );
dump_ints( req->errors, FD_MAX_EVENTS );
}
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 );
}
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] = {
(dump_func)dump_new_process_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_continue_debug_event_request,
(dump_func)dump_debug_process_request,
(dump_func)dump_read_process_memory_request,
};
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)0,
(dump_func)0,
(dump_func)dump_read_process_memory_reply,
};
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",
"continue_debug_event",
"debug_process",
"read_process_memory",
};
/* ### make_requests end ### */