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