Update copyright year range in all GDB files.
[deliverable/binutils-gdb.git] / sim / common / syscall.c
CommitLineData
c906108c 1/* Remote target system call support.
b811d2c2 2 Copyright 1997-2020 Free Software Foundation, Inc.
c906108c
SS
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
4744ac1b 9 the Free Software Foundation; either version 3 of the License, or
c906108c
SS
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
4744ac1b 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
c906108c
SS
19
20/* This interface isn't intended to be specific to any particular kind
21 of remote (hardware, simulator, whatever). As such, support for it
22 (e.g. sim/common/callback.c) should *not* live in the simulator source
23 tree, nor should it live in the gdb source tree. K&R C must be
24 supported. */
25
26#ifdef HAVE_CONFIG_H
936df756 27#include "config.h"
c906108c
SS
28#endif
29#include "ansidecl.h"
30#include "libiberty.h"
c906108c 31#include <stdarg.h>
c906108c
SS
32#include <stdio.h>
33#ifdef HAVE_STDLIB_H
34#include <stdlib.h>
35#endif
027e2a04
HPN
36#ifdef HAVE_STRING_H
37#include <string.h>
38#elif defined (HAVE_STRINGS_H)
39#include <strings.h>
40#endif
c906108c
SS
41#ifdef HAVE_UNISTD_H
42#include <unistd.h>
43#endif
44#include <errno.h>
45#include <fcntl.h>
46#include <time.h>
47#include <sys/types.h>
48#include <sys/stat.h>
3c25f8c7 49#include "gdb/callback.h"
c906108c
SS
50#include "targ-vals.h"
51
52#ifndef ENOSYS
53#define ENOSYS EINVAL
54#endif
55#ifndef ENAMETOOLONG
56#define ENAMETOOLONG EINVAL
57#endif
58
59/* Maximum length of a path name. */
60#ifndef MAX_PATH_LEN
61#define MAX_PATH_LEN 1024
62#endif
63
64/* When doing file read/writes, do this many bytes at a time. */
65#define FILE_XFR_SIZE 4096
66
67/* FIXME: for now, need to consider target word size. */
68#define TWORD long
69#define TADDR unsigned long
70
027e2a04
HPN
71/* Path to be prepended to syscalls with absolute paths, and to be
72 chdir:ed at startup, if not empty. */
73char *simulator_sysroot = "";
74
c906108c
SS
75/* Utility of cb_syscall to fetch a path name or other string from the target.
76 The result is 0 for success or a host errno value. */
77
71712327 78int
1a8a700e
MF
79cb_get_string (host_callback *cb, CB_SYSCALL *sc, char *buf, int buflen,
80 TADDR addr)
c906108c
SS
81{
82 char *p, *pend;
83
84 for (p = buf, pend = buf + buflen; p < pend; ++p, ++addr)
85 {
86 /* No, it isn't expected that this would cause one transaction with
87 the remote target for each byte. The target could send the
88 path name along with the syscall request, and cache the file
89 name somewhere (or otherwise tweak this as desired). */
90 unsigned int count = (*sc->read_mem) (cb, sc, addr, p, 1);
028f6515 91
c906108c
SS
92 if (count != 1)
93 return EINVAL;
94 if (*p == 0)
95 break;
96 }
97 if (p == pend)
98 return ENAMETOOLONG;
99 return 0;
100}
101
102/* Utility of cb_syscall to fetch a path name.
103 The buffer is malloc'd and the address is stored in BUFP.
027e2a04
HPN
104 The result is that of get_string, but prepended with
105 simulator_sysroot if the string starts with '/'.
c906108c
SS
106 If an error occurs, no buffer is left malloc'd. */
107
108static int
1a8a700e 109get_path (host_callback *cb, CB_SYSCALL *sc, TADDR addr, char **bufp)
c906108c
SS
110{
111 char *buf = xmalloc (MAX_PATH_LEN);
112 int result;
027e2a04 113 int sysroot_len = strlen (simulator_sysroot);
c906108c 114
71712327 115 result = cb_get_string (cb, sc, buf, MAX_PATH_LEN - sysroot_len, addr);
c906108c 116 if (result == 0)
027e2a04
HPN
117 {
118 /* Prepend absolute paths with simulator_sysroot. Relative paths
119 are supposed to be relative to a chdir within that path, but at
120 this point unknown where. */
121 if (simulator_sysroot[0] != '\0' && *buf == '/')
122 {
123 /* Considering expected rareness of syscalls with absolute
124 file paths (compared to relative file paths and insn
125 execution), it does not seem worthwhile to rearrange things
126 to get rid of the string moves here; we'd need at least an
127 extra call to check the initial '/' in the path. */
128 memmove (buf + sysroot_len, buf, sysroot_len);
129 memcpy (buf, simulator_sysroot, sysroot_len);
130 }
131
132 *bufp = buf;
133 }
c906108c
SS
134 else
135 free (buf);
136 return result;
137}
138
139/* Perform a system call on behalf of the target. */
140
141CB_RC
1a8a700e 142cb_syscall (host_callback *cb, CB_SYSCALL *sc)
c906108c
SS
143{
144 TWORD result = 0, errcode = 0;
145
146 if (sc->magic != CB_SYSCALL_MAGIC)
147 abort ();
148
149 switch (cb_target_to_host_syscall (cb, sc->func))
150 {
151#if 0 /* FIXME: wip */
152 case CB_SYS_argvlen :
153 {
154 /* Compute how much space is required to store the argv,envp
155 strings so that the program can allocate the space and then
156 call SYS_argv to fetch the values. */
157 int addr_size = cb->addr_size;
158 int argc,envc,arglen,envlen;
159 const char **argv = cb->init_argv;
160 const char **envp = cb->init_envp;
161
162 argc = arglen = 0;
163 if (argv)
164 {
165 for ( ; argv[argc]; ++argc)
166 arglen += strlen (argv[argc]) + 1;
167 }
168 envc = envlen = 0;
169 if (envp)
170 {
171 for ( ; envp[envc]; ++envc)
172 envlen += strlen (envp[envc]) + 1;
173 }
174 result = arglen + envlen;
175 break;
176 }
177
178 case CB_SYS_argv :
179 {
180 /* Pointer to target's buffer. */
181 TADDR tbuf = sc->arg1;
182 /* Buffer size. */
183 int bufsize = sc->arg2;
184 /* Q is the target address of where all the strings go. */
185 TADDR q;
186 int word_size = cb->word_size;
187 int i,argc,envc,len;
188 const char **argv = cb->init_argv;
189 const char **envp = cb->init_envp;
190
191 argc = 0;
192 if (argv)
193 {
194 for ( ; argv[argc]; ++argc)
195 {
196 int len = strlen (argv[argc]);
197 int written = (*sc->write_mem) (cb, sc, tbuf, argv[argc], len + 1);
198 if (written != len)
199 {
200 result = -1;
201 errcode = EINVAL;
202 goto FinishSyscall;
203 }
204 tbuf = len + 1;
205 }
206 }
207 if ((*sc->write_mem) (cb, sc, tbuf, "", 1) != 1)
208 {
209 result = -1;
210 errcode = EINVAL;
211 goto FinishSyscall;
212 }
213 tbuf++;
214 envc = 0;
215 if (envp)
216 {
217 for ( ; envp[envc]; ++envc)
218 {
219 int len = strlen (envp[envc]);
220 int written = (*sc->write_mem) (cb, sc, tbuf, envp[envc], len + 1);
221 if (written != len)
222 {
223 result = -1;
224 errcode = EINVAL;
225 goto FinishSyscall;
226 }
227 tbuf = len + 1;
228 }
229 }
230 if ((*sc->write_mem) (cb, sc, tbuf, "", 1) != 1)
231 {
232 result = -1;
233 errcode = EINVAL;
234 goto FinishSyscall;
235 }
236 result = argc;
237 sc->result2 = envc;
238 break;
239 }
240#endif /* wip */
241
242 case CB_SYS_exit :
7d5c6c43 243 /* Caller must catch and handle; see sim_syscall as an example. */
c906108c
SS
244 break;
245
246 case CB_SYS_open :
247 {
248 char *path;
249
250 errcode = get_path (cb, sc, sc->arg1, &path);
251 if (errcode != 0)
252 {
253 result = -1;
254 goto FinishSyscall;
255 }
256 result = (*cb->open) (cb, path, sc->arg2 /*, sc->arg3*/);
257 free (path);
258 if (result < 0)
259 goto ErrorFinish;
260 }
261 break;
262
263 case CB_SYS_close :
264 result = (*cb->close) (cb, sc->arg1);
265 if (result < 0)
266 goto ErrorFinish;
267 break;
268
269 case CB_SYS_read :
270 {
271 /* ??? Perfect handling of error conditions may require only one
272 call to cb->read. One can't assume all the data is
273 contiguously stored in host memory so that would require
274 malloc'ing/free'ing the space. Maybe later. */
275 char buf[FILE_XFR_SIZE];
276 int fd = sc->arg1;
277 TADDR addr = sc->arg2;
278 size_t count = sc->arg3;
279 size_t bytes_read = 0;
280 int bytes_written;
281
282 while (count > 0)
283 {
b981d709 284 if (cb_is_stdin (cb, fd))
c906108c
SS
285 result = (int) (*cb->read_stdin) (cb, buf,
286 (count < FILE_XFR_SIZE
287 ? count : FILE_XFR_SIZE));
288 else
289 result = (int) (*cb->read) (cb, fd, buf,
290 (count < FILE_XFR_SIZE
291 ? count : FILE_XFR_SIZE));
292 if (result == -1)
293 goto ErrorFinish;
294 if (result == 0) /* EOF */
295 break;
296 bytes_written = (*sc->write_mem) (cb, sc, addr, buf, result);
297 if (bytes_written != result)
298 {
299 result = -1;
300 errcode = EINVAL;
301 goto FinishSyscall;
302 }
303 bytes_read += result;
304 count -= result;
305 addr += result;
306 /* If this is a short read, don't go back for more */
307 if (result != FILE_XFR_SIZE)
308 break;
309 }
310 result = bytes_read;
311 }
312 break;
313
314 case CB_SYS_write :
315 {
316 /* ??? Perfect handling of error conditions may require only one
317 call to cb->write. One can't assume all the data is
318 contiguously stored in host memory so that would require
319 malloc'ing/free'ing the space. Maybe later. */
320 char buf[FILE_XFR_SIZE];
321 int fd = sc->arg1;
322 TADDR addr = sc->arg2;
323 size_t count = sc->arg3;
324 int bytes_read;
325 size_t bytes_written = 0;
326
327 while (count > 0)
328 {
329 int bytes_to_read = count < FILE_XFR_SIZE ? count : FILE_XFR_SIZE;
330 bytes_read = (*sc->read_mem) (cb, sc, addr, buf, bytes_to_read);
331 if (bytes_read != bytes_to_read)
332 {
333 result = -1;
334 errcode = EINVAL;
335 goto FinishSyscall;
336 }
34b47c38 337 if (cb_is_stdout (cb, fd))
c906108c
SS
338 {
339 result = (int) (*cb->write_stdout) (cb, buf, bytes_read);
340 (*cb->flush_stdout) (cb);
341 }
34b47c38 342 else if (cb_is_stderr (cb, fd))
c906108c
SS
343 {
344 result = (int) (*cb->write_stderr) (cb, buf, bytes_read);
345 (*cb->flush_stderr) (cb);
346 }
347 else
348 result = (int) (*cb->write) (cb, fd, buf, bytes_read);
349 if (result == -1)
350 goto ErrorFinish;
351 bytes_written += result;
352 count -= result;
353 addr += result;
354 }
355 result = bytes_written;
356 }
357 break;
358
359 case CB_SYS_lseek :
360 {
361 int fd = sc->arg1;
362 unsigned long offset = sc->arg2;
363 int whence = sc->arg3;
364
365 result = (*cb->lseek) (cb, fd, offset, whence);
366 if (result < 0)
367 goto ErrorFinish;
368 }
369 break;
370
371 case CB_SYS_unlink :
372 {
373 char *path;
374
375 errcode = get_path (cb, sc, sc->arg1, &path);
376 if (errcode != 0)
377 {
378 result = -1;
379 goto FinishSyscall;
380 }
381 result = (*cb->unlink) (cb, path);
382 free (path);
383 if (result < 0)
384 goto ErrorFinish;
385 }
386 break;
387
5d945fec
HPN
388 case CB_SYS_truncate :
389 {
390 char *path;
391 long len = sc->arg2;
392
393 errcode = get_path (cb, sc, sc->arg1, &path);
394 if (errcode != 0)
395 {
396 result = -1;
397 errcode = EFAULT;
398 goto FinishSyscall;
399 }
400 result = (*cb->truncate) (cb, path, len);
401 free (path);
402 if (result < 0)
403 goto ErrorFinish;
404 }
405 break;
406
407 case CB_SYS_ftruncate :
408 {
409 int fd = sc->arg1;
410 long len = sc->arg2;
411
412 result = (*cb->ftruncate) (cb, fd, len);
413 if (result < 0)
414 goto ErrorFinish;
415 }
416 break;
417
82571856
HPN
418 case CB_SYS_rename :
419 {
420 char *path1, *path2;
421
422 errcode = get_path (cb, sc, sc->arg1, &path1);
423 if (errcode != 0)
424 {
425 result = -1;
426 errcode = EFAULT;
427 goto FinishSyscall;
428 }
429 errcode = get_path (cb, sc, sc->arg2, &path2);
430 if (errcode != 0)
431 {
432 result = -1;
433 errcode = EFAULT;
434 free (path1);
435 goto FinishSyscall;
436 }
437 result = (*cb->rename) (cb, path1, path2);
438 free (path1);
439 free (path2);
440 if (result < 0)
441 goto ErrorFinish;
442 }
443 break;
444
c906108c
SS
445 case CB_SYS_stat :
446 {
447 char *path,*buf;
448 int buflen;
449 struct stat statbuf;
450 TADDR addr = sc->arg2;
451
452 errcode = get_path (cb, sc, sc->arg1, &path);
453 if (errcode != 0)
454 {
455 result = -1;
456 goto FinishSyscall;
457 }
2d7bb758 458 result = (*cb->to_stat) (cb, path, &statbuf);
c906108c
SS
459 free (path);
460 if (result < 0)
461 goto ErrorFinish;
462 buflen = cb_host_to_target_stat (cb, NULL, NULL);
463 buf = xmalloc (buflen);
464 if (cb_host_to_target_stat (cb, &statbuf, buf) != buflen)
465 {
466 /* The translation failed. This is due to an internal
467 host program error, not the target's fault. */
468 free (buf);
469 errcode = ENOSYS;
470 result = -1;
471 goto FinishSyscall;
472 }
473 if ((*sc->write_mem) (cb, sc, addr, buf, buflen) != buflen)
474 {
475 free (buf);
476 errcode = EINVAL;
477 result = -1;
478 goto FinishSyscall;
479 }
480 free (buf);
481 }
482 break;
483
484 case CB_SYS_fstat :
485 {
486 char *buf;
487 int buflen;
488 struct stat statbuf;
489 TADDR addr = sc->arg2;
490
2d7bb758 491 result = (*cb->to_fstat) (cb, sc->arg1, &statbuf);
c906108c
SS
492 if (result < 0)
493 goto ErrorFinish;
494 buflen = cb_host_to_target_stat (cb, NULL, NULL);
495 buf = xmalloc (buflen);
496 if (cb_host_to_target_stat (cb, &statbuf, buf) != buflen)
497 {
498 /* The translation failed. This is due to an internal
499 host program error, not the target's fault. */
500 free (buf);
501 errcode = ENOSYS;
502 result = -1;
503 goto FinishSyscall;
504 }
505 if ((*sc->write_mem) (cb, sc, addr, buf, buflen) != buflen)
506 {
507 free (buf);
508 errcode = EINVAL;
509 result = -1;
510 goto FinishSyscall;
511 }
512 free (buf);
513 }
514 break;
515
0d3cd463
HPN
516 case CB_SYS_lstat :
517 {
518 char *path, *buf;
519 int buflen;
520 struct stat statbuf;
521 TADDR addr = sc->arg2;
522
523 errcode = get_path (cb, sc, sc->arg1, &path);
524 if (errcode != 0)
525 {
526 result = -1;
527 goto FinishSyscall;
528 }
2d7bb758 529 result = (*cb->to_lstat) (cb, path, &statbuf);
0d3cd463
HPN
530 free (path);
531 if (result < 0)
532 goto ErrorFinish;
533
534 buflen = cb_host_to_target_stat (cb, NULL, NULL);
535 buf = xmalloc (buflen);
536 if (cb_host_to_target_stat (cb, &statbuf, buf) != buflen)
537 {
538 /* The translation failed. This is due to an internal
539 host program error, not the target's fault.
540 Unfortunately, it's hard to test this case, so there's no
541 test-case for this execution path. */
542 free (buf);
543 errcode = ENOSYS;
544 result = -1;
545 goto FinishSyscall;
546 }
547
548 if ((*sc->write_mem) (cb, sc, addr, buf, buflen) != buflen)
549 {
550 free (buf);
551 errcode = EINVAL;
552 result = -1;
553 goto FinishSyscall;
554 }
555
556 free (buf);
557 }
558 break;
559
97f669ed
HPN
560 case CB_SYS_pipe :
561 {
562 int p[2];
563 char *target_p = xcalloc (1, cb->target_sizeof_int * 2);
564
565 result = (*cb->pipe) (cb, p);
566 if (result != 0)
567 goto ErrorFinish;
568
569 cb_store_target_endian (cb, target_p, cb->target_sizeof_int, p[0]);
570 cb_store_target_endian (cb, target_p + cb->target_sizeof_int,
571 cb->target_sizeof_int, p[1]);
572 if ((*sc->write_mem) (cb, sc, sc->arg1, target_p,
573 cb->target_sizeof_int * 2)
574 != cb->target_sizeof_int * 2)
575 {
576 /* Close the pipe fd:s. */
577 (*cb->close) (cb, p[0]);
578 (*cb->close) (cb, p[1]);
579 errcode = EFAULT;
580 result = -1;
581 }
582
583 free (target_p);
584 }
585 break;
586
c906108c
SS
587 case CB_SYS_time :
588 {
589 /* FIXME: May wish to change CB_SYS_time to something else.
590 We might also want gettimeofday or times, but if system calls
591 can be built on others, we can keep the number we have to support
592 here down. */
593 time_t t = (*cb->time) (cb, (time_t *) 0);
594 result = t;
595 /* It is up to target code to process the argument to time(). */
596 }
597 break;
598
599 case CB_SYS_chdir :
600 case CB_SYS_chmod :
601 case CB_SYS_utime :
602 /* fall through for now */
603
604 default :
605 result = -1;
606 errcode = ENOSYS;
607 break;
608 }
609
610 FinishSyscall:
611 sc->result = result;
612 if (errcode == 0)
613 sc->errcode = 0;
614 else
615 sc->errcode = cb_host_to_target_errno (cb, errcode);
616 return CB_RC_OK;
617
618 ErrorFinish:
619 sc->result = result;
620 sc->errcode = (*cb->get_errno) (cb);
621 return CB_RC_OK;
622}
This page took 0.915117 seconds and 4 git commands to generate.