xref: /netbsd-src/external/gpl3/gdb/dist/sim/common/syscall.c (revision 181254a7b1bdde6873432bffef2d2decc4b5c22f)
1 /* Remote target system call support.
2    Copyright 1997-2019 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.  */
73 char *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 
78 int
79 cb_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 
108 static int
109 get_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 
141 CB_RC
142 cb_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