OSDN Git Service

sim: common: trim trailing whitespace
[pf3gnuchains/sourceware.git] / sim / common / syscall.c
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 }