sim: common: add basic model assert
[external/binutils.git] / sim / common / syscall.c
1 /* Remote target system call support.
2    Copyright 1997-2015 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.  */
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 }