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.  */
68char *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
73int
74cb_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
103static int
104get_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
136CB_RC
137cb_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