diff --git a/server/Makefile.in b/server/Makefile.in index 50d35300b5f..bfd5c319926 100644 --- a/server/Makefile.in +++ b/server/Makefile.in @@ -32,6 +32,7 @@ C_SRCS = \ named_pipe.c \ object.c \ process.c \ + procfs.c \ ptrace.c \ queue.c \ region.c \ diff --git a/server/process.h b/server/process.h index 11a7d93b1f1..6f392406ffc 100644 --- a/server/process.h +++ b/server/process.h @@ -133,6 +133,8 @@ extern void enum_processes( int (*cb)(struct process*, void*), void *user); /* process tracing mechanism to use */ #ifdef __APPLE__ #define USE_MACH +#elif defined(__sun) +#define USE_PROCFS #else #define USE_PTRACE #endif diff --git a/server/procfs.c b/server/procfs.c new file mode 100644 index 00000000000..b15bfcd9e2b --- /dev/null +++ b/server/procfs.c @@ -0,0 +1,181 @@ +/* + * Server-side /proc support for Solaris + * + * Copyright (C) 2007 Alexandre Julliard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ntstatus.h" +#define WIN32_NO_STATUS +#include "winternl.h" + +#include "file.h" +#include "process.h" +#include "thread.h" + +#ifdef USE_PROCFS + +#include + +static int open_proc_as( struct process *process, int flags ) +{ + char buffer[32]; + int fd; + + sprintf( buffer, "/proc/%u/as", process->unix_pid ); + if ((fd = open( buffer, flags )) == -1) file_set_error(); + return fd; +} + +static int open_proc_lwpctl( struct thread *thread ) +{ + char buffer[48]; + int fd; + + sprintf( buffer, "/proc/%u/lwp/%u/lwpctl", thread->unix_pid, thread->unix_tid ); + if ((fd = open( buffer, O_WRONLY )) == -1) file_set_error(); + return fd; +} + + +/* handle a SIGCHLD signal */ +void sigchld_callback(void) +{ + assert( 0 ); /* should only be called when using ptrace */ +} + +/* initialize the process tracing mechanism */ +void init_tracing_mechanism(void) +{ + /* no initialization needed */ +} + +/* initialize the per-process tracing mechanism */ +void init_process_tracing( struct process *process ) +{ + /* setup is done on-demand */ +} + +/* terminate the per-process tracing mechanism */ +void finish_process_tracing( struct process *process ) +{ +} + +/* send a Unix signal to a specific thread */ +int send_thread_signal( struct thread *thread, int sig ) +{ + int fd = open_proc_lwpctl( thread ); + long kill[2]; + ssize_t ret; + + if (fd == -1) return 0; + + kill[0] = PCKILL; + kill[1] = sig; + ret = write( fd, kill, sizeof(kill) ); + close( fd ); + return (ret == sizeof(kill)); +} + +/* read data from a process memory space */ +int read_process_memory( struct process *process, const void *ptr, size_t size, char *dest ) +{ + ssize_t ret; + int fd = open_proc_as( process, O_RDONLY ); + + if (fd == -1) return 0; + + ret = pread( fd, dest, size, (off_t)ptr ); + close( fd ); + if (ret == size) return 1; + + if (ret == -1) file_set_error(); + else set_error( STATUS_ACCESS_VIOLATION ); + return 0; +} + +/* write data to a process memory space */ +int write_process_memory( struct process *process, void *ptr, size_t size, const char *src ) +{ + ssize_t ret; + int fd = open_proc_as( process, O_WRONLY ); + + if (fd == -1) return 0; + + ret = pwrite( fd, src, size, (off_t)ptr ); + close( fd ); + if (ret == size) return 1; + + if (ret == -1) file_set_error(); + else set_error( STATUS_ACCESS_VIOLATION ); + return 0; +} + +/* retrieve an LDT selector entry */ +void get_selector_entry( struct thread *thread, int entry, unsigned int *base, + unsigned int *limit, unsigned char *flags ) +{ + ssize_t ret; + off_t pos = (off_t)thread->process->ldt_copy; + int fd = open_proc_as( thread->process, O_RDONLY ); + + if (fd == -1) return; + + ret = pread( fd, base, sizeof(*base), pos + entry*sizeof(int) ); + if (ret != sizeof(*base)) goto error; + ret = pread( fd, limit, sizeof(*limit), pos + (8192 + entry)*sizeof(int) ); + if (ret != sizeof(*limit)) goto error; + ret = pread( fd, flags, sizeof(*flags), pos + 2*8192*sizeof(int) + entry ); + if (ret != sizeof(*flags)) goto error; + close( fd ); + return; + +error: + if (ret == -1) file_set_error(); + else set_error( STATUS_ACCESS_VIOLATION ); + close( fd ); +} + +/* retrieve the thread registers */ +void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int flags ) +{ + /* all other regs are handled on the client side */ + assert( (flags | CONTEXT_i386) == CONTEXT_DEBUG_REGISTERS ); + + /* FIXME: get debug registers */ +} + +/* set the thread registers */ +void set_thread_context( struct thread *thread, const CONTEXT *context, unsigned int flags ) +{ + /* all other regs are handled on the client side */ + assert( (flags | CONTEXT_i386) == CONTEXT_DEBUG_REGISTERS ); + + /* FIXME: set debug registers */ +} + +#endif /* USE_PROCFS */