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