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