1/* Remote target system call support.
2   Copyright 1997-2020 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#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"
51
52#ifndef ENOSYS
53#define ENOSYS EINVAL
54#endif
55#ifndef ENAMETOOLONG
56#define ENAMETOOLONG EINVAL
57#endif
58
59/* Maximum length of a path name.  */
60#ifndef MAX_PATH_LEN
61#define MAX_PATH_LEN 1024
62#endif
63
64/* When doing file read/writes, do this many bytes at a time.  */
65#define FILE_XFR_SIZE 4096
66
67/* FIXME: for now, need to consider target word size.  */
68#define TWORD long
69#define TADDR unsigned long
70
71/* Path to be prepended to syscalls with absolute paths, and to be
72   chdir:ed at startup, if not empty.  */
73char *simulator_sysroot = "";
74
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.  */
77
78int
79cb_get_string (host_callback *cb, CB_SYSCALL *sc, char *buf, int buflen,
80	       TADDR addr)
81{
82  char *p, *pend;
83
84  for (p = buf, pend = buf + buflen; p < pend; ++p, ++addr)
85    {
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);
91
92      if (count != 1)
93	return EINVAL;
94      if (*p == 0)
95	break;
96    }
97  if (p == pend)
98    return ENAMETOOLONG;
99  return 0;
100}
101
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.  */
107
108static int
109get_path (host_callback *cb, CB_SYSCALL *sc, TADDR addr, char **bufp)
110{
111  char *buf = xmalloc (MAX_PATH_LEN);
112  int result;
113  int sysroot_len = strlen (simulator_sysroot);
114
115  result = cb_get_string (cb, sc, buf, MAX_PATH_LEN - sysroot_len, addr);
116  if (result == 0)
117    {
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 == '/')
122	{
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);
130	}
131
132      *bufp = buf;
133    }
134  else
135    free (buf);
136  return result;
137}
138
139/* Perform a system call on behalf of the target.  */
140
141CB_RC
142cb_syscall (host_callback *cb, CB_SYSCALL *sc)
143{
144  TWORD result = 0, errcode = 0;
145
146  if (sc->magic != CB_SYSCALL_MAGIC)
147    abort ();
148
149  switch (cb_target_to_host_syscall (cb, sc->func))
150    {
151#if 0 /* FIXME: wip */
152    case CB_SYS_argvlen :
153      {
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;
161
162	argc = arglen = 0;
163	if (argv)
164	  {
165	    for ( ; argv[argc]; ++argc)
166	      arglen += strlen (argv[argc]) + 1;
167	  }
168	envc = envlen = 0;
169	if (envp)
170	  {
171	    for ( ; envp[envc]; ++envc)
172	      envlen += strlen (envp[envc]) + 1;
173	  }
174	result = arglen + envlen;
175	break;
176      }
177
178    case CB_SYS_argv :
179      {
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;
190
191	argc = 0;
192	if (argv)
193	  {
194	    for ( ; argv[argc]; ++argc)
195	      {
196		int len = strlen (argv[argc]);
197		int written = (*sc->write_mem) (cb, sc, tbuf, argv[argc], len + 1);
198		if (written != len)
199		  {
200		    result = -1;
201		    errcode = EINVAL;
202		    goto FinishSyscall;
203		  }
204		tbuf = len + 1;
205	      }
206	  }
207	if ((*sc->write_mem) (cb, sc, tbuf, "", 1) != 1)
208	  {
209	    result = -1;
210	    errcode = EINVAL;
211	    goto FinishSyscall;
212	  }
213	tbuf++;
214	envc = 0;
215	if (envp)
216	  {
217	    for ( ; envp[envc]; ++envc)
218	      {
219		int len = strlen (envp[envc]);
220		int written = (*sc->write_mem) (cb, sc, tbuf, envp[envc], len + 1);
221		if (written != len)
222		  {
223		    result = -1;
224		    errcode = EINVAL;
225		    goto FinishSyscall;
226		  }
227		tbuf = len + 1;
228	      }
229	  }
230	if ((*sc->write_mem) (cb, sc, tbuf, "", 1) != 1)
231	  {
232	    result = -1;
233	    errcode = EINVAL;
234	    goto FinishSyscall;
235	  }
236	result = argc;
237	sc->result2 = envc;
238	break;
239      }
240#endif /* wip */
241
242    case CB_SYS_exit :
243      /* Caller must catch and handle; see sim_syscall as an example.  */
244      break;
245
246    case CB_SYS_open :
247      {
248	char *path;
249
250	errcode = get_path (cb, sc, sc->arg1, &path);
251	if (errcode != 0)
252	  {
253	    result = -1;
254	    goto FinishSyscall;
255	  }
256	result = (*cb->open) (cb, path, sc->arg2 /*, sc->arg3*/);
257	free (path);
258	if (result < 0)
259	  goto ErrorFinish;
260      }
261      break;
262
263    case CB_SYS_close :
264      result = (*cb->close) (cb, sc->arg1);
265      if (result < 0)
266	goto ErrorFinish;
267      break;
268
269    case CB_SYS_read :
270      {
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;
281
282	while (count > 0)
283	  {
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)
298	      {
299		result = -1;
300		errcode = EINVAL;
301		goto FinishSyscall;
302	      }
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;
309	  }
310	result = bytes_read;
311      }
312      break;
313
314    case CB_SYS_write :
315      {
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;
326
327	while (count > 0)
328	  {
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)
332	      {
333		result = -1;
334		errcode = EINVAL;
335		goto FinishSyscall;
336	      }
337	    if (cb_is_stdout (cb, fd))
338	      {
339		result = (int) (*cb->write_stdout) (cb, buf, bytes_read);
340		(*cb->flush_stdout) (cb);
341	      }
342	    else if (cb_is_stderr (cb, fd))
343	      {
344		result = (int) (*cb->write_stderr) (cb, buf, bytes_read);
345		(*cb->flush_stderr) (cb);
346	      }
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;
354	  }
355	result = bytes_written;
356      }
357      break;
358
359    case CB_SYS_lseek :
360      {
361	int fd = sc->arg1;
362	unsigned long offset = sc->arg2;
363	int whence = sc->arg3;
364
365	result = (*cb->lseek) (cb, fd, offset, whence);
366	if (result < 0)
367	  goto ErrorFinish;
368      }
369      break;
370
371    case CB_SYS_unlink :
372      {
373	char *path;
374
375	errcode = get_path (cb, sc, sc->arg1, &path);
376	if (errcode != 0)
377	  {
378	    result = -1;
379	    goto FinishSyscall;
380	  }
381	result = (*cb->unlink) (cb, path);
382	free (path);
383	if (result < 0)
384	  goto ErrorFinish;
385      }
386      break;
387
388    case CB_SYS_truncate :
389      {
390	char *path;
391	long len = sc->arg2;
392
393	errcode = get_path (cb, sc, sc->arg1, &path);
394	if (errcode != 0)
395	  {
396	    result = -1;
397	    errcode = EFAULT;
398	    goto FinishSyscall;
399	  }
400	result = (*cb->truncate) (cb, path, len);
401	free (path);
402	if (result < 0)
403	  goto ErrorFinish;
404      }
405      break;
406
407    case CB_SYS_ftruncate :
408      {
409	int fd = sc->arg1;
410	long len = sc->arg2;
411
412	result = (*cb->ftruncate) (cb, fd, len);
413	if (result < 0)
414	  goto ErrorFinish;
415      }
416      break;
417
418    case CB_SYS_rename :
419      {
420	char *path1, *path2;
421
422	errcode = get_path (cb, sc, sc->arg1, &path1);
423	if (errcode != 0)
424	  {
425	    result = -1;
426	    errcode = EFAULT;
427	    goto FinishSyscall;
428	  }
429	errcode = get_path (cb, sc, sc->arg2, &path2);
430	if (errcode != 0)
431	  {
432	    result = -1;
433	    errcode = EFAULT;
434	    free (path1);
435	    goto FinishSyscall;
436	  }
437	result = (*cb->rename) (cb, path1, path2);
438	free (path1);
439	free (path2);
440	if (result < 0)
441	  goto ErrorFinish;
442      }
443      break;
444
445    case CB_SYS_stat :
446      {
447	char *path,*buf;
448	int buflen;
449	struct stat statbuf;
450	TADDR addr = sc->arg2;
451
452	errcode = get_path (cb, sc, sc->arg1, &path);
453	if (errcode != 0)
454	  {
455	    result = -1;
456	    goto FinishSyscall;
457	  }
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)
465	  {
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;
472	  }
473	if ((*sc->write_mem) (cb, sc, addr, buf, buflen) != buflen)
474	  {
475	    free (buf);
476	    errcode = EINVAL;
477	    result = -1;
478	    goto FinishSyscall;
479	  }
480	free (buf);
481      }
482      break;
483
484    case CB_SYS_fstat :
485      {
486	char *buf;
487	int buflen;
488	struct stat statbuf;
489	TADDR addr = sc->arg2;
490
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)
497	  {
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;
504	  }
505	if ((*sc->write_mem) (cb, sc, addr, buf, buflen) != buflen)
506	  {
507	    free (buf);
508	    errcode = EINVAL;
509	    result = -1;
510	    goto FinishSyscall;
511	  }
512	free (buf);
513      }
514      break;
515
516    case CB_SYS_lstat :
517      {
518	char *path, *buf;
519	int buflen;
520	struct stat statbuf;
521	TADDR addr = sc->arg2;
522
523	errcode = get_path (cb, sc, sc->arg1, &path);
524	if (errcode != 0)
525	  {
526	    result = -1;
527	    goto FinishSyscall;
528	  }
529	result = (*cb->to_lstat) (cb, path, &statbuf);
530	free (path);
531	if (result < 0)
532	  goto ErrorFinish;
533
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)
537	  {
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;
546	  }
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
556	free (buf);
557      }
558      break;
559
560    case CB_SYS_pipe :
561      {
562	int p[2];
563	char *target_p = xcalloc (1, cb->target_sizeof_int * 2);
564
565	result = (*cb->pipe) (cb, p);
566	if (result != 0)
567	  goto ErrorFinish;
568
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)
575	  {
576	    /* Close the pipe fd:s.  */
577	    (*cb->close) (cb, p[0]);
578	    (*cb->close) (cb, p[1]);
579	    errcode = EFAULT;
580	    result = -1;
581	  }
582
583	free (target_p);
584      }
585      break;
586
587    case CB_SYS_time :
588      {
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().  */
596      }
597      break;
598
599    case CB_SYS_chdir :
600    case CB_SYS_chmod :
601    case CB_SYS_utime :
602      /* fall through for now */
603
604    default :
605      result = -1;
606      errcode = ENOSYS;
607      break;
608    }
609
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;
617
618 ErrorFinish:
619  sc->result = result;
620  sc->errcode = (*cb->get_errno) (cb);
621  return CB_RC_OK;
622}
623