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