mirror of
https://github.com/reactos/wine.git
synced 2024-11-25 12:49:45 +00:00
server: Moved read/write_process_memory and get_selector_entry to ptrace.c.
This commit is contained in:
parent
0b492c708f
commit
cb70931f67
131
server/process.c
131
server/process.c
@ -709,137 +709,6 @@ void enum_processes( int (*cb)(struct process*, void*), void *user )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* read data from a process memory space */
|
|
||||||
static int read_process_memory( struct process *process, const void *ptr, size_t size, char *dest )
|
|
||||||
{
|
|
||||||
struct thread *thread = get_process_first_thread( process );
|
|
||||||
unsigned int first_offset, last_offset, len;
|
|
||||||
int data, *addr;
|
|
||||||
|
|
||||||
if (!thread) /* process is dead */
|
|
||||||
{
|
|
||||||
set_error( STATUS_ACCESS_DENIED );
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
first_offset = (unsigned long)ptr % sizeof(int);
|
|
||||||
last_offset = (size + first_offset) % sizeof(int);
|
|
||||||
if (!last_offset) last_offset = sizeof(int);
|
|
||||||
|
|
||||||
addr = (int *)((char *)ptr - first_offset);
|
|
||||||
len = (size + first_offset + sizeof(int) - 1) / sizeof(int);
|
|
||||||
|
|
||||||
if (suspend_for_ptrace( thread ))
|
|
||||||
{
|
|
||||||
if (len > 1)
|
|
||||||
{
|
|
||||||
if (read_thread_int( thread, addr++, &data ) == -1) goto done;
|
|
||||||
memcpy( dest, (char *)&data + first_offset, sizeof(int) - first_offset );
|
|
||||||
dest += sizeof(int) - first_offset;
|
|
||||||
first_offset = 0;
|
|
||||||
len--;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (len > 1)
|
|
||||||
{
|
|
||||||
if (read_thread_int( thread, addr++, &data ) == -1) goto done;
|
|
||||||
memcpy( dest, &data, sizeof(int) );
|
|
||||||
dest += sizeof(int);
|
|
||||||
len--;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (read_thread_int( thread, addr++, &data ) == -1) goto done;
|
|
||||||
memcpy( dest, (char *)&data + first_offset, last_offset - first_offset );
|
|
||||||
len--;
|
|
||||||
|
|
||||||
done:
|
|
||||||
resume_after_ptrace( thread );
|
|
||||||
}
|
|
||||||
return !len;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* make sure we can write to the whole address range */
|
|
||||||
/* len is the total size (in ints) */
|
|
||||||
static int check_process_write_access( struct thread *thread, int *addr, size_t len )
|
|
||||||
{
|
|
||||||
int page = get_page_size() / sizeof(int);
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
if (write_thread_int( thread, addr, 0, 0 ) == -1) return 0;
|
|
||||||
if (len <= page) break;
|
|
||||||
addr += page;
|
|
||||||
len -= page;
|
|
||||||
}
|
|
||||||
return (write_thread_int( thread, addr + len - 1, 0, 0 ) != -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* write data to a process memory space */
|
|
||||||
static int write_process_memory( struct process *process, void *ptr, size_t size, const char *src )
|
|
||||||
{
|
|
||||||
struct thread *thread = get_process_first_thread( process );
|
|
||||||
int ret = 0, data = 0;
|
|
||||||
size_t len;
|
|
||||||
int *addr;
|
|
||||||
unsigned int first_mask, first_offset, last_mask, last_offset;
|
|
||||||
|
|
||||||
if (!thread) /* process is dead */
|
|
||||||
{
|
|
||||||
set_error( STATUS_ACCESS_DENIED );
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* compute the mask for the first int */
|
|
||||||
first_mask = ~0;
|
|
||||||
first_offset = (unsigned long)ptr % sizeof(int);
|
|
||||||
memset( &first_mask, 0, first_offset );
|
|
||||||
|
|
||||||
/* compute the mask for the last int */
|
|
||||||
last_offset = (size + first_offset) % sizeof(int);
|
|
||||||
if (!last_offset) last_offset = sizeof(int);
|
|
||||||
last_mask = 0;
|
|
||||||
memset( &last_mask, 0xff, last_offset );
|
|
||||||
|
|
||||||
addr = (int *)((char *)ptr - first_offset);
|
|
||||||
len = (size + first_offset + sizeof(int) - 1) / sizeof(int);
|
|
||||||
|
|
||||||
if (suspend_for_ptrace( thread ))
|
|
||||||
{
|
|
||||||
if (!check_process_write_access( thread, addr, len ))
|
|
||||||
{
|
|
||||||
set_error( STATUS_ACCESS_DENIED );
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
/* first word is special */
|
|
||||||
if (len > 1)
|
|
||||||
{
|
|
||||||
memcpy( (char *)&data + first_offset, src, sizeof(int) - first_offset );
|
|
||||||
src += sizeof(int) - first_offset;
|
|
||||||
if (write_thread_int( thread, addr++, data, first_mask ) == -1) goto done;
|
|
||||||
first_offset = 0;
|
|
||||||
len--;
|
|
||||||
}
|
|
||||||
else last_mask &= first_mask;
|
|
||||||
|
|
||||||
while (len > 1)
|
|
||||||
{
|
|
||||||
memcpy( &data, src, sizeof(int) );
|
|
||||||
src += sizeof(int);
|
|
||||||
if (write_thread_int( thread, addr++, data, ~0 ) == -1) goto done;
|
|
||||||
len--;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* last word is special too */
|
|
||||||
memcpy( (char *)&data + first_offset, src, last_offset - first_offset );
|
|
||||||
if (write_thread_int( thread, addr, data, last_mask ) == -1) goto done;
|
|
||||||
ret = 1;
|
|
||||||
|
|
||||||
done:
|
|
||||||
resume_after_ptrace( thread );
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* set the debugged flag in the process PEB */
|
/* set the debugged flag in the process PEB */
|
||||||
int set_process_debug_flag( struct process *process, int flag )
|
int set_process_debug_flag( struct process *process, int flag )
|
||||||
{
|
{
|
||||||
|
@ -125,6 +125,8 @@ extern void detach_debugged_processes( struct thread *debugger );
|
|||||||
extern struct process_snapshot *process_snap( int *count );
|
extern struct process_snapshot *process_snap( int *count );
|
||||||
extern struct module_snapshot *module_snap( struct process *process, int *count );
|
extern struct module_snapshot *module_snap( struct process *process, int *count );
|
||||||
extern void enum_processes( int (*cb)(struct process*, void*), void *user);
|
extern void enum_processes( int (*cb)(struct process*, void*), void *user);
|
||||||
|
extern int read_process_memory( struct process *process, const void *ptr, size_t size, char *dest );
|
||||||
|
extern int write_process_memory( struct process *process, void *ptr, size_t size, const char *src );
|
||||||
|
|
||||||
inline static process_id_t get_process_id( struct process *process ) { return process->id; }
|
inline static process_id_t get_process_id( struct process *process ) { return process->id; }
|
||||||
|
|
||||||
|
163
server/ptrace.c
163
server/ptrace.c
@ -279,7 +279,7 @@ void resume_after_ptrace( struct thread *thread )
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* read an int from a thread address space */
|
/* read an int from a thread address space */
|
||||||
int read_thread_int( struct thread *thread, const int *addr, int *data )
|
static int read_thread_int( struct thread *thread, const int *addr, int *data )
|
||||||
{
|
{
|
||||||
errno = 0;
|
errno = 0;
|
||||||
*data = ptrace( PTRACE_PEEKDATA, get_ptrace_pid(thread), (caddr_t)addr, 0 );
|
*data = ptrace( PTRACE_PEEKDATA, get_ptrace_pid(thread), (caddr_t)addr, 0 );
|
||||||
@ -292,7 +292,7 @@ int read_thread_int( struct thread *thread, const int *addr, int *data )
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* write an int to a thread address space */
|
/* write an int to a thread address space */
|
||||||
int write_thread_int( struct thread *thread, int *addr, int data, unsigned int mask )
|
static int write_thread_int( struct thread *thread, int *addr, int data, unsigned int mask )
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
if (mask != ~0)
|
if (mask != ~0)
|
||||||
@ -304,3 +304,162 @@ int write_thread_int( struct thread *thread, int *addr, int data, unsigned int m
|
|||||||
file_set_error();
|
file_set_error();
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* read data from a process memory space */
|
||||||
|
int read_process_memory( struct process *process, const void *ptr, size_t size, char *dest )
|
||||||
|
{
|
||||||
|
struct thread *thread = get_process_first_thread( process );
|
||||||
|
unsigned int first_offset, last_offset, len;
|
||||||
|
int data, *addr;
|
||||||
|
|
||||||
|
if (!thread) /* process is dead */
|
||||||
|
{
|
||||||
|
set_error( STATUS_ACCESS_DENIED );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
first_offset = (unsigned long)ptr % sizeof(int);
|
||||||
|
last_offset = (size + first_offset) % sizeof(int);
|
||||||
|
if (!last_offset) last_offset = sizeof(int);
|
||||||
|
|
||||||
|
addr = (int *)((char *)ptr - first_offset);
|
||||||
|
len = (size + first_offset + sizeof(int) - 1) / sizeof(int);
|
||||||
|
|
||||||
|
if (suspend_for_ptrace( thread ))
|
||||||
|
{
|
||||||
|
if (len > 1)
|
||||||
|
{
|
||||||
|
if (read_thread_int( thread, addr++, &data ) == -1) goto done;
|
||||||
|
memcpy( dest, (char *)&data + first_offset, sizeof(int) - first_offset );
|
||||||
|
dest += sizeof(int) - first_offset;
|
||||||
|
first_offset = 0;
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (len > 1)
|
||||||
|
{
|
||||||
|
if (read_thread_int( thread, addr++, &data ) == -1) goto done;
|
||||||
|
memcpy( dest, &data, sizeof(int) );
|
||||||
|
dest += sizeof(int);
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (read_thread_int( thread, addr++, &data ) == -1) goto done;
|
||||||
|
memcpy( dest, (char *)&data + first_offset, last_offset - first_offset );
|
||||||
|
len--;
|
||||||
|
|
||||||
|
done:
|
||||||
|
resume_after_ptrace( thread );
|
||||||
|
}
|
||||||
|
return !len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* make sure we can write to the whole address range */
|
||||||
|
/* len is the total size (in ints) */
|
||||||
|
static int check_process_write_access( struct thread *thread, int *addr, size_t len )
|
||||||
|
{
|
||||||
|
int page = get_page_size() / sizeof(int);
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (write_thread_int( thread, addr, 0, 0 ) == -1) return 0;
|
||||||
|
if (len <= page) break;
|
||||||
|
addr += page;
|
||||||
|
len -= page;
|
||||||
|
}
|
||||||
|
return (write_thread_int( thread, addr + len - 1, 0, 0 ) != -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* write data to a process memory space */
|
||||||
|
int write_process_memory( struct process *process, void *ptr, size_t size, const char *src )
|
||||||
|
{
|
||||||
|
struct thread *thread = get_process_first_thread( process );
|
||||||
|
int ret = 0, data = 0;
|
||||||
|
size_t len;
|
||||||
|
int *addr;
|
||||||
|
unsigned int first_mask, first_offset, last_mask, last_offset;
|
||||||
|
|
||||||
|
if (!thread) /* process is dead */
|
||||||
|
{
|
||||||
|
set_error( STATUS_ACCESS_DENIED );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* compute the mask for the first int */
|
||||||
|
first_mask = ~0;
|
||||||
|
first_offset = (unsigned long)ptr % sizeof(int);
|
||||||
|
memset( &first_mask, 0, first_offset );
|
||||||
|
|
||||||
|
/* compute the mask for the last int */
|
||||||
|
last_offset = (size + first_offset) % sizeof(int);
|
||||||
|
if (!last_offset) last_offset = sizeof(int);
|
||||||
|
last_mask = 0;
|
||||||
|
memset( &last_mask, 0xff, last_offset );
|
||||||
|
|
||||||
|
addr = (int *)((char *)ptr - first_offset);
|
||||||
|
len = (size + first_offset + sizeof(int) - 1) / sizeof(int);
|
||||||
|
|
||||||
|
if (suspend_for_ptrace( thread ))
|
||||||
|
{
|
||||||
|
if (!check_process_write_access( thread, addr, len ))
|
||||||
|
{
|
||||||
|
set_error( STATUS_ACCESS_DENIED );
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
/* first word is special */
|
||||||
|
if (len > 1)
|
||||||
|
{
|
||||||
|
memcpy( (char *)&data + first_offset, src, sizeof(int) - first_offset );
|
||||||
|
src += sizeof(int) - first_offset;
|
||||||
|
if (write_thread_int( thread, addr++, data, first_mask ) == -1) goto done;
|
||||||
|
first_offset = 0;
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
else last_mask &= first_mask;
|
||||||
|
|
||||||
|
while (len > 1)
|
||||||
|
{
|
||||||
|
memcpy( &data, src, sizeof(int) );
|
||||||
|
src += sizeof(int);
|
||||||
|
if (write_thread_int( thread, addr++, data, ~0 ) == -1) goto done;
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* last word is special too */
|
||||||
|
memcpy( (char *)&data + first_offset, src, last_offset - first_offset );
|
||||||
|
if (write_thread_int( thread, addr, data, last_mask ) == -1) goto done;
|
||||||
|
ret = 1;
|
||||||
|
|
||||||
|
done:
|
||||||
|
resume_after_ptrace( thread );
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* retrieve an LDT selector entry */
|
||||||
|
void get_selector_entry( struct thread *thread, int entry, unsigned int *base,
|
||||||
|
unsigned int *limit, unsigned char *flags )
|
||||||
|
{
|
||||||
|
if (!thread->process->ldt_copy)
|
||||||
|
{
|
||||||
|
set_error( STATUS_ACCESS_DENIED );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (entry >= 8192)
|
||||||
|
{
|
||||||
|
set_error( STATUS_INVALID_PARAMETER ); /* FIXME */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (suspend_for_ptrace( thread ))
|
||||||
|
{
|
||||||
|
unsigned char flags_buf[4];
|
||||||
|
int *addr = (int *)thread->process->ldt_copy + entry;
|
||||||
|
if (read_thread_int( thread, addr, (int *)base ) == -1) goto done;
|
||||||
|
if (read_thread_int( thread, addr + 8192, (int *)limit ) == -1) goto done;
|
||||||
|
addr = (int *)thread->process->ldt_copy + 2*8192 + (entry >> 2);
|
||||||
|
if (read_thread_int( thread, addr, (int *)flags_buf ) == -1) goto done;
|
||||||
|
*flags = flags_buf[entry & 3];
|
||||||
|
done:
|
||||||
|
resume_after_ptrace( thread );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -733,35 +733,6 @@ int thread_get_inflight_fd( struct thread *thread, int client )
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* retrieve an LDT selector entry */
|
|
||||||
static void get_selector_entry( struct thread *thread, int entry,
|
|
||||||
unsigned int *base, unsigned int *limit,
|
|
||||||
unsigned char *flags )
|
|
||||||
{
|
|
||||||
if (!thread->process->ldt_copy)
|
|
||||||
{
|
|
||||||
set_error( STATUS_ACCESS_DENIED );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (entry >= 8192)
|
|
||||||
{
|
|
||||||
set_error( STATUS_INVALID_PARAMETER ); /* FIXME */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (suspend_for_ptrace( thread ))
|
|
||||||
{
|
|
||||||
unsigned char flags_buf[4];
|
|
||||||
int *addr = (int *)thread->process->ldt_copy + entry;
|
|
||||||
if (read_thread_int( thread, addr, (int *)base ) == -1) goto done;
|
|
||||||
if (read_thread_int( thread, addr + 8192, (int *)limit ) == -1) goto done;
|
|
||||||
addr = (int *)thread->process->ldt_copy + 2*8192 + (entry >> 2);
|
|
||||||
if (read_thread_int( thread, addr, (int *)flags_buf ) == -1) goto done;
|
|
||||||
*flags = flags_buf[entry & 3];
|
|
||||||
done:
|
|
||||||
resume_after_ptrace( thread );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* kill a thread on the spot */
|
/* kill a thread on the spot */
|
||||||
void kill_thread( struct thread *thread, int violent_death )
|
void kill_thread( struct thread *thread, int violent_death )
|
||||||
{
|
{
|
||||||
|
@ -126,14 +126,14 @@ extern int attach_process( struct process *process );
|
|||||||
extern void detach_process( struct process *process );
|
extern void detach_process( struct process *process );
|
||||||
extern int suspend_for_ptrace( struct thread *thread );
|
extern int suspend_for_ptrace( struct thread *thread );
|
||||||
extern void resume_after_ptrace( struct thread *thread );
|
extern void resume_after_ptrace( struct thread *thread );
|
||||||
extern int read_thread_int( struct thread *thread, const int *addr, int *data );
|
|
||||||
extern int write_thread_int( struct thread *thread, int *addr, int data, unsigned int mask );
|
|
||||||
extern void *get_thread_ip( struct thread *thread );
|
extern void *get_thread_ip( struct thread *thread );
|
||||||
extern int get_thread_single_step( struct thread *thread );
|
extern int get_thread_single_step( struct thread *thread );
|
||||||
extern void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int flags );
|
extern void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int flags );
|
||||||
extern void set_thread_context( struct thread *thread, const CONTEXT *context, unsigned int flags );
|
extern void set_thread_context( struct thread *thread, const CONTEXT *context, unsigned int flags );
|
||||||
extern int tkill( int tgid, int pid, int sig );
|
extern int tkill( int tgid, int pid, int sig );
|
||||||
extern int send_thread_signal( struct thread *thread, int sig );
|
extern int send_thread_signal( struct thread *thread, int sig );
|
||||||
|
extern void get_selector_entry( struct thread *thread, int entry, unsigned int *base,
|
||||||
|
unsigned int *limit, unsigned char *flags );
|
||||||
|
|
||||||
extern unsigned int global_error; /* global error code for when no thread is current */
|
extern unsigned int global_error; /* global error code for when no thread is current */
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user