]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/common/callback.c
sim: switch config.h usage to defs.h
[thirdparty/binutils-gdb.git] / sim / common / callback.c
CommitLineData
c906108c 1/* Remote target callback routines.
3666a048 2 Copyright 1995-2021 Free Software Foundation, Inc.
c906108c
SS
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
4744ac1b 9 the Free Software Foundation; either version 3 of the License, or
c906108c
SS
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
4744ac1b 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
c906108c
SS
19
20/* This file provides a standard way for targets to talk to the host OS
21 level. */
22
6df01ab8
MF
23/* This must come before any other includes. */
24#include "defs.h"
25
c906108c 26#include "ansidecl.h"
c906108c 27#include <stdarg.h>
c906108c 28#include <stdio.h>
c906108c 29#include <stdlib.h>
c906108c 30#include <string.h>
97f669ed
HPN
31/* For PIPE_BUF. */
32#include <limits.h>
c906108c
SS
33#include <errno.h>
34#include <fcntl.h>
35#include <time.h>
36#include <sys/types.h>
37#include <sys/stat.h>
df68e12b 38#include "sim/callback.h"
c906108c 39#include "targ-vals.h"
97f669ed
HPN
40/* For xmalloc. */
41#include "libiberty.h"
c906108c
SS
42
43#ifdef HAVE_UNISTD_H
44#include <unistd.h>
45#endif
46
33aa0cbb
PB
47#ifndef PIPE_BUF
48#define PIPE_BUF 512
49#endif
50
c906108c
SS
51/* ??? sim_cb_printf should be cb_printf, but until the callback support is
52 broken out of the simulator directory, these are here to not require
53 sim-utils.h. */
bdca5ee4
TT
54void sim_cb_printf (host_callback *, const char *, ...);
55void sim_cb_eprintf (host_callback *, const char *, ...);
c906108c
SS
56
57extern CB_TARGET_DEFS_MAP cb_init_syscall_map[];
58extern CB_TARGET_DEFS_MAP cb_init_errno_map[];
59extern CB_TARGET_DEFS_MAP cb_init_open_map[];
60
c906108c
SS
61/* Make sure the FD provided is ok. If not, return non-zero
62 and set errno. */
63
028f6515 64static int
1a8a700e 65fdbad (host_callback *p, int fd)
c906108c 66{
594ee3a7 67 if (fd < 0 || fd > MAX_CALLBACK_FDS || p->fd_buddy[fd] < 0)
c906108c 68 {
fee17b35 69 p->last_errno = EBADF;
c906108c
SS
70 return -1;
71 }
72 return 0;
73}
74
028f6515 75static int
1a8a700e 76fdmap (host_callback *p, int fd)
c906108c
SS
77{
78 return p->fdmap[fd];
79}
80
028f6515 81static int
1a8a700e 82os_close (host_callback *p, int fd)
c906108c
SS
83{
84 int result;
594ee3a7 85 int i, next;
c906108c
SS
86
87 result = fdbad (p, fd);
88 if (result)
89 return result;
594ee3a7
JR
90 /* If this file descripter has one or more buddies (originals /
91 duplicates from a dup), just remove it from the circular list. */
92 for (i = fd; (next = p->fd_buddy[i]) != fd; )
93 i = next;
94 if (fd != i)
95 p->fd_buddy[i] = p->fd_buddy[fd];
96 else
97f669ed
HPN
97 {
98 if (p->ispipe[fd])
99 {
100 int other = p->ispipe[fd];
101 int reader, writer;
102
103 if (other > 0)
104 {
105 /* Closing the read side. */
106 reader = fd;
107 writer = other;
108 }
109 else
110 {
111 /* Closing the write side. */
112 writer = fd;
113 reader = -other;
114 }
115
116 /* If there was data in the buffer, make a last "now empty"
117 call, then deallocate data. */
118 if (p->pipe_buffer[writer].buffer != NULL)
119 {
120 (*p->pipe_empty) (p, reader, writer);
121 free (p->pipe_buffer[writer].buffer);
122 p->pipe_buffer[writer].buffer = NULL;
123 }
124
125 /* Clear pipe data for this side. */
126 p->pipe_buffer[fd].size = 0;
127 p->ispipe[fd] = 0;
128
129 /* If this was the first close, mark the other side as the
130 only remaining side. */
131 if (fd != abs (other))
132 p->ispipe[abs (other)] = -other;
133 p->fd_buddy[fd] = -1;
134 return 0;
135 }
136
ccf2e592
MF
137 result = close (fdmap (p, fd));
138 p->last_errno = errno;
97f669ed 139 }
594ee3a7 140 p->fd_buddy[fd] = -1;
c906108c
SS
141
142 return result;
143}
144
145
146/* taken from gdb/util.c:notice_quit() - should be in a library */
147
148
149#if defined(__GO32__) || defined (_MSC_VER)
150static int
1a8a700e 151os_poll_quit (host_callback *p)
c906108c
SS
152{
153#if defined(__GO32__)
154 int kbhit ();
155 int getkey ();
156 if (kbhit ())
157 {
158 int k = getkey ();
159 if (k == 1)
160 {
161 return 1;
162 }
163 else if (k == 2)
164 {
165 return 1;
166 }
028f6515 167 else
c906108c
SS
168 {
169 sim_cb_eprintf (p, "CTRL-A to quit, CTRL-B to quit harder\n");
170 }
171 }
172#endif
173#if defined (_MSC_VER)
174 /* NB - this will not compile! */
34b47c38 175 int k = win32pollquit ();
c906108c
SS
176 if (k == 1)
177 return 1;
178 else if (k == 2)
179 return 1;
180#endif
181 return 0;
182}
183#else
184#define os_poll_quit 0
185#endif /* defined(__GO32__) || defined(_MSC_VER) */
186
028f6515 187static int
1a8a700e 188os_get_errno (host_callback *p)
c906108c
SS
189{
190 return cb_host_to_target_errno (p, p->last_errno);
191}
192
193
028f6515 194static int
1a8a700e 195os_isatty (host_callback *p, int fd)
c906108c
SS
196{
197 int result;
198
199 result = fdbad (p, fd);
200 if (result)
201 return result;
c906108c 202
ccf2e592
MF
203 result = isatty (fdmap (p, fd));
204 p->last_errno = errno;
c906108c
SS
205 return result;
206}
207
2fbe9507
MF
208static int64_t
209os_lseek (host_callback *p, int fd, int64_t off, int way)
c906108c 210{
2fbe9507 211 int64_t result;
c906108c
SS
212
213 result = fdbad (p, fd);
214 if (result)
215 return result;
ccf2e592
MF
216
217 result = lseek (fdmap (p, fd), off, way);
218 p->last_errno = errno;
c906108c
SS
219 return result;
220}
221
028f6515 222static int
1a8a700e 223os_open (host_callback *p, const char *name, int flags)
c906108c
SS
224{
225 int i;
226 for (i = 0; i < MAX_CALLBACK_FDS; i++)
227 {
594ee3a7 228 if (p->fd_buddy[i] < 0)
c906108c
SS
229 {
230 int f = open (name, cb_target_to_host_open (p, flags), 0644);
231 if (f < 0)
232 {
233 p->last_errno = errno;
234 return f;
235 }
594ee3a7 236 p->fd_buddy[i] = i;
c906108c
SS
237 p->fdmap[i] = f;
238 return i;
239 }
240 }
241 p->last_errno = EMFILE;
242 return -1;
243}
244
028f6515 245static int
1a8a700e 246os_read (host_callback *p, int fd, char *buf, int len)
c906108c
SS
247{
248 int result;
249
250 result = fdbad (p, fd);
251 if (result)
252 return result;
97f669ed
HPN
253 if (p->ispipe[fd])
254 {
255 int writer = p->ispipe[fd];
256
257 /* Can't read from the write-end. */
258 if (writer < 0)
259 {
260 p->last_errno = EBADF;
261 return -1;
262 }
263
264 /* Nothing to read if nothing is written. */
265 if (p->pipe_buffer[writer].size == 0)
266 return 0;
267
268 /* Truncate read request size to buffer size minus what's already
269 read. */
270 if (len > p->pipe_buffer[writer].size - p->pipe_buffer[fd].size)
271 len = p->pipe_buffer[writer].size - p->pipe_buffer[fd].size;
272
273 memcpy (buf, p->pipe_buffer[writer].buffer + p->pipe_buffer[fd].size,
274 len);
275
276 /* Account for what we just read. */
277 p->pipe_buffer[fd].size += len;
278
279 /* If we've read everything, empty and deallocate the buffer and
280 signal buffer-empty to client. (This isn't expected to be a
281 hot path in the simulator, so we don't hold on to the buffer.) */
282 if (p->pipe_buffer[fd].size == p->pipe_buffer[writer].size)
283 {
284 free (p->pipe_buffer[writer].buffer);
285 p->pipe_buffer[writer].buffer = NULL;
286 p->pipe_buffer[fd].size = 0;
287 p->pipe_buffer[writer].size = 0;
288 (*p->pipe_empty) (p, fd, writer);
289 }
290
291 return len;
292 }
293
ccf2e592
MF
294 result = read (fdmap (p, fd), buf, len);
295 p->last_errno = errno;
c906108c
SS
296 return result;
297}
298
028f6515 299static int
1a8a700e 300os_read_stdin (host_callback *p, char *buf, int len)
c906108c 301{
ccf2e592
MF
302 int result;
303
304 result = read (0, buf, len);
305 p->last_errno = errno;
306 return result;
c906108c
SS
307}
308
028f6515 309static int
1a8a700e 310os_write (host_callback *p, int fd, const char *buf, int len)
c906108c
SS
311{
312 int result;
313 int real_fd;
314
315 result = fdbad (p, fd);
316 if (result)
317 return result;
97f669ed
HPN
318
319 if (p->ispipe[fd])
320 {
321 int reader = -p->ispipe[fd];
322
323 /* Can't write to the read-end. */
324 if (reader < 0)
325 {
326 p->last_errno = EBADF;
327 return -1;
328 }
329
330 /* Can't write to pipe with closed read end.
331 FIXME: We should send a SIGPIPE. */
332 if (reader == fd)
333 {
334 p->last_errno = EPIPE;
335 return -1;
336 }
337
338 /* As a sanity-check, we bail out it the buffered contents is much
339 larger than the size of the buffer on the host. We don't want
340 to run out of memory in the simulator due to a target program
341 bug if we can help it. Unfortunately, regarding the value that
342 reaches the simulated program, it's no use returning *less*
343 than the requested amount, because cb_syscall loops calling
344 this function until the whole amount is done. */
345 if (p->pipe_buffer[fd].size + len > 10 * PIPE_BUF)
346 {
347 p->last_errno = EFBIG;
348 return -1;
349 }
350
351 p->pipe_buffer[fd].buffer
352 = xrealloc (p->pipe_buffer[fd].buffer, p->pipe_buffer[fd].size + len);
353 memcpy (p->pipe_buffer[fd].buffer + p->pipe_buffer[fd].size,
354 buf, len);
355 p->pipe_buffer[fd].size += len;
356
357 (*p->pipe_nonempty) (p, reader, fd);
358 return len;
359 }
360
c906108c
SS
361 real_fd = fdmap (p, fd);
362 switch (real_fd)
363 {
364 default:
ccf2e592
MF
365 result = write (real_fd, buf, len);
366 p->last_errno = errno;
c906108c
SS
367 break;
368 case 1:
369 result = p->write_stdout (p, buf, len);
370 break;
371 case 2:
372 result = p->write_stderr (p, buf, len);
373 break;
374 }
375 return result;
376}
377
028f6515 378static int
1a8a700e 379os_write_stdout (host_callback *p ATTRIBUTE_UNUSED, const char *buf, int len)
c906108c
SS
380{
381 return fwrite (buf, 1, len, stdout);
382}
383
384static void
1a8a700e 385os_flush_stdout (host_callback *p ATTRIBUTE_UNUSED)
c906108c
SS
386{
387 fflush (stdout);
388}
389
028f6515 390static int
1a8a700e 391os_write_stderr (host_callback *p ATTRIBUTE_UNUSED, const char *buf, int len)
c906108c
SS
392{
393 return fwrite (buf, 1, len, stderr);
394}
395
396static void
1a8a700e 397os_flush_stderr (host_callback *p ATTRIBUTE_UNUSED)
c906108c
SS
398{
399 fflush (stderr);
400}
401
028f6515 402static int
1a8a700e 403os_rename (host_callback *p, const char *f1, const char *f2)
c906108c 404{
ccf2e592
MF
405 int result;
406
407 result = rename (f1, f2);
408 p->last_errno = errno;
409 return result;
c906108c
SS
410}
411
412
413static int
1a8a700e 414os_system (host_callback *p, const char *s)
c906108c 415{
ccf2e592
MF
416 int result;
417
418 result = system (s);
419 p->last_errno = errno;
420 return result;
c906108c
SS
421}
422
00330cd1
MF
423static int64_t
424os_time (host_callback *p)
c906108c 425{
00330cd1 426 int64_t result;
ccf2e592 427
00330cd1 428 result = time (NULL);
ccf2e592
MF
429 p->last_errno = errno;
430 return result;
c906108c
SS
431}
432
433
028f6515 434static int
1a8a700e 435os_unlink (host_callback *p, const char *f1)
c906108c 436{
ccf2e592
MF
437 int result;
438
439 result = unlink (f1);
440 p->last_errno = errno;
441 return result;
c906108c
SS
442}
443
444static int
1a8a700e 445os_stat (host_callback *p, const char *file, struct stat *buf)
c906108c 446{
ccf2e592
MF
447 int result;
448
c906108c
SS
449 /* ??? There is an issue of when to translate to the target layout.
450 One could do that inside this function, or one could have the
451 caller do it. It's more flexible to let the caller do it, though
452 I'm not sure the flexibility will ever be useful. */
ccf2e592
MF
453 result = stat (file, buf);
454 p->last_errno = errno;
455 return result;
c906108c
SS
456}
457
458static int
1a8a700e 459os_fstat (host_callback *p, int fd, struct stat *buf)
c906108c 460{
ccf2e592
MF
461 int result;
462
c906108c
SS
463 if (fdbad (p, fd))
464 return -1;
97f669ed
HPN
465
466 if (p->ispipe[fd])
467 {
0c4507fd 468#if defined (HAVE_STRUCT_STAT_ST_ATIME) || defined (HAVE_STRUCT_STAT_ST_CTIME) || defined (HAVE_STRUCT_STAT_ST_MTIME)
00330cd1 469 time_t t = (*p->time) (p);
0c4507fd 470#endif
97f669ed
HPN
471
472 /* We have to fake the struct stat contents, since the pipe is
473 made up in the simulator. */
474 memset (buf, 0, sizeof (*buf));
475
476#ifdef HAVE_STRUCT_STAT_ST_MODE
477 buf->st_mode = S_IFIFO;
478#endif
479
480 /* If more accurate tracking than current-time is needed (for
481 example, on GNU/Linux we get accurate numbers), the p->time
482 callback (which may be something other than os_time) should
483 happen for each read and write, and we'd need to keep track of
484 atime, ctime and mtime. */
485#ifdef HAVE_STRUCT_STAT_ST_ATIME
486 buf->st_atime = t;
487#endif
488#ifdef HAVE_STRUCT_STAT_ST_CTIME
489 buf->st_ctime = t;
490#endif
491#ifdef HAVE_STRUCT_STAT_ST_MTIME
492 buf->st_mtime = t;
493#endif
494 return 0;
495 }
496
c906108c
SS
497 /* ??? There is an issue of when to translate to the target layout.
498 One could do that inside this function, or one could have the
499 caller do it. It's more flexible to let the caller do it, though
500 I'm not sure the flexibility will ever be useful. */
ccf2e592
MF
501 result = fstat (fdmap (p, fd), buf);
502 p->last_errno = errno;
503 return result;
c906108c
SS
504}
505
0d3cd463 506static int
1a8a700e 507os_lstat (host_callback *p, const char *file, struct stat *buf)
0d3cd463 508{
ccf2e592
MF
509 int result;
510
0d3cd463 511 /* NOTE: hpn/2004-12-12: Same issue here as with os_fstat. */
33aa0cbb 512#ifdef HAVE_LSTAT
ccf2e592 513 result = lstat (file, buf);
33aa0cbb 514#else
ccf2e592 515 result = stat (file, buf);
33aa0cbb 516#endif
ccf2e592
MF
517 p->last_errno = errno;
518 return result;
0d3cd463
HPN
519}
520
028f6515 521static int
2fbe9507 522os_ftruncate (host_callback *p, int fd, int64_t len)
8822d001
JR
523{
524 int result;
525
526 result = fdbad (p, fd);
97f669ed
HPN
527 if (p->ispipe[fd])
528 {
529 p->last_errno = EINVAL;
530 return -1;
531 }
8822d001
JR
532 if (result)
533 return result;
33aa0cbb 534#ifdef HAVE_FTRUNCATE
ccf2e592
MF
535 result = ftruncate (fdmap (p, fd), len);
536 p->last_errno = errno;
33aa0cbb
PB
537#else
538 p->last_errno = EINVAL;
539 result = -1;
540#endif
8822d001
JR
541 return result;
542}
543
544static int
2fbe9507 545os_truncate (host_callback *p, const char *file, int64_t len)
8822d001 546{
33aa0cbb 547#ifdef HAVE_TRUNCATE
ccf2e592
MF
548 int result;
549
550 result = truncate (file, len);
551 p->last_errno = errno;
552 return result;
33aa0cbb
PB
553#else
554 p->last_errno = EINVAL;
555 return -1;
556#endif
8822d001
JR
557}
558
97f669ed 559static int
1a8a700e 560os_pipe (host_callback *p, int *filedes)
97f669ed
HPN
561{
562 int i;
563
564 /* We deliberately don't use fd 0. It's probably stdin anyway. */
565 for (i = 1; i < MAX_CALLBACK_FDS; i++)
566 {
567 int j;
568
569 if (p->fd_buddy[i] < 0)
570 for (j = i + 1; j < MAX_CALLBACK_FDS; j++)
571 if (p->fd_buddy[j] < 0)
572 {
573 /* Found two free fd:s. Set stat to allocated and mark
574 pipeness. */
575 p->fd_buddy[i] = i;
576 p->fd_buddy[j] = j;
577 p->ispipe[i] = j;
578 p->ispipe[j] = -i;
579 filedes[0] = i;
580 filedes[1] = j;
581
582 /* Poison the FD map to make bugs apparent. */
583 p->fdmap[i] = -1;
584 p->fdmap[j] = -1;
585 return 0;
586 }
587 }
588
589 p->last_errno = EMFILE;
590 return -1;
591}
592
593/* Stub functions for pipe support. They should always be overridden in
594 targets using the pipe support, but that's up to the target. */
595
596/* Called when the simulator says that the pipe at (reader, writer) is
597 now empty (so the writer should leave its waiting state). */
598
599static void
1a8a700e 600os_pipe_empty (host_callback *p, int reader, int writer)
97f669ed
HPN
601{
602}
603
604/* Called when the simulator says the pipe at (reader, writer) is now
605 non-empty (so the writer should wait). */
606
607static void
1a8a700e 608os_pipe_nonempty (host_callback *p, int reader, int writer)
97f669ed
HPN
609{
610}
611
c906108c 612static int
1a8a700e 613os_shutdown (host_callback *p)
c906108c 614{
594ee3a7 615 int i, next, j;
c906108c
SS
616 for (i = 0; i < MAX_CALLBACK_FDS; i++)
617 {
594ee3a7
JR
618 int do_close = 1;
619
97f669ed
HPN
620 /* Zero out all pipe state. Don't call callbacks for non-empty
621 pipes; the target program has likely terminated at this point
622 or we're called at initialization time. */
623 p->ispipe[i] = 0;
624 p->pipe_buffer[i].size = 0;
625 p->pipe_buffer[i].buffer = NULL;
626
594ee3a7
JR
627 next = p->fd_buddy[i];
628 if (next < 0)
629 continue;
630 do
631 {
632 j = next;
633 if (j == MAX_CALLBACK_FDS)
634 do_close = 0;
635 next = p->fd_buddy[j];
636 p->fd_buddy[j] = -1;
637 /* At the initial call of os_init, we got -1, 0, 0, 0, ... */
638 if (next < 0)
639 {
0242f9ea 640 p->fd_buddy[i] = -1;
594ee3a7
JR
641 do_close = 0;
642 break;
643 }
644 }
645 while (j != i);
646 if (do_close)
c906108c 647 close (p->fdmap[i]);
c906108c
SS
648 }
649 return 1;
650}
651
652static int
1a8a700e 653os_init (host_callback *p)
c906108c
SS
654{
655 int i;
656
657 os_shutdown (p);
658 for (i = 0; i < 3; i++)
659 {
660 p->fdmap[i] = i;
594ee3a7 661 p->fd_buddy[i] = i - 1;
c906108c 662 }
594ee3a7
JR
663 p->fd_buddy[0] = MAX_CALLBACK_FDS;
664 p->fd_buddy[MAX_CALLBACK_FDS] = 2;
c906108c
SS
665
666 p->syscall_map = cb_init_syscall_map;
667 p->errno_map = cb_init_errno_map;
668 p->open_map = cb_init_open_map;
669
670 return 1;
671}
672
5accf1ff 673/* DEPRECATED */
c906108c
SS
674
675/* VARARGS */
2f632133 676static void ATTRIBUTE_PRINTF (2, 3)
6d358e86 677os_printf_filtered (host_callback *p ATTRIBUTE_UNUSED, const char *format, ...)
c906108c
SS
678{
679 va_list args;
c906108c 680 va_start (args, format);
c906108c
SS
681
682 vfprintf (stdout, format, args);
683 va_end (args);
684}
685
686/* VARARGS */
2f632133 687static void ATTRIBUTE_PRINTF (2, 0)
6d358e86 688os_vprintf_filtered (host_callback *p ATTRIBUTE_UNUSED, const char *format, va_list args)
c906108c
SS
689{
690 vprintf (format, args);
691}
692
693/* VARARGS */
2f632133 694static void ATTRIBUTE_PRINTF (2, 0)
6d358e86 695os_evprintf_filtered (host_callback *p ATTRIBUTE_UNUSED, const char *format, va_list args)
c906108c
SS
696{
697 vfprintf (stderr, format, args);
698}
699
700/* VARARGS */
f0c4dc40 701static void ATTRIBUTE_PRINTF (2, 3) ATTRIBUTE_NORETURN
6d358e86 702os_error (host_callback *p ATTRIBUTE_UNUSED, const char *format, ...)
c906108c
SS
703{
704 va_list args;
c906108c 705 va_start (args, format);
c906108c
SS
706
707 vfprintf (stderr, format, args);
708 fprintf (stderr, "\n");
709
710 va_end (args);
711 exit (1);
712}
713
714host_callback default_callback =
715{
716 os_close,
717 os_get_errno,
718 os_isatty,
719 os_lseek,
720 os_open,
721 os_read,
722 os_read_stdin,
723 os_rename,
724 os_system,
725 os_time,
726 os_unlink,
727 os_write,
728 os_write_stdout,
729 os_flush_stdout,
730 os_write_stderr,
731 os_flush_stderr,
732
733 os_stat,
734 os_fstat,
0d3cd463 735 os_lstat,
c906108c 736
8822d001
JR
737 os_ftruncate,
738 os_truncate,
739
97f669ed
HPN
740 os_pipe,
741 os_pipe_empty,
742 os_pipe_nonempty,
743
c906108c
SS
744 os_poll_quit,
745
746 os_shutdown,
747 os_init,
748
749 os_printf_filtered, /* deprecated */
750
751 os_vprintf_filtered,
752 os_evprintf_filtered,
753 os_error,
754
755 0, /* last errno */
756
757 { 0, }, /* fdmap */
594ee3a7 758 { -1, }, /* fd_buddy */
97f669ed
HPN
759 { 0, }, /* ispipe */
760 { { 0, 0 }, }, /* pipe_buffer */
c906108c
SS
761
762 0, /* syscall_map */
763 0, /* errno_map */
764 0, /* open_map */
765 0, /* signal_map */
766 0, /* stat_map */
028f6515 767
f4f8cce4
HPN
768 /* Defaults expected to be overridden at initialization, where needed. */
769 BFD_ENDIAN_UNKNOWN, /* target_endian */
97f669ed 770 4, /* target_sizeof_int */
f4f8cce4 771
c906108c
SS
772 HOST_CALLBACK_MAGIC,
773};
774\f
775/* Read in a file describing the target's system call values.
776 E.g. maybe someone will want to use something other than newlib.
777 This assumes that the basic system call recognition and value passing/
778 returning is supported. So maybe some coding/recompilation will be
779 necessary, but not as much.
780
781 If an error occurs, the existing mapping is not changed. */
782
783CB_RC
1a8a700e 784cb_read_target_syscall_maps (host_callback *cb, const char *file)
c906108c
SS
785{
786 CB_TARGET_DEFS_MAP *syscall_map, *errno_map, *open_map, *signal_map;
787 const char *stat_map;
788 FILE *f;
789
790 if ((f = fopen (file, "r")) == NULL)
791 return CB_RC_ACCESS;
792
793 /* ... read in and parse file ... */
794
795 fclose (f);
796 return CB_RC_NO_MEM; /* FIXME:wip */
797
798 /* Free storage allocated for any existing maps. */
799 if (cb->syscall_map)
800 free (cb->syscall_map);
801 if (cb->errno_map)
802 free (cb->errno_map);
803 if (cb->open_map)
804 free (cb->open_map);
805 if (cb->signal_map)
806 free (cb->signal_map);
807 if (cb->stat_map)
808 free ((PTR) cb->stat_map);
809
810 cb->syscall_map = syscall_map;
811 cb->errno_map = errno_map;
812 cb->open_map = open_map;
813 cb->signal_map = signal_map;
814 cb->stat_map = stat_map;
815
816 return CB_RC_OK;
817}
818
6362a3f8
MF
819/* General utility functions to search a map for a value. */
820
821static const CB_TARGET_DEFS_MAP *
822cb_target_map_entry (const CB_TARGET_DEFS_MAP map[], int target_val)
823{
824 const CB_TARGET_DEFS_MAP *m;
825
7aec3bb9 826 for (m = &map[0]; m->target_val != -1; ++m)
6362a3f8
MF
827 if (m->target_val == target_val)
828 return m;
829
830 return NULL;
831}
832
833static const CB_TARGET_DEFS_MAP *
834cb_host_map_entry (const CB_TARGET_DEFS_MAP map[], int host_val)
835{
836 const CB_TARGET_DEFS_MAP *m;
837
7aec3bb9 838 for (m = &map[0]; m->host_val != -1; ++m)
6362a3f8
MF
839 if (m->host_val == host_val)
840 return m;
841
842 return NULL;
843}
844
c906108c
SS
845/* Translate the target's version of a syscall number to the host's.
846 This isn't actually the host's version, rather a canonical form.
847 ??? Perhaps this should be renamed to ..._canon_syscall. */
848
849int
1a8a700e 850cb_target_to_host_syscall (host_callback *cb, int target_val)
c906108c 851{
6362a3f8
MF
852 const CB_TARGET_DEFS_MAP *m =
853 cb_target_map_entry (cb->syscall_map, target_val);
c906108c 854
6362a3f8 855 return m ? m->host_val : -1;
c906108c
SS
856}
857
858/* FIXME: sort tables if large.
859 Alternatively, an obvious improvement for errno conversion is
860 to machine generate a function with a large switch(). */
861
862/* Translate the host's version of errno to the target's. */
863
864int
1a8a700e 865cb_host_to_target_errno (host_callback *cb, int host_val)
c906108c 866{
6362a3f8 867 const CB_TARGET_DEFS_MAP *m = cb_host_map_entry (cb->errno_map, host_val);
c906108c
SS
868
869 /* ??? Which error to return in this case is up for grabs.
870 Note that some missing values may have standard alternatives.
871 For now return 0 and require caller to deal with it. */
6362a3f8 872 return m ? m->target_val : 0;
c906108c
SS
873}
874
875/* Given a set of target bitmasks for the open system call,
876 return the host equivalent.
877 Mapping open flag values is best done by looping so there's no need
878 to machine generate this function. */
879
880int
1a8a700e 881cb_target_to_host_open (host_callback *cb, int target_val)
c906108c
SS
882{
883 int host_val = 0;
884 CB_TARGET_DEFS_MAP *m;
885
886 for (m = &cb->open_map[0]; m->host_val != -1; ++m)
887 {
888 switch (m->target_val)
889 {
890 /* O_RDONLY can be (and usually is) 0 which needs to be treated
891 specially. */
892 case TARGET_O_RDONLY :
893 case TARGET_O_WRONLY :
894 case TARGET_O_RDWR :
895 if ((target_val & (TARGET_O_RDONLY | TARGET_O_WRONLY | TARGET_O_RDWR))
896 == m->target_val)
897 host_val |= m->host_val;
898 /* Handle the host/target differentiating between binary and
899 text mode. Only one case is of importance */
900#if ! defined (TARGET_O_BINARY) && defined (O_BINARY)
901 host_val |= O_BINARY;
902#endif
903 break;
904 default :
905 if ((m->target_val & target_val) == m->target_val)
906 host_val |= m->host_val;
907 break;
908 }
909 }
910
911 return host_val;
912}
913
f4f8cce4 914/* Utility for e.g. cb_host_to_target_stat to store values in the target's
1a8a700e
MF
915 stat struct.
916
917 ??? The "val" must be as big as target word size. */
c906108c 918
f4f8cce4 919void
1a8a700e 920cb_store_target_endian (host_callback *cb, char *p, int size, long val)
c906108c 921{
f4f8cce4 922 if (cb->target_endian == BFD_ENDIAN_BIG)
c906108c
SS
923 {
924 p += size;
925 while (size-- > 0)
926 {
927 *--p = val;
928 val >>= 8;
929 }
930 }
931 else
932 {
933 while (size-- > 0)
934 {
935 *p++ = val;
936 val >>= 8;
937 }
938 }
939}
940
941/* Translate a host's stat struct into a target's.
942 If HS is NULL, just compute the length of the buffer required,
943 TS is ignored.
944
945 The result is the size of the target's stat struct,
6439295f 946 or zero if an error occurred during the translation. */
c906108c
SS
947
948int
64654371 949cb_host_to_target_stat (host_callback *cb, const struct stat *hs, void *ts)
c906108c
SS
950{
951 const char *m = cb->stat_map;
952 char *p;
c906108c
SS
953
954 if (hs == NULL)
955 ts = NULL;
956 p = ts;
957
958 while (m)
959 {
960 char *q = strchr (m, ',');
961 int size;
962
963 /* FIXME: Use sscanf? */
964 if (q == NULL)
965 {
966 /* FIXME: print error message */
967 return 0;
968 }
969 size = atoi (q + 1);
970 if (size == 0)
971 {
972 /* FIXME: print error message */
973 return 0;
974 }
975
976 if (hs != NULL)
977 {
e1591da4 978 if (0)
697afb65
HPN
979 ;
980 /* Defined here to avoid emacs indigestion on a lone "else". */
981#undef ST_x
982#define ST_x(FLD) \
983 else if (strncmp (m, #FLD, q - m) == 0) \
f4f8cce4 984 cb_store_target_endian (cb, p, size, hs->FLD)
697afb65
HPN
985
986#ifdef HAVE_STRUCT_STAT_ST_DEV
987 ST_x (st_dev);
988#endif
989#ifdef HAVE_STRUCT_STAT_ST_INO
990 ST_x (st_ino);
991#endif
992#ifdef HAVE_STRUCT_STAT_ST_MODE
993 ST_x (st_mode);
994#endif
995#ifdef HAVE_STRUCT_STAT_ST_NLINK
996 ST_x (st_nlink);
997#endif
998#ifdef HAVE_STRUCT_STAT_ST_UID
999 ST_x (st_uid);
1000#endif
1001#ifdef HAVE_STRUCT_STAT_ST_GID
1002 ST_x (st_gid);
1003#endif
1004#ifdef HAVE_STRUCT_STAT_ST_RDEV
1005 ST_x (st_rdev);
1006#endif
1007#ifdef HAVE_STRUCT_STAT_ST_SIZE
1008 ST_x (st_size);
1009#endif
1010#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
1011 ST_x (st_blksize);
1012#endif
1013#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
1014 ST_x (st_blocks);
1015#endif
1016#ifdef HAVE_STRUCT_STAT_ST_ATIME
1017 ST_x (st_atime);
1018#endif
1019#ifdef HAVE_STRUCT_STAT_ST_MTIME
1020 ST_x (st_mtime);
1021#endif
1022#ifdef HAVE_STRUCT_STAT_ST_CTIME
1023 ST_x (st_ctime);
1024#endif
1025#undef ST_x
c906108c
SS
1026 /* FIXME:wip */
1027 else
f4f8cce4
HPN
1028 /* Unsupported field, store 0. */
1029 cb_store_target_endian (cb, p, size, 0);
c906108c
SS
1030 }
1031
1032 p += size;
1033 m = strchr (q, ':');
1034 if (m)
1035 ++m;
1036 }
1037
1038 return p - (char *) ts;
1039}
1040\f
1041/* Cover functions to the vfprintf callbacks.
1042
1043 ??? If one thinks of the callbacks as a subsystem onto itself [or part of
1044 a larger "remote target subsystem"] with a well defined interface, then
1045 one would think that the subsystem would provide these. However, until
1046 one is allowed to create such a subsystem (with its own source tree
1047 independent of any particular user), such a critter can't exist. Thus
1048 these functions are here for the time being. */
1049
1050void
1051sim_cb_printf (host_callback *p, const char *fmt, ...)
1052{
1053 va_list ap;
1054
1055 va_start (ap, fmt);
1056 p->vprintf_filtered (p, fmt, ap);
1057 va_end (ap);
1058}
1059
1060void
1061sim_cb_eprintf (host_callback *p, const char *fmt, ...)
1062{
1063 va_list ap;
1064
1065 va_start (ap, fmt);
1066 p->evprintf_filtered (p, fmt, ap);
1067 va_end (ap);
1068}
b981d709
DJ
1069
1070int
1071cb_is_stdin (host_callback *cb, int fd)
1072{
1073 return fdbad (cb, fd) ? 0 : fdmap (cb, fd) == 0;
1074}
1075
eb639c50
DJ
1076int
1077cb_is_stdout (host_callback *cb, int fd)
1078{
1079 return fdbad (cb, fd) ? 0 : fdmap (cb, fd) == 1;
1080}
1081
1082int
1083cb_is_stderr (host_callback *cb, int fd)
1084{
1085 return fdbad (cb, fd) ? 0 : fdmap (cb, fd) == 2;
1086}
6362a3f8
MF
1087\f
1088const char *
1089cb_host_str_syscall (host_callback *cb, int host_val)
1090{
1091 const CB_TARGET_DEFS_MAP *m = cb_host_map_entry (cb->syscall_map, host_val);
1092
1093 return m ? m->name : NULL;
1094}
1095
1096const char *
1097cb_host_str_errno (host_callback *cb, int host_val)
1098{
1099 const CB_TARGET_DEFS_MAP *m = cb_host_map_entry (cb->errno_map, host_val);
1100
1101 return m ? m->name : NULL;
1102}
1103
1104const char *
1105cb_host_str_signal (host_callback *cb, int host_val)
1106{
1107 const CB_TARGET_DEFS_MAP *m = cb_host_map_entry (cb->signal_map, host_val);
1108
1109 return m ? m->name : NULL;
1110}
1111
1112const char *
1113cb_target_str_syscall (host_callback *cb, int target_val)
1114{
1115 const CB_TARGET_DEFS_MAP *m =
1116 cb_target_map_entry (cb->syscall_map, target_val);
1117
1118 return m ? m->name : NULL;
1119}
1120
1121const char *
1122cb_target_str_errno (host_callback *cb, int target_val)
1123{
1124 const CB_TARGET_DEFS_MAP *m =
1125 cb_target_map_entry (cb->errno_map, target_val);
1126
1127 return m ? m->name : NULL;
1128}
1129
1130const char *
1131cb_target_str_signal (host_callback *cb, int target_val)
1132{
1133 const CB_TARGET_DEFS_MAP *m =
1134 cb_target_map_entry (cb->signal_map, target_val);
1135
1136 return m ? m->name : NULL;
1137}