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