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