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