blob: 5caa02b66df8309c9f2a75c317a53e6d3316107e [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
Alexandre Julliarda30778b2009-09-01 17:39:51 +020042/* procfs doesn't support large files */
43# undef _FILE_OFFSET_BITS
44# define _FILE_OFFSET_BITS 32
Alexandre Julliardf2792522007-03-09 13:40:41 +010045#include <procfs.h>
46
47static int open_proc_as( struct process *process, int flags )
48{
49 char buffer[32];
50 int fd;
51
Alexandre Julliard44043a72008-07-10 20:15:15 +020052 if (process->unix_pid == -1)
53 {
54 set_error( STATUS_ACCESS_DENIED );
55 return -1;
56 }
57
Alexandre Julliardf2792522007-03-09 13:40:41 +010058 sprintf( buffer, "/proc/%u/as", process->unix_pid );
Alexandre Julliard44043a72008-07-10 20:15:15 +020059 if ((fd = open( buffer, flags )) == -1)
60 {
61 if (errno == ENOENT) /* probably got killed */
62 {
63 process->unix_pid = -1;
64 set_error( STATUS_ACCESS_DENIED );
65 }
66 else file_set_error();
67 }
Alexandre Julliardf2792522007-03-09 13:40:41 +010068 return fd;
69}
70
71static int open_proc_lwpctl( struct thread *thread )
72{
73 char buffer[48];
74 int fd;
75
Alexandre Julliard44043a72008-07-10 20:15:15 +020076 if (thread->unix_pid == -1) return -1;
77
Alexandre Julliardf2792522007-03-09 13:40:41 +010078 sprintf( buffer, "/proc/%u/lwp/%u/lwpctl", thread->unix_pid, thread->unix_tid );
Alexandre Julliard44043a72008-07-10 20:15:15 +020079 if ((fd = open( buffer, O_WRONLY )) == -1)
80 {
81 if (errno == ENOENT) /* probably got killed */
82 thread->unix_pid = thread->unix_tid = -1;
83 else
84 file_set_error();
85 }
Alexandre Julliardf2792522007-03-09 13:40:41 +010086 return fd;
87}
88
89
90/* handle a SIGCHLD signal */
91void sigchld_callback(void)
92{
93 assert( 0 ); /* should only be called when using ptrace */
94}
95
96/* initialize the process tracing mechanism */
97void init_tracing_mechanism(void)
98{
99 /* no initialization needed */
100}
101
102/* initialize the per-process tracing mechanism */
103void init_process_tracing( struct process *process )
104{
105 /* setup is done on-demand */
106}
107
108/* terminate the per-process tracing mechanism */
109void finish_process_tracing( struct process *process )
110{
111}
112
113/* send a Unix signal to a specific thread */
114int send_thread_signal( struct thread *thread, int sig )
115{
116 int fd = open_proc_lwpctl( thread );
117 long kill[2];
118 ssize_t ret;
119
120 if (fd == -1) return 0;
121
122 kill[0] = PCKILL;
123 kill[1] = sig;
124 ret = write( fd, kill, sizeof(kill) );
125 close( fd );
126 return (ret == sizeof(kill));
127}
128
129/* read data from a process memory space */
Alexandre Julliard8e9c1562008-12-30 14:11:58 +0100130int read_process_memory( struct process *process, client_ptr_t ptr, size_t size, char *dest )
Alexandre Julliardf2792522007-03-09 13:40:41 +0100131{
132 ssize_t ret;
Alexandre Julliard8e9c1562008-12-30 14:11:58 +0100133 int fd;
Alexandre Julliardf2792522007-03-09 13:40:41 +0100134
Alexandre Julliard8e9c1562008-12-30 14:11:58 +0100135 if ((off_t)ptr != ptr)
136 {
137 set_error( STATUS_ACCESS_DENIED );
138 return 0;
139 }
140
141 if ((fd = open_proc_as( process, O_RDONLY )) == -1) return 0;
Alexandre Julliardf2792522007-03-09 13:40:41 +0100142
143 ret = pread( fd, dest, size, (off_t)ptr );
144 close( fd );
145 if (ret == size) return 1;
146
147 if (ret == -1) file_set_error();
148 else set_error( STATUS_ACCESS_VIOLATION );
149 return 0;
150}
151
152/* write data to a process memory space */
Alexandre Julliard8e9c1562008-12-30 14:11:58 +0100153int write_process_memory( struct process *process, client_ptr_t ptr, size_t size, const char *src )
Alexandre Julliardf2792522007-03-09 13:40:41 +0100154{
155 ssize_t ret;
Alexandre Julliard8e9c1562008-12-30 14:11:58 +0100156 int fd;
Alexandre Julliardf2792522007-03-09 13:40:41 +0100157
Alexandre Julliard8e9c1562008-12-30 14:11:58 +0100158 if ((off_t)ptr != ptr)
159 {
160 set_error( STATUS_ACCESS_DENIED );
161 return 0;
162 }
163
Andrey Turkin5116dca2009-10-22 17:09:51 +0400164 if ((fd = open_proc_as( process, O_WRONLY )) == -1) return 0;
Alexandre Julliardf2792522007-03-09 13:40:41 +0100165
166 ret = pwrite( fd, src, size, (off_t)ptr );
167 close( fd );
168 if (ret == size) return 1;
169
170 if (ret == -1) file_set_error();
171 else set_error( STATUS_ACCESS_VIOLATION );
172 return 0;
173}
174
175/* retrieve an LDT selector entry */
176void get_selector_entry( struct thread *thread, int entry, unsigned int *base,
177 unsigned int *limit, unsigned char *flags )
178{
179 ssize_t ret;
Alexandre Julliard2cf868c2008-12-30 22:47:48 +0100180 off_t pos = thread->process->ldt_copy;
181 int fd;
Alexandre Julliardf2792522007-03-09 13:40:41 +0100182
Alexandre Julliard2cf868c2008-12-30 22:47:48 +0100183 if (!pos)
184 {
185 set_error( STATUS_ACCESS_DENIED );
Alexandre Julliard548e1892009-01-30 14:04:56 +0100186 return;
Alexandre Julliard2cf868c2008-12-30 22:47:48 +0100187 }
188 if ((fd = open_proc_as( thread->process, O_RDONLY )) == -1) return;
Alexandre Julliardf2792522007-03-09 13:40:41 +0100189
190 ret = pread( fd, base, sizeof(*base), pos + entry*sizeof(int) );
191 if (ret != sizeof(*base)) goto error;
192 ret = pread( fd, limit, sizeof(*limit), pos + (8192 + entry)*sizeof(int) );
193 if (ret != sizeof(*limit)) goto error;
194 ret = pread( fd, flags, sizeof(*flags), pos + 2*8192*sizeof(int) + entry );
195 if (ret != sizeof(*flags)) goto error;
196 close( fd );
197 return;
198
199error:
200 if (ret == -1) file_set_error();
201 else set_error( STATUS_ACCESS_VIOLATION );
202 close( fd );
203}
204
205/* retrieve the thread registers */
Alexandre Julliard5316dd02009-04-08 19:38:02 +0200206void get_thread_context( struct thread *thread, context_t *context, unsigned int flags )
Alexandre Julliardf2792522007-03-09 13:40:41 +0100207{
Alexandre Julliardf2792522007-03-09 13:40:41 +0100208 /* FIXME: get debug registers */
209}
210
211/* set the thread registers */
Alexandre Julliard5316dd02009-04-08 19:38:02 +0200212void set_thread_context( struct thread *thread, const context_t *context, unsigned int flags )
Alexandre Julliardf2792522007-03-09 13:40:41 +0100213{
Alexandre Julliardf2792522007-03-09 13:40:41 +0100214 /* FIXME: set debug registers */
215}
216
217#endif /* USE_PROCFS */