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