blob: b15bfcd9e2b33643a5223e4e533e9c350edfef2b [file] [log] [blame]
Alexandre Julliardf2792522007-03-09 13:40:41 +01001/*
2 * Server-side /proc support for Solaris
3 *
4 * Copyright (C) 2007 Alexandre Julliard
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21#include "config.h"
22
23#include <assert.h>
24#include <errno.h>
25#include <fcntl.h>
26#include <stdio.h>
27#include <signal.h>
28#include <stdarg.h>
29#include <sys/types.h>
30#include <unistd.h>
31
32#include "ntstatus.h"
33#define WIN32_NO_STATUS
34#include "winternl.h"
35
36#include "file.h"
37#include "process.h"
38#include "thread.h"
39
40#ifdef USE_PROCFS
41
42#include <procfs.h>
43
44static int open_proc_as( struct process *process, int flags )
45{
46 char buffer[32];
47 int fd;
48
49 sprintf( buffer, "/proc/%u/as", process->unix_pid );
50 if ((fd = open( buffer, flags )) == -1) file_set_error();
51 return fd;
52}
53
54static int open_proc_lwpctl( struct thread *thread )
55{
56 char buffer[48];
57 int fd;
58
59 sprintf( buffer, "/proc/%u/lwp/%u/lwpctl", thread->unix_pid, thread->unix_tid );
60 if ((fd = open( buffer, O_WRONLY )) == -1) file_set_error();
61 return fd;
62}
63
64
65/* handle a SIGCHLD signal */
66void sigchld_callback(void)
67{
68 assert( 0 ); /* should only be called when using ptrace */
69}
70
71/* initialize the process tracing mechanism */
72void init_tracing_mechanism(void)
73{
74 /* no initialization needed */
75}
76
77/* initialize the per-process tracing mechanism */
78void init_process_tracing( struct process *process )
79{
80 /* setup is done on-demand */
81}
82
83/* terminate the per-process tracing mechanism */
84void finish_process_tracing( struct process *process )
85{
86}
87
88/* send a Unix signal to a specific thread */
89int send_thread_signal( struct thread *thread, int sig )
90{
91 int fd = open_proc_lwpctl( thread );
92 long kill[2];
93 ssize_t ret;
94
95 if (fd == -1) return 0;
96
97 kill[0] = PCKILL;
98 kill[1] = sig;
99 ret = write( fd, kill, sizeof(kill) );
100 close( fd );
101 return (ret == sizeof(kill));
102}
103
104/* read data from a process memory space */
105int read_process_memory( struct process *process, const void *ptr, size_t size, char *dest )
106{
107 ssize_t ret;
108 int fd = open_proc_as( process, O_RDONLY );
109
110 if (fd == -1) return 0;
111
112 ret = pread( fd, dest, size, (off_t)ptr );
113 close( fd );
114 if (ret == size) return 1;
115
116 if (ret == -1) file_set_error();
117 else set_error( STATUS_ACCESS_VIOLATION );
118 return 0;
119}
120
121/* write data to a process memory space */
122int write_process_memory( struct process *process, void *ptr, size_t size, const char *src )
123{
124 ssize_t ret;
125 int fd = open_proc_as( process, O_WRONLY );
126
127 if (fd == -1) return 0;
128
129 ret = pwrite( fd, src, size, (off_t)ptr );
130 close( fd );
131 if (ret == size) return 1;
132
133 if (ret == -1) file_set_error();
134 else set_error( STATUS_ACCESS_VIOLATION );
135 return 0;
136}
137
138/* retrieve an LDT selector entry */
139void get_selector_entry( struct thread *thread, int entry, unsigned int *base,
140 unsigned int *limit, unsigned char *flags )
141{
142 ssize_t ret;
143 off_t pos = (off_t)thread->process->ldt_copy;
144 int fd = open_proc_as( thread->process, O_RDONLY );
145
146 if (fd == -1) return;
147
148 ret = pread( fd, base, sizeof(*base), pos + entry*sizeof(int) );
149 if (ret != sizeof(*base)) goto error;
150 ret = pread( fd, limit, sizeof(*limit), pos + (8192 + entry)*sizeof(int) );
151 if (ret != sizeof(*limit)) goto error;
152 ret = pread( fd, flags, sizeof(*flags), pos + 2*8192*sizeof(int) + entry );
153 if (ret != sizeof(*flags)) goto error;
154 close( fd );
155 return;
156
157error:
158 if (ret == -1) file_set_error();
159 else set_error( STATUS_ACCESS_VIOLATION );
160 close( fd );
161}
162
163/* retrieve the thread registers */
164void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int flags )
165{
166 /* all other regs are handled on the client side */
167 assert( (flags | CONTEXT_i386) == CONTEXT_DEBUG_REGISTERS );
168
169 /* FIXME: get debug registers */
170}
171
172/* set the thread registers */
173void set_thread_context( struct thread *thread, const CONTEXT *context, unsigned int flags )
174{
175 /* all other regs are handled on the client side */
176 assert( (flags | CONTEXT_i386) == CONTEXT_DEBUG_REGISTERS );
177
178 /* FIXME: set debug registers */
179}
180
181#endif /* USE_PROCFS */