1 /*
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
44 static int open_proc_as( struct process *process, int flags )
45 {
46 char buffer[32];
47 int fd;
48
49 if (process->unix_pid == -1)
50 {
51 set_error( STATUS_ACCESS_DENIED );
52 return -1;
53 }
54
55 sprintf( buffer, "/proc/%u/as", process->unix_pid );
56 if ((fd = open( buffer, flags )) == -1)
57 {
58 if (errno == ENOENT) /* probably got killed */
59 {
60 process->unix_pid = -1;
61 set_error( STATUS_ACCESS_DENIED );
62 }
63 else file_set_error();
64 }
65 return fd;
66 }
67
68 static int open_proc_lwpctl( struct thread *thread )
69 {
70 char buffer[48];
71 int fd;
72
73 if (thread->unix_pid == -1) return -1;
74
75 sprintf( buffer, "/proc/%u/lwp/%u/lwpctl", thread->unix_pid, thread->unix_tid );
76 if ((fd = open( buffer, O_WRONLY )) == -1)
77 {
78 if (errno == ENOENT) /* probably got killed */
79 thread->unix_pid = thread->unix_tid = -1;
80 else
81 file_set_error();
82 }
83 return fd;
84 }
85
86
87 /* handle a SIGCHLD signal */
88 void sigchld_callback(void)
89 {
90 assert( 0 ); /* should only be called when using ptrace */
91 }
92
93 /* initialize the process tracing mechanism */
94 void init_tracing_mechanism(void)
95 {
96 /* no initialization needed */
97 }
98
99 /* initialize the per-process tracing mechanism */
100 void init_process_tracing( struct process *process )
101 {
102 /* setup is done on-demand */
103 }
104
105 /* terminate the per-process tracing mechanism */
106 void finish_process_tracing( struct process *process )
107 {
108 }
109
110 /* send a Unix signal to a specific thread */
111 int send_thread_signal( struct thread *thread, int sig )
112 {
113 int fd = open_proc_lwpctl( thread );
114 long kill[2];
115 ssize_t ret;
116
117 if (fd == -1) return 0;
118
119 kill[0] = PCKILL;
120 kill[1] = sig;
121 ret = write( fd, kill, sizeof(kill) );
122 close( fd );
123 return (ret == sizeof(kill));
124 }
125
126 /* read data from a process memory space */
127 int read_process_memory( struct process *process, client_ptr_t ptr, size_t size, char *dest )
128 {
129 ssize_t ret;
130 int fd;
131
132 if ((off_t)ptr != ptr)
133 {
134 set_error( STATUS_ACCESS_DENIED );
135 return 0;
136 }
137
138 if ((fd = open_proc_as( process, O_RDONLY )) == -1) return 0;
139
140 ret = pread( fd, dest, size, (off_t)ptr );
141 close( fd );
142 if (ret == size) return 1;
143
144 if (ret == -1) file_set_error();
145 else set_error( STATUS_ACCESS_VIOLATION );
146 return 0;
147 }
148
149 /* write data to a process memory space */
150 int write_process_memory( struct process *process, client_ptr_t ptr, size_t size, const char *src )
151 {
152 ssize_t ret;
153 int fd;
154
155 if ((off_t)ptr != ptr)
156 {
157 set_error( STATUS_ACCESS_DENIED );
158 return 0;
159 }
160
161 if ((fd = open_proc_as( process, O_RDONLY )) == -1) return 0;
162
163 ret = pwrite( fd, src, size, (off_t)ptr );
164 close( fd );
165 if (ret == size) return 1;
166
167 if (ret == -1) file_set_error();
168 else set_error( STATUS_ACCESS_VIOLATION );
169 return 0;
170 }
171
172 /* retrieve an LDT selector entry */
173 void get_selector_entry( struct thread *thread, int entry, unsigned int *base,
174 unsigned int *limit, unsigned char *flags )
175 {
176 ssize_t ret;
177 off_t pos = thread->process->ldt_copy;
178 int fd;
179
180 if (!pos)
181 {
182 set_error( STATUS_ACCESS_DENIED );
183 return;
184 }
185 if ((fd = open_proc_as( thread->process, O_RDONLY )) == -1) return;
186
187 ret = pread( fd, base, sizeof(*base), pos + entry*sizeof(int) );
188 if (ret != sizeof(*base)) goto error;
189 ret = pread( fd, limit, sizeof(*limit), pos + (8192 + entry)*sizeof(int) );
190 if (ret != sizeof(*limit)) goto error;
191 ret = pread( fd, flags, sizeof(*flags), pos + 2*8192*sizeof(int) + entry );
192 if (ret != sizeof(*flags)) goto error;
193 close( fd );
194 return;
195
196 error:
197 if (ret == -1) file_set_error();
198 else set_error( STATUS_ACCESS_VIOLATION );
199 close( fd );
200 }
201
202 /* retrieve the thread registers */
203 void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int flags )
204 {
205 /* all other regs are handled on the client side */
206 assert( (flags | CONTEXT_i386) == CONTEXT_DEBUG_REGISTERS );
207
208 /* FIXME: get debug registers */
209 }
210
211 /* set the thread registers */
212 void set_thread_context( struct thread *thread, const CONTEXT *context, unsigned int flags )
213 {
214 /* all other regs are handled on the client side */
215 assert( (flags | CONTEXT_i386) == CONTEXT_DEBUG_REGISTERS );
216
217 /* FIXME: set debug registers */
218 }
219
220 #endif /* USE_PROCFS */
221
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.