[binutils, ARM, 5/16] BF insns infrastructure with new global reloc R_ARM_THM_BF16
[binutils-gdb.git] / sim / common / syscall.c
blobd9fc5fd26dbe924075c5c4973ab09349d0be73d1
1 /* Remote target system call support.
2 Copyright 1997-2019 Free Software Foundation, Inc.
3 Contributed by Cygnus Solutions.
5 This file is part of GDB.
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.
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.
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/>. */
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. */
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29 #include "ansidecl.h"
30 #include "libiberty.h"
31 #include <stdarg.h>
32 #include <stdio.h>
33 #ifdef HAVE_STDLIB_H
34 #include <stdlib.h>
35 #endif
36 #ifdef HAVE_STRING_H
37 #include <string.h>
38 #elif defined (HAVE_STRINGS_H)
39 #include <strings.h>
40 #endif
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>
49 #include "gdb/callback.h"
50 #include "targ-vals.h"
52 #ifndef ENOSYS
53 #define ENOSYS EINVAL
54 #endif
55 #ifndef ENAMETOOLONG
56 #define ENAMETOOLONG EINVAL
57 #endif
59 /* Maximum length of a path name. */
60 #ifndef MAX_PATH_LEN
61 #define MAX_PATH_LEN 1024
62 #endif
64 /* When doing file read/writes, do this many bytes at a time. */
65 #define FILE_XFR_SIZE 4096
67 /* FIXME: for now, need to consider target word size. */
68 #define TWORD long
69 #define TADDR unsigned long
71 /* Path to be prepended to syscalls with absolute paths, and to be
72 chdir:ed at startup, if not empty. */
73 char *simulator_sysroot = "";
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. */
78 int
79 cb_get_string (host_callback *cb, CB_SYSCALL *sc, char *buf, int buflen,
80 TADDR addr)
82 char *p, *pend;
84 for (p = buf, pend = buf + buflen; p < pend; ++p, ++addr)
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);
92 if (count != 1)
93 return EINVAL;
94 if (*p == 0)
95 break;
97 if (p == pend)
98 return ENAMETOOLONG;
99 return 0;
102 /* Utility of cb_syscall to fetch a path name.
103 The buffer is malloc'd and the address is stored in BUFP.
104 The result is that of get_string, but prepended with
105 simulator_sysroot if the string starts with '/'.
106 If an error occurs, no buffer is left malloc'd. */
108 static int
109 get_path (host_callback *cb, CB_SYSCALL *sc, TADDR addr, char **bufp)
111 char *buf = xmalloc (MAX_PATH_LEN);
112 int result;
113 int sysroot_len = strlen (simulator_sysroot);
115 result = cb_get_string (cb, sc, buf, MAX_PATH_LEN - sysroot_len, addr);
116 if (result == 0)
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 == '/')
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);
132 *bufp = buf;
134 else
135 free (buf);
136 return result;
139 /* Perform a system call on behalf of the target. */
141 CB_RC
142 cb_syscall (host_callback *cb, CB_SYSCALL *sc)
144 TWORD result = 0, errcode = 0;
146 if (sc->magic != CB_SYSCALL_MAGIC)
147 abort ();
149 switch (cb_target_to_host_syscall (cb, sc->func))
151 #if 0 /* FIXME: wip */
152 case CB_SYS_argvlen :
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;
162 argc = arglen = 0;
163 if (argv)
165 for ( ; argv[argc]; ++argc)
166 arglen += strlen (argv[argc]) + 1;
168 envc = envlen = 0;
169 if (envp)
171 for ( ; envp[envc]; ++envc)
172 envlen += strlen (envp[envc]) + 1;
174 result = arglen + envlen;
175 break;
178 case CB_SYS_argv :
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;
191 argc = 0;
192 if (argv)
194 for ( ; argv[argc]; ++argc)
196 int len = strlen (argv[argc]);
197 int written = (*sc->write_mem) (cb, sc, tbuf, argv[argc], len + 1);
198 if (written != len)
200 result = -1;
201 errcode = EINVAL;
202 goto FinishSyscall;
204 tbuf = len + 1;
207 if ((*sc->write_mem) (cb, sc, tbuf, "", 1) != 1)
209 result = -1;
210 errcode = EINVAL;
211 goto FinishSyscall;
213 tbuf++;
214 envc = 0;
215 if (envp)
217 for ( ; envp[envc]; ++envc)
219 int len = strlen (envp[envc]);
220 int written = (*sc->write_mem) (cb, sc, tbuf, envp[envc], len + 1);
221 if (written != len)
223 result = -1;
224 errcode = EINVAL;
225 goto FinishSyscall;
227 tbuf = len + 1;
230 if ((*sc->write_mem) (cb, sc, tbuf, "", 1) != 1)
232 result = -1;
233 errcode = EINVAL;
234 goto FinishSyscall;
236 result = argc;
237 sc->result2 = envc;
238 break;
240 #endif /* wip */
242 case CB_SYS_exit :
243 /* Caller must catch and handle; see sim_syscall as an example. */
244 break;
246 case CB_SYS_open :
248 char *path;
250 errcode = get_path (cb, sc, sc->arg1, &path);
251 if (errcode != 0)
253 result = -1;
254 goto FinishSyscall;
256 result = (*cb->open) (cb, path, sc->arg2 /*, sc->arg3*/);
257 free (path);
258 if (result < 0)
259 goto ErrorFinish;
261 break;
263 case CB_SYS_close :
264 result = (*cb->close) (cb, sc->arg1);
265 if (result < 0)
266 goto ErrorFinish;
267 break;
269 case CB_SYS_read :
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;
282 while (count > 0)
284 if (cb_is_stdin (cb, fd))
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)
299 result = -1;
300 errcode = EINVAL;
301 goto FinishSyscall;
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;
310 result = bytes_read;
312 break;
314 case CB_SYS_write :
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;
327 while (count > 0)
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)
333 result = -1;
334 errcode = EINVAL;
335 goto FinishSyscall;
337 if (cb_is_stdout (cb, fd))
339 result = (int) (*cb->write_stdout) (cb, buf, bytes_read);
340 (*cb->flush_stdout) (cb);
342 else if (cb_is_stderr (cb, fd))
344 result = (int) (*cb->write_stderr) (cb, buf, bytes_read);
345 (*cb->flush_stderr) (cb);
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;
355 result = bytes_written;
357 break;
359 case CB_SYS_lseek :
361 int fd = sc->arg1;
362 unsigned long offset = sc->arg2;
363 int whence = sc->arg3;
365 result = (*cb->lseek) (cb, fd, offset, whence);
366 if (result < 0)
367 goto ErrorFinish;
369 break;
371 case CB_SYS_unlink :
373 char *path;
375 errcode = get_path (cb, sc, sc->arg1, &path);
376 if (errcode != 0)
378 result = -1;
379 goto FinishSyscall;
381 result = (*cb->unlink) (cb, path);
382 free (path);
383 if (result < 0)
384 goto ErrorFinish;
386 break;
388 case CB_SYS_truncate :
390 char *path;
391 long len = sc->arg2;
393 errcode = get_path (cb, sc, sc->arg1, &path);
394 if (errcode != 0)
396 result = -1;
397 errcode = EFAULT;
398 goto FinishSyscall;
400 result = (*cb->truncate) (cb, path, len);
401 free (path);
402 if (result < 0)
403 goto ErrorFinish;
405 break;
407 case CB_SYS_ftruncate :
409 int fd = sc->arg1;
410 long len = sc->arg2;
412 result = (*cb->ftruncate) (cb, fd, len);
413 if (result < 0)
414 goto ErrorFinish;
416 break;
418 case CB_SYS_rename :
420 char *path1, *path2;
422 errcode = get_path (cb, sc, sc->arg1, &path1);
423 if (errcode != 0)
425 result = -1;
426 errcode = EFAULT;
427 goto FinishSyscall;
429 errcode = get_path (cb, sc, sc->arg2, &path2);
430 if (errcode != 0)
432 result = -1;
433 errcode = EFAULT;
434 free (path1);
435 goto FinishSyscall;
437 result = (*cb->rename) (cb, path1, path2);
438 free (path1);
439 free (path2);
440 if (result < 0)
441 goto ErrorFinish;
443 break;
445 case CB_SYS_stat :
447 char *path,*buf;
448 int buflen;
449 struct stat statbuf;
450 TADDR addr = sc->arg2;
452 errcode = get_path (cb, sc, sc->arg1, &path);
453 if (errcode != 0)
455 result = -1;
456 goto FinishSyscall;
458 result = (*cb->to_stat) (cb, path, &statbuf);
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)
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;
473 if ((*sc->write_mem) (cb, sc, addr, buf, buflen) != buflen)
475 free (buf);
476 errcode = EINVAL;
477 result = -1;
478 goto FinishSyscall;
480 free (buf);
482 break;
484 case CB_SYS_fstat :
486 char *buf;
487 int buflen;
488 struct stat statbuf;
489 TADDR addr = sc->arg2;
491 result = (*cb->to_fstat) (cb, sc->arg1, &statbuf);
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)
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;
505 if ((*sc->write_mem) (cb, sc, addr, buf, buflen) != buflen)
507 free (buf);
508 errcode = EINVAL;
509 result = -1;
510 goto FinishSyscall;
512 free (buf);
514 break;
516 case CB_SYS_lstat :
518 char *path, *buf;
519 int buflen;
520 struct stat statbuf;
521 TADDR addr = sc->arg2;
523 errcode = get_path (cb, sc, sc->arg1, &path);
524 if (errcode != 0)
526 result = -1;
527 goto FinishSyscall;
529 result = (*cb->to_lstat) (cb, path, &statbuf);
530 free (path);
531 if (result < 0)
532 goto ErrorFinish;
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)
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;
548 if ((*sc->write_mem) (cb, sc, addr, buf, buflen) != buflen)
550 free (buf);
551 errcode = EINVAL;
552 result = -1;
553 goto FinishSyscall;
556 free (buf);
558 break;
560 case CB_SYS_pipe :
562 int p[2];
563 char *target_p = xcalloc (1, cb->target_sizeof_int * 2);
565 result = (*cb->pipe) (cb, p);
566 if (result != 0)
567 goto ErrorFinish;
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)
576 /* Close the pipe fd:s. */
577 (*cb->close) (cb, p[0]);
578 (*cb->close) (cb, p[1]);
579 errcode = EFAULT;
580 result = -1;
583 free (target_p);
585 break;
587 case CB_SYS_time :
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(). */
597 break;
599 case CB_SYS_chdir :
600 case CB_SYS_chmod :
601 case CB_SYS_utime :
602 /* fall through for now */
604 default :
605 result = -1;
606 errcode = ENOSYS;
607 break;
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;
618 ErrorFinish:
619 sc->result = result;
620 sc->errcode = (*cb->get_errno) (cb);
621 return CB_RC_OK;