]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/common/syscall.c
4e76d2008a30d3287a6594b51fdfdadbde0c7015
[thirdparty/binutils-gdb.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 }