* Make-common.in (DEP, COMMON_DEP_CFLAGS): Define.
[deliverable/binutils-gdb.git] / sim / common / syscall.c
1 /* Remote target system call support.
2 Copyright 1997 Free Software Foundation, Inc.
3 Contributed by Cygnus Solutions.
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GAS; see the file COPYING. If not, write to the Free Software
19 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20
21 /* This interface isn't intended to be specific to any particular kind
22 of remote (hardware, simulator, whatever). As such, support for it
23 (e.g. sim/common/callback.c) should *not* live in the simulator source
24 tree, nor should it live in the gdb source tree. K&R C must be
25 supported. */
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30 #include "ansidecl.h"
31 #ifdef ANSI_PROTOTYPES
32 #include <stdarg.h>
33 #else
34 #include <varargs.h>
35 #endif
36 #include <stdio.h>
37 #ifdef HAVE_STDLIB_H
38 #include <stdlib.h>
39 #endif
40 #include <errno.h>
41 #include <fcntl.h>
42 #include <time.h>
43 #include "callback.h"
44 #include "remote-sim.h"
45 #include "targ-vals.h"
46
47 #ifdef HAVE_UNISTD_H
48 #include <unistd.h>
49 #endif
50
51 /* When doing file read/writes, do this many bytes at a time. */
52 #define FILE_XFR_SIZE 4096
53
54 /* Maximum length of a path name. */
55 #ifndef MAX_PATH_LEN
56 #define MAX_PATH_LEN 1024
57 #endif
58
59 /* Utility of cb_syscall to fetch a path name from the target.
60 The result is 0 for success or a target errno value. */
61
62 static int
63 get_path (cb, sc, buf, buflen, addr)
64 host_callback *cb;
65 CB_SYSCALL *sc;
66 char *buf;
67 int buflen;
68 long addr;
69 {
70 char *p, *pend;
71
72 for (p = buf, pend = buf + buflen; p < pend; ++p, ++addr)
73 {
74 /* No, it isn't expected that this would cause one transaction with
75 the remote target for each byte. The target could send the
76 path name along with the syscall request, and cache the file
77 name somewhere. */
78 unsigned int count = (*sc->read_mem) (cb, sc, addr, p, 1);
79
80 if (count != 1)
81 return TARGET_EINVAL;
82 if (*p == 0)
83 break;
84 }
85 if (p == pend)
86 return TARGET_ENAMETOOLONG;
87 return 0;
88 }
89
90 /* Perform a system call on behalf of the target. */
91
92 CB_RC
93 cb_syscall (cb, sc)
94 host_callback *cb;
95 CB_SYSCALL *sc;
96 {
97 /* ??? Need to consider target word size. */
98 long result = 0, errcode = 0;
99
100 switch (cb_target_to_host_syscall (cb, sc->func))
101 {
102 #if 0 /* FIXME: wip */
103 case CB_SYS_argvlen :
104 {
105 /* Compute how much space is required to store the argv,envp
106 strings so that the program can allocate the space and then
107 call SYS_argv to fetch the values. */
108 int addr_size = cb->addr_size;
109 int argc,envc,arglen,envlen;
110 const char **argv = cb->init_argv;
111 const char **envp = cb->init_envp;
112
113 argc = arglen = 0;
114 if (argv)
115 {
116 for ( ; argv[argc]; ++argc)
117 arglen += strlen (argv[argc]) + 1;
118 }
119 envc = envlen = 0;
120 if (envp)
121 {
122 for ( ; envp[envc]; ++envc)
123 envlen += strlen (envp[envc]) + 1;
124 }
125 result = arglen + envlen;
126 break;
127 }
128
129 case CB_SYS_argv :
130 {
131 /* Pointer to target's buffer. */
132 SIM_ADDR tbuf = sc->arg1;
133 /* Buffer size. */
134 int bufsize = sc->arg2;
135 /* Q is the target address of where all the strings go. */
136 SIM_ADDR q;
137 int word_size = cb->word_size;
138 int i,argc,envc,len;
139 const char **argv = cb->init_argv;
140 const char **envp = cb->init_envp;
141
142 argc = 0;
143 if (argv)
144 {
145 for ( ; argv[argc]; ++argc)
146 {
147 int len = strlen (argv[argc]);
148 int written = (*sc->write_mem) (cb, sc, tbuf, argv[argc], len + 1);
149 if (written != len)
150 {
151 result = -1;
152 errcode = TARGET_EINVAL;
153 goto FinishSyscall;
154 }
155 tbuf = len + 1;
156 }
157 }
158 if ((*sc->write_mem) (cb, sc, tbuf, "", 1) != 1)
159 {
160 result = -1;
161 errcode = TARGET_EINVAL;
162 goto FinishSyscall;
163 }
164 tbuf++;
165 envc = 0;
166 if (envp)
167 {
168 for ( ; envp[envc]; ++envc)
169 {
170 int len = strlen (envp[envc]);
171 int written = (*sc->write_mem) (cb, sc, tbuf, envp[envc], len + 1);
172 if (written != len)
173 {
174 result = -1;
175 errcode = TARGET_EINVAL;
176 goto FinishSyscall;
177 }
178 tbuf = len + 1;
179 }
180 }
181 if ((*sc->write_mem) (cb, sc, tbuf, "", 1) != 1)
182 {
183 result = -1;
184 errcode = TARGET_EINVAL;
185 goto FinishSyscall;
186 }
187 result = argc;
188 sc->result2 = envc;
189 break;
190 }
191 #endif /* wip */
192
193 case CB_SYS_exit :
194 /* Caller must catch and handle. */
195 break;
196
197 case CB_SYS_open :
198 {
199 char path[MAX_PATH_LEN];
200 int errcode;
201
202 errcode = get_path (cb, sc, path, MAX_PATH_LEN, sc->arg1);
203 if (errcode != 0)
204 {
205 result = -1;
206 errcode = errcode;
207 goto FinishSyscall;
208 }
209 result = (*cb->open) (cb, path, sc->arg2 /*, sc->arg3*/);
210 }
211 break;
212
213 case CB_SYS_close :
214 result = (*cb->close) (cb, sc->arg1);
215 break;
216
217 case CB_SYS_read :
218 {
219 /* ??? Perfect handling of error conditions may require only one
220 call to cb->read. One can't assume all the data is
221 contiguously stored in host memory so that would require
222 malloc'ing/free'ing the space. Maybe later. */
223 char buf[FILE_XFR_SIZE];
224 int fd = sc->arg1;
225 SIM_ADDR addr = sc->arg2;
226 size_t count = sc->arg3;
227 size_t bytes_read = 0;
228 int bytes_written;
229
230 while (count > 0)
231 {
232 result = (int) (*cb->read) (cb, fd, buf,
233 count < FILE_XFR_SIZE ? count : FILE_XFR_SIZE);
234 if (result == -1)
235 goto FinishSyscall;
236 bytes_written = (*sc->write_mem) (cb, sc, addr, buf, result);
237 if (bytes_written != result)
238 {
239 result = -1;
240 errcode = TARGET_EINVAL;
241 goto FinishSyscall;
242 }
243 bytes_read += result;
244 count -= result;
245 addr += result;
246 }
247 result = bytes_read;
248 }
249 break;
250
251 case CB_SYS_write :
252 {
253 /* ??? Perfect handling of error conditions may require only one
254 call to cb->write. One can't assume all the data is
255 contiguously stored in host memory so that would require
256 malloc'ing/free'ing the space. Maybe later. */
257 char buf[FILE_XFR_SIZE];
258 int fd = sc->arg1;
259 SIM_ADDR addr = sc->arg2;
260 size_t count = sc->arg3;
261 int bytes_read;
262 size_t bytes_written = 0;
263
264 while (count > 0)
265 {
266 int bytes_to_read = count < FILE_XFR_SIZE ? count : FILE_XFR_SIZE;
267 bytes_read = (*sc->read_mem) (cb, sc, addr, buf, bytes_to_read);
268 if (bytes_read != bytes_to_read)
269 {
270 result = -1;
271 errcode = TARGET_EINVAL;
272 goto FinishSyscall;
273 }
274 if (fd == 1)
275 result = (int) (*cb->write_stdout) (cb, buf, bytes_read);
276 else
277 result = (int) (*cb->write) (cb, fd, buf, bytes_read);
278 if (result == -1)
279 goto FinishSyscall;
280 bytes_written += result;
281 count -= result;
282 addr += result;
283 }
284 result = bytes_written;
285 }
286 break;
287
288 default :
289 result = -1;
290 #ifdef TARGET_ENOSYS
291 errcode = TARGET_ENOSYS;
292 #else
293 errcode = TARGET_EINVAL;
294 #endif
295 break;
296 }
297
298 FinishSyscall:
299 sc->result = result;
300 if (errcode == 0)
301 sc->errcode = (*cb->get_errno) (cb);
302 else
303 sc->errcode = errcode;
304
305 return CB_RC_OK;
306 }
This page took 0.056016 seconds and 5 git commands to generate.