xref: /netbsd-src/external/gpl3/gdb/dist/sim/common/syscall.c (revision ba65fde2d7fefa7d39838fa5fa855e62bd606b5e)
1 /* Remote target system call support.
2    Copyright 1997, 1998, 2002, 2004, 2007, 2008, 2009, 2010, 2011
3    Free Software Foundation, Inc.
4    Contributed by Cygnus Solutions.
5 
6    This file is part of GDB.
7 
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12 
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17 
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20 
21 /* This interface isn't intended to be specific to any particular kind
22    of remote (hardware, simulator, whatever).  As such, support for it
23    (e.g. sim/common/callback.c) should *not* live in the simulator source
24    tree, nor should it live in the gdb source tree.  K&R C must be
25    supported.  */
26 
27 #ifdef HAVE_CONFIG_H
28 #include "cconfig.h"
29 #endif
30 #include "ansidecl.h"
31 #include "libiberty.h"
32 #include <stdarg.h>
33 #include <stdio.h>
34 #ifdef HAVE_STDLIB_H
35 #include <stdlib.h>
36 #endif
37 #ifdef HAVE_STRING_H
38 #include <string.h>
39 #elif defined (HAVE_STRINGS_H)
40 #include <strings.h>
41 #endif
42 #ifdef HAVE_UNISTD_H
43 #include <unistd.h>
44 #endif
45 #include <errno.h>
46 #include <fcntl.h>
47 #include <time.h>
48 #include <sys/types.h>
49 #include <sys/stat.h>
50 #include "gdb/callback.h"
51 #include "targ-vals.h"
52 
53 #ifndef ENOSYS
54 #define ENOSYS EINVAL
55 #endif
56 #ifndef ENAMETOOLONG
57 #define ENAMETOOLONG EINVAL
58 #endif
59 
60 /* Maximum length of a path name.  */
61 #ifndef MAX_PATH_LEN
62 #define MAX_PATH_LEN 1024
63 #endif
64 
65 /* When doing file read/writes, do this many bytes at a time.  */
66 #define FILE_XFR_SIZE 4096
67 
68 /* FIXME: for now, need to consider target word size.  */
69 #define TWORD long
70 #define TADDR unsigned long
71 
72 /* Path to be prepended to syscalls with absolute paths, and to be
73    chdir:ed at startup, if not empty.  */
74 char *simulator_sysroot = "";
75 
76 /* Utility of cb_syscall to fetch a path name or other string from the target.
77    The result is 0 for success or a host errno value.  */
78 
79 static int
80 get_string (cb, sc, buf, buflen, addr)
81      host_callback *cb;
82      CB_SYSCALL *sc;
83      char *buf;
84      int buflen;
85      TADDR addr;
86 {
87   char *p, *pend;
88 
89   for (p = buf, pend = buf + buflen; p < pend; ++p, ++addr)
90     {
91       /* No, it isn't expected that this would cause one transaction with
92 	 the remote target for each byte.  The target could send the
93 	 path name along with the syscall request, and cache the file
94 	 name somewhere (or otherwise tweak this as desired).  */
95       unsigned int count = (*sc->read_mem) (cb, sc, addr, p, 1);
96 
97       if (count != 1)
98 	return EINVAL;
99       if (*p == 0)
100 	break;
101     }
102   if (p == pend)
103     return ENAMETOOLONG;
104   return 0;
105 }
106 
107 /* Utility of cb_syscall to fetch a path name.
108    The buffer is malloc'd and the address is stored in BUFP.
109    The result is that of get_string, but prepended with
110    simulator_sysroot if the string starts with '/'.
111    If an error occurs, no buffer is left malloc'd.  */
112 
113 static int
114 get_path (cb, sc, addr, bufp)
115      host_callback *cb;
116      CB_SYSCALL *sc;
117      TADDR addr;
118      char **bufp;
119 {
120   char *buf = xmalloc (MAX_PATH_LEN);
121   int result;
122   int sysroot_len = strlen (simulator_sysroot);
123 
124   result = get_string (cb, sc, buf, MAX_PATH_LEN - sysroot_len, addr);
125   if (result == 0)
126     {
127       /* Prepend absolute paths with simulator_sysroot.  Relative paths
128 	 are supposed to be relative to a chdir within that path, but at
129 	 this point unknown where.  */
130       if (simulator_sysroot[0] != '\0' && *buf == '/')
131 	{
132 	  /* Considering expected rareness of syscalls with absolute
133 	     file paths (compared to relative file paths and insn
134 	     execution), it does not seem worthwhile to rearrange things
135 	     to get rid of the string moves here; we'd need at least an
136 	     extra call to check the initial '/' in the path.  */
137 	  memmove (buf + sysroot_len, buf, sysroot_len);
138 	  memcpy (buf, simulator_sysroot, sysroot_len);
139 	}
140 
141       *bufp = buf;
142     }
143   else
144     free (buf);
145   return result;
146 }
147 
148 /* Perform a system call on behalf of the target.  */
149 
150 CB_RC
151 cb_syscall (cb, sc)
152      host_callback *cb;
153      CB_SYSCALL *sc;
154 {
155   TWORD result = 0, errcode = 0;
156 
157   if (sc->magic != CB_SYSCALL_MAGIC)
158     abort ();
159 
160   switch (cb_target_to_host_syscall (cb, sc->func))
161     {
162 #if 0 /* FIXME: wip */
163     case CB_SYS_argvlen :
164       {
165 	/* Compute how much space is required to store the argv,envp
166 	   strings so that the program can allocate the space and then
167 	   call SYS_argv to fetch the values.  */
168 	int addr_size = cb->addr_size;
169 	int argc,envc,arglen,envlen;
170 	const char **argv = cb->init_argv;
171 	const char **envp = cb->init_envp;
172 
173 	argc = arglen = 0;
174 	if (argv)
175 	  {
176 	    for ( ; argv[argc]; ++argc)
177 	      arglen += strlen (argv[argc]) + 1;
178 	  }
179 	envc = envlen = 0;
180 	if (envp)
181 	  {
182 	    for ( ; envp[envc]; ++envc)
183 	      envlen += strlen (envp[envc]) + 1;
184 	  }
185 	result = arglen + envlen;
186 	break;
187       }
188 
189     case CB_SYS_argv :
190       {
191 	/* Pointer to target's buffer.  */
192 	TADDR tbuf = sc->arg1;
193 	/* Buffer size.  */
194 	int bufsize = sc->arg2;
195 	/* Q is the target address of where all the strings go.  */
196 	TADDR q;
197 	int word_size = cb->word_size;
198 	int i,argc,envc,len;
199 	const char **argv = cb->init_argv;
200 	const char **envp = cb->init_envp;
201 
202 	argc = 0;
203 	if (argv)
204 	  {
205 	    for ( ; argv[argc]; ++argc)
206 	      {
207 		int len = strlen (argv[argc]);
208 		int written = (*sc->write_mem) (cb, sc, tbuf, argv[argc], len + 1);
209 		if (written != len)
210 		  {
211 		    result = -1;
212 		    errcode = EINVAL;
213 		    goto FinishSyscall;
214 		  }
215 		tbuf = len + 1;
216 	      }
217 	  }
218 	if ((*sc->write_mem) (cb, sc, tbuf, "", 1) != 1)
219 	  {
220 	    result = -1;
221 	    errcode = EINVAL;
222 	    goto FinishSyscall;
223 	  }
224 	tbuf++;
225 	envc = 0;
226 	if (envp)
227 	  {
228 	    for ( ; envp[envc]; ++envc)
229 	      {
230 		int len = strlen (envp[envc]);
231 		int written = (*sc->write_mem) (cb, sc, tbuf, envp[envc], len + 1);
232 		if (written != len)
233 		  {
234 		    result = -1;
235 		    errcode = EINVAL;
236 		    goto FinishSyscall;
237 		  }
238 		tbuf = len + 1;
239 	      }
240 	  }
241 	if ((*sc->write_mem) (cb, sc, tbuf, "", 1) != 1)
242 	  {
243 	    result = -1;
244 	    errcode = EINVAL;
245 	    goto FinishSyscall;
246 	  }
247 	result = argc;
248 	sc->result2 = envc;
249 	break;
250       }
251 #endif /* wip */
252 
253     case CB_SYS_exit :
254       /* Caller must catch and handle.  */
255       break;
256 
257     case CB_SYS_open :
258       {
259 	char *path;
260 
261 	errcode = get_path (cb, sc, sc->arg1, &path);
262 	if (errcode != 0)
263 	  {
264 	    result = -1;
265 	    goto FinishSyscall;
266 	  }
267 	result = (*cb->open) (cb, path, sc->arg2 /*, sc->arg3*/);
268 	free (path);
269 	if (result < 0)
270 	  goto ErrorFinish;
271       }
272       break;
273 
274     case CB_SYS_close :
275       result = (*cb->close) (cb, sc->arg1);
276       if (result < 0)
277 	goto ErrorFinish;
278       break;
279 
280     case CB_SYS_read :
281       {
282 	/* ??? Perfect handling of error conditions may require only one
283 	   call to cb->read.  One can't assume all the data is
284 	   contiguously stored in host memory so that would require
285 	   malloc'ing/free'ing the space.  Maybe later.  */
286 	char buf[FILE_XFR_SIZE];
287 	int fd = sc->arg1;
288 	TADDR addr = sc->arg2;
289 	size_t count = sc->arg3;
290 	size_t bytes_read = 0;
291 	int bytes_written;
292 
293 	while (count > 0)
294 	  {
295 	    if (cb_is_stdin (cb, fd))
296 	      result = (int) (*cb->read_stdin) (cb, buf,
297 						(count < FILE_XFR_SIZE
298 						 ? count : FILE_XFR_SIZE));
299 	    else
300 	      result = (int) (*cb->read) (cb, fd, buf,
301 					  (count < FILE_XFR_SIZE
302 					   ? count : FILE_XFR_SIZE));
303 	    if (result == -1)
304 	      goto ErrorFinish;
305 	    if (result == 0)	/* EOF */
306 	      break;
307 	    bytes_written = (*sc->write_mem) (cb, sc, addr, buf, result);
308 	    if (bytes_written != result)
309 	      {
310 		result = -1;
311 		errcode = EINVAL;
312 		goto FinishSyscall;
313 	      }
314 	    bytes_read += result;
315 	    count -= result;
316 	    addr += result;
317 	    /* If this is a short read, don't go back for more */
318 	    if (result != FILE_XFR_SIZE)
319 	      break;
320 	  }
321 	result = bytes_read;
322       }
323       break;
324 
325     case CB_SYS_write :
326       {
327 	/* ??? Perfect handling of error conditions may require only one
328 	   call to cb->write.  One can't assume all the data is
329 	   contiguously stored in host memory so that would require
330 	   malloc'ing/free'ing the space.  Maybe later.  */
331 	char buf[FILE_XFR_SIZE];
332 	int fd = sc->arg1;
333 	TADDR addr = sc->arg2;
334 	size_t count = sc->arg3;
335 	int bytes_read;
336 	size_t bytes_written = 0;
337 
338 	while (count > 0)
339 	  {
340 	    int bytes_to_read = count < FILE_XFR_SIZE ? count : FILE_XFR_SIZE;
341 	    bytes_read = (*sc->read_mem) (cb, sc, addr, buf, bytes_to_read);
342 	    if (bytes_read != bytes_to_read)
343 	      {
344 		result = -1;
345 		errcode = EINVAL;
346 		goto FinishSyscall;
347 	      }
348 	    if (cb_is_stdout(cb, fd))
349 	      {
350 		result = (int) (*cb->write_stdout) (cb, buf, bytes_read);
351 		(*cb->flush_stdout) (cb);
352 	      }
353 	    else if (cb_is_stderr(cb, fd))
354 	      {
355 		result = (int) (*cb->write_stderr) (cb, buf, bytes_read);
356 		(*cb->flush_stderr) (cb);
357 	      }
358 	    else
359 	      result = (int) (*cb->write) (cb, fd, buf, bytes_read);
360 	    if (result == -1)
361 	      goto ErrorFinish;
362 	    bytes_written += result;
363 	    count -= result;
364 	    addr += result;
365 	  }
366 	result = bytes_written;
367       }
368       break;
369 
370     case CB_SYS_lseek :
371       {
372 	int fd = sc->arg1;
373 	unsigned long offset = sc->arg2;
374 	int whence = sc->arg3;
375 
376 	result = (*cb->lseek) (cb, fd, offset, whence);
377 	if (result < 0)
378 	  goto ErrorFinish;
379       }
380       break;
381 
382     case CB_SYS_unlink :
383       {
384 	char *path;
385 
386 	errcode = get_path (cb, sc, sc->arg1, &path);
387 	if (errcode != 0)
388 	  {
389 	    result = -1;
390 	    goto FinishSyscall;
391 	  }
392 	result = (*cb->unlink) (cb, path);
393 	free (path);
394 	if (result < 0)
395 	  goto ErrorFinish;
396       }
397       break;
398 
399     case CB_SYS_truncate :
400       {
401 	char *path;
402 	long len = sc->arg2;
403 
404 	errcode = get_path (cb, sc, sc->arg1, &path);
405 	if (errcode != 0)
406 	  {
407 	    result = -1;
408 	    errcode = EFAULT;
409 	    goto FinishSyscall;
410 	  }
411 	result = (*cb->truncate) (cb, path, len);
412 	free (path);
413 	if (result < 0)
414 	  goto ErrorFinish;
415       }
416       break;
417 
418     case CB_SYS_ftruncate :
419       {
420 	int fd = sc->arg1;
421 	long len = sc->arg2;
422 
423 	result = (*cb->ftruncate) (cb, fd, len);
424 	if (result < 0)
425 	  goto ErrorFinish;
426       }
427       break;
428 
429     case CB_SYS_rename :
430       {
431 	char *path1, *path2;
432 
433 	errcode = get_path (cb, sc, sc->arg1, &path1);
434 	if (errcode != 0)
435 	  {
436 	    result = -1;
437 	    errcode = EFAULT;
438 	    goto FinishSyscall;
439 	  }
440 	errcode = get_path (cb, sc, sc->arg2, &path2);
441 	if (errcode != 0)
442 	  {
443 	    result = -1;
444 	    errcode = EFAULT;
445 	    free (path1);
446 	    goto FinishSyscall;
447 	  }
448 	result = (*cb->rename) (cb, path1, path2);
449 	free (path1);
450 	free (path2);
451 	if (result < 0)
452 	  goto ErrorFinish;
453       }
454       break;
455 
456     case CB_SYS_stat :
457       {
458 	char *path,*buf;
459 	int buflen;
460 	struct stat statbuf;
461 	TADDR addr = sc->arg2;
462 
463 	errcode = get_path (cb, sc, sc->arg1, &path);
464 	if (errcode != 0)
465 	  {
466 	    result = -1;
467 	    goto FinishSyscall;
468 	  }
469 	result = (*cb->stat) (cb, path, &statbuf);
470 	free (path);
471 	if (result < 0)
472 	  goto ErrorFinish;
473 	buflen = cb_host_to_target_stat (cb, NULL, NULL);
474 	buf = xmalloc (buflen);
475 	if (cb_host_to_target_stat (cb, &statbuf, buf) != buflen)
476 	  {
477 	    /* The translation failed.  This is due to an internal
478 	       host program error, not the target's fault.  */
479 	    free (buf);
480 	    errcode = ENOSYS;
481 	    result = -1;
482 	    goto FinishSyscall;
483 	  }
484 	if ((*sc->write_mem) (cb, sc, addr, buf, buflen) != buflen)
485 	  {
486 	    free (buf);
487 	    errcode = EINVAL;
488 	    result = -1;
489 	    goto FinishSyscall;
490 	  }
491 	free (buf);
492       }
493       break;
494 
495     case CB_SYS_fstat :
496       {
497 	char *buf;
498 	int buflen;
499 	struct stat statbuf;
500 	TADDR addr = sc->arg2;
501 
502 	result = (*cb->fstat) (cb, sc->arg1, &statbuf);
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_lstat :
528       {
529 	char *path, *buf;
530 	int buflen;
531 	struct stat statbuf;
532 	TADDR addr = sc->arg2;
533 
534 	errcode = get_path (cb, sc, sc->arg1, &path);
535 	if (errcode != 0)
536 	  {
537 	    result = -1;
538 	    goto FinishSyscall;
539 	  }
540 	result = (*cb->lstat) (cb, path, &statbuf);
541 	free (path);
542 	if (result < 0)
543 	  goto ErrorFinish;
544 
545 	buflen = cb_host_to_target_stat (cb, NULL, NULL);
546 	buf = xmalloc (buflen);
547 	if (cb_host_to_target_stat (cb, &statbuf, buf) != buflen)
548 	  {
549 	    /* The translation failed.  This is due to an internal
550 	       host program error, not the target's fault.
551 	       Unfortunately, it's hard to test this case, so there's no
552 	       test-case for this execution path.  */
553 	    free (buf);
554 	    errcode = ENOSYS;
555 	    result = -1;
556 	    goto FinishSyscall;
557 	  }
558 
559 	if ((*sc->write_mem) (cb, sc, addr, buf, buflen) != buflen)
560 	  {
561 	    free (buf);
562 	    errcode = EINVAL;
563 	    result = -1;
564 	    goto FinishSyscall;
565 	  }
566 
567 	free (buf);
568       }
569       break;
570 
571     case CB_SYS_pipe :
572       {
573 	int p[2];
574 	char *target_p = xcalloc (1, cb->target_sizeof_int * 2);
575 
576 	result = (*cb->pipe) (cb, p);
577 	if (result != 0)
578 	  goto ErrorFinish;
579 
580 	cb_store_target_endian (cb, target_p, cb->target_sizeof_int, p[0]);
581 	cb_store_target_endian (cb, target_p + cb->target_sizeof_int,
582 				cb->target_sizeof_int, p[1]);
583 	if ((*sc->write_mem) (cb, sc, sc->arg1, target_p,
584 			      cb->target_sizeof_int * 2)
585 	    != cb->target_sizeof_int * 2)
586 	  {
587 	    /* Close the pipe fd:s.  */
588 	    (*cb->close) (cb, p[0]);
589 	    (*cb->close) (cb, p[1]);
590 	    errcode = EFAULT;
591 	    result = -1;
592 	  }
593 
594 	free (target_p);
595       }
596       break;
597 
598     case CB_SYS_time :
599       {
600 	/* FIXME: May wish to change CB_SYS_time to something else.
601 	   We might also want gettimeofday or times, but if system calls
602 	   can be built on others, we can keep the number we have to support
603 	   here down.  */
604 	time_t t = (*cb->time) (cb, (time_t *) 0);
605 	result = t;
606 	/* It is up to target code to process the argument to time().  */
607       }
608       break;
609 
610     case CB_SYS_chdir :
611     case CB_SYS_chmod :
612     case CB_SYS_utime :
613       /* fall through for now */
614 
615     default :
616       result = -1;
617       errcode = ENOSYS;
618       break;
619     }
620 
621  FinishSyscall:
622   sc->result = result;
623   if (errcode == 0)
624     sc->errcode = 0;
625   else
626     sc->errcode = cb_host_to_target_errno (cb, errcode);
627   return CB_RC_OK;
628 
629  ErrorFinish:
630   sc->result = result;
631   sc->errcode = (*cb->get_errno) (cb);
632   return CB_RC_OK;
633 }
634