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