xref: /netbsd-src/external/gpl3/gdb/dist/sim/common/syscall.c (revision 0e2e28bced52bda3788c857106bde6c44d2df3b8)
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 #ifdef HAVE_UNISTD_H
37 #include <unistd.h>
38 #endif
39 #include <sys/stat.h>
40 #include <sys/types.h>
41 
42 #include "ansidecl.h"
43 #include "libiberty.h"
44 
45 #include "sim/callback.h"
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 
66 /* Path to be prepended to syscalls with absolute paths, and to be
67    chdir:ed at startup, if not empty.  */
68 char *simulator_sysroot = "";
69 
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 
73 int
74 cb_get_string (host_callback *cb, CB_SYSCALL *sc, char *buf, int buflen,
75 	       TADDR addr)
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);
86 
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.
99    The result is that of get_string, but prepended with
100    simulator_sysroot if the string starts with '/'.
101    If an error occurs, no buffer is left malloc'd.  */
102 
103 static int
104 get_path (host_callback *cb, CB_SYSCALL *sc, TADDR addr, char **bufp)
105 {
106   char *buf = xmalloc (MAX_PATH_LEN);
107   int result;
108   int sysroot_len = strlen (simulator_sysroot);
109 
110   result = cb_get_string (cb, sc, buf, MAX_PATH_LEN - sysroot_len, addr);
111   if (result == 0)
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     }
129   else
130     free (buf);
131   return result;
132 }
133 
134 /* Perform a system call on behalf of the target.  */
135 
136 CB_RC
137 cb_syscall (host_callback *cb, CB_SYSCALL *sc)
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     {
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 
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.  */
191 	int argc, envc, arglen, envlen;
192 	char **argv = cb->argv;
193 	char **envp = cb->envp;
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 	  }
207 	result = arglen + 1 + envlen + 1;
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;
217 	int written = 0;
218 	/* Q is the target address of where all the strings go.  */
219 	TADDR q;
220 	int i, argc, envc, len, ret;
221 	char **argv = cb->argv;
222 	char **envp = cb->envp;
223 
224 	result = -1;
225 
226 	argc = 0;
227 	if (argv)
228 	  {
229 	    for ( ; argv[argc]; ++argc)
230 	      {
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;
241 	      }
242 	  }
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 
250 	envc = 0;
251 	if (envp)
252 	  {
253 	    for ( ; envp[envc]; ++envc)
254 	      {
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;
264 	      }
265 	  }
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 
272 	result = argc;
273 	sc->result2 = envc;
274 	break;
275 
276  efault:
277 	errcode = EFAULT;
278 	goto FinishSyscall;
279 
280  einval:
281 	errcode = EINVAL;
282 	goto FinishSyscall;
283       }
284 
285     case CB_SYS_exit :
286       /* Caller must catch and handle; see sim_syscall as an example.  */
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 	  {
327 	    if (cb_is_stdin (cb, fd))
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 	      }
380 	    if (cb_is_stdout (cb, fd))
381 	      {
382 		result = (int) (*cb->write_stdout) (cb, buf, bytes_read);
383 		(*cb->flush_stdout) (cb);
384 	      }
385 	    else if (cb_is_stderr (cb, fd))
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 
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 
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 
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 	  }
501 	result = (*cb->to_stat) (cb, path, &statbuf);
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 
534 	result = (*cb->to_fstat) (cb, sc->arg1, &statbuf);
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 
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 	  }
572 	result = (*cb->to_lstat) (cb, path, &statbuf);
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 
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 
630     case CB_SYS_getpid:
631       /* POSIX says getpid always succeeds.  */
632       result = (*cb->getpid) (cb);
633       break;
634 
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 
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.  */
659 	time_t t = (*cb->time) (cb);
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 }
689