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 #include <errno.h>
46 #include <fcntl.h>
47 #include <time.h>
48 #include <sys/types.h>
49 #include <sys/stat.h>
50 #include "gdb/callback.h"
51 #include "targ-vals.h"
52
53 #ifdef HAVE_UNISTD_H
54 #include <unistd.h>
55 #endif
56
57 /* ??? sim_cb_printf should be cb_printf, but until the callback support is
58 broken out of the simulator directory, these are here to not require
59 sim-utils.h. */
60 void sim_cb_printf PARAMS ((host_callback *, const char *, ...));
61 void sim_cb_eprintf PARAMS ((host_callback *, const char *, ...));
62
63 extern CB_TARGET_DEFS_MAP cb_init_syscall_map[];
64 extern CB_TARGET_DEFS_MAP cb_init_errno_map[];
65 extern CB_TARGET_DEFS_MAP cb_init_open_map[];
66
67 extern int system PARAMS ((const char *));
68
69 static int os_init PARAMS ((host_callback *));
70 static int os_shutdown PARAMS ((host_callback *));
71 static int os_unlink PARAMS ((host_callback *, const char *));
72 static long os_time PARAMS ((host_callback *, long *));
73 static int os_system PARAMS ((host_callback *, const char *));
74 static int os_rename PARAMS ((host_callback *, const char *, const char *));
75 static int os_write_stdout PARAMS ((host_callback *, const char *, int));
76 static void os_flush_stdout PARAMS ((host_callback *));
77 static int os_write_stderr PARAMS ((host_callback *, const char *, int));
78 static void os_flush_stderr PARAMS ((host_callback *));
79 static int os_write PARAMS ((host_callback *, int, const char *, int));
80 static int os_read_stdin PARAMS ((host_callback *, char *, int));
81 static int os_read PARAMS ((host_callback *, int, char *, int));
82 static int os_open PARAMS ((host_callback *, const char *, int));
83 static int os_lseek PARAMS ((host_callback *, int, long, int));
84 static int os_isatty PARAMS ((host_callback *, int));
85 static int os_get_errno PARAMS ((host_callback *));
86 static int os_close PARAMS ((host_callback *, int));
87 static void os_vprintf_filtered PARAMS ((host_callback *, const char *, va_list));
88 static void os_evprintf_filtered PARAMS ((host_callback *, const char *, va_list));
89 static void os_error PARAMS ((host_callback *, const char *, ...));
90 static int fdmap PARAMS ((host_callback *, int));
91 static int fdbad PARAMS ((host_callback *, int));
92 static int wrap PARAMS ((host_callback *, int));
93
94 /* Set the callback copy of errno from what we see now. */
95
96 static int
wrap(p,val)97 wrap (p, val)
98 host_callback *p;
99 int val;
100 {
101 p->last_errno = errno;
102 return val;
103 }
104
105 /* Make sure the FD provided is ok. If not, return non-zero
106 and set errno. */
107
108 static int
fdbad(p,fd)109 fdbad (p, fd)
110 host_callback *p;
111 int fd;
112 {
113 if (fd < 0 || fd > MAX_CALLBACK_FDS || p->fd_buddy[fd] < 0)
114 {
115 p->last_errno = EINVAL;
116 return -1;
117 }
118 return 0;
119 }
120
121 static int
fdmap(p,fd)122 fdmap (p, fd)
123 host_callback *p;
124 int fd;
125 {
126 return p->fdmap[fd];
127 }
128
129 static int
os_close(p,fd)130 os_close (p, fd)
131 host_callback *p;
132 int fd;
133 {
134 int result;
135 int i, next;
136
137 result = fdbad (p, fd);
138 if (result)
139 return result;
140 /* If this file descripter has one or more buddies (originals /
141 duplicates from a dup), just remove it from the circular list. */
142 for (i = fd; (next = p->fd_buddy[i]) != fd; )
143 i = next;
144 if (fd != i)
145 p->fd_buddy[i] = p->fd_buddy[fd];
146 else
147 result = wrap (p, close (fdmap (p, fd)));
148 p->fd_buddy[fd] = -1;
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)
158 static int
os_poll_quit(p)159 os_poll_quit (p)
160 host_callback *p;
161 {
162 #if defined(__GO32__)
163 int kbhit ();
164 int getkey ();
165 if (kbhit ())
166 {
167 int k = getkey ();
168 if (k == 1)
169 {
170 return 1;
171 }
172 else if (k == 2)
173 {
174 return 1;
175 }
176 else
177 {
178 sim_cb_eprintf (p, "CTRL-A to quit, CTRL-B to quit harder\n");
179 }
180 }
181 #endif
182 #if defined (_MSC_VER)
183 /* NB - this will not compile! */
184 int k = win32pollquit();
185 if (k == 1)
186 return 1;
187 else if (k == 2)
188 return 1;
189 #endif
190 return 0;
191 }
192 #else
193 #define os_poll_quit 0
194 #endif /* defined(__GO32__) || defined(_MSC_VER) */
195
196 static int
os_get_errno(p)197 os_get_errno (p)
198 host_callback *p;
199 {
200 return cb_host_to_target_errno (p, p->last_errno);
201 }
202
203
204 static int
os_isatty(p,fd)205 os_isatty (p, fd)
206 host_callback *p;
207 int fd;
208 {
209 int result;
210
211 result = fdbad (p, fd);
212 if (result)
213 return result;
214 result = wrap (p, isatty (fdmap (p, fd)));
215
216 return result;
217 }
218
219 static int
os_lseek(p,fd,off,way)220 os_lseek (p, fd, off, way)
221 host_callback *p;
222 int fd;
223 long off;
224 int way;
225 {
226 int result;
227
228 result = fdbad (p, fd);
229 if (result)
230 return result;
231 result = lseek (fdmap (p, fd), off, way);
232 return result;
233 }
234
235 static int
os_open(p,name,flags)236 os_open (p, name, flags)
237 host_callback *p;
238 const char *name;
239 int flags;
240 {
241 int i;
242 for (i = 0; i < MAX_CALLBACK_FDS; i++)
243 {
244 if (p->fd_buddy[i] < 0)
245 {
246 int f = open (name, cb_target_to_host_open (p, flags), 0644);
247 if (f < 0)
248 {
249 p->last_errno = errno;
250 return f;
251 }
252 p->fd_buddy[i] = i;
253 p->fdmap[i] = f;
254 return i;
255 }
256 }
257 p->last_errno = EMFILE;
258 return -1;
259 }
260
261 static int
os_read(p,fd,buf,len)262 os_read (p, fd, buf, len)
263 host_callback *p;
264 int fd;
265 char *buf;
266 int len;
267 {
268 int result;
269
270 result = fdbad (p, fd);
271 if (result)
272 return result;
273 result = wrap (p, read (fdmap (p, fd), buf, len));
274 return result;
275 }
276
277 static int
os_read_stdin(p,buf,len)278 os_read_stdin (p, buf, len)
279 host_callback *p;
280 char *buf;
281 int len;
282 {
283 return wrap (p, read (0, buf, len));
284 }
285
286 static int
os_write(p,fd,buf,len)287 os_write (p, fd, buf, len)
288 host_callback *p;
289 int fd;
290 const char *buf;
291 int len;
292 {
293 int result;
294 int real_fd;
295
296 result = fdbad (p, fd);
297 if (result)
298 return result;
299 real_fd = fdmap (p, fd);
300 switch (real_fd)
301 {
302 default:
303 result = wrap (p, write (real_fd, buf, len));
304 break;
305 case 1:
306 result = p->write_stdout (p, buf, len);
307 break;
308 case 2:
309 result = p->write_stderr (p, buf, len);
310 break;
311 }
312 return result;
313 }
314
315 static int
os_write_stdout(p,buf,len)316 os_write_stdout (p, buf, len)
317 host_callback *p ATTRIBUTE_UNUSED;
318 const char *buf;
319 int len;
320 {
321 return fwrite (buf, 1, len, stdout);
322 }
323
324 static void
os_flush_stdout(p)325 os_flush_stdout (p)
326 host_callback *p ATTRIBUTE_UNUSED;
327 {
328 fflush (stdout);
329 }
330
331 static int
os_write_stderr(p,buf,len)332 os_write_stderr (p, buf, len)
333 host_callback *p ATTRIBUTE_UNUSED;
334 const char *buf;
335 int len;
336 {
337 return fwrite (buf, 1, len, stderr);
338 }
339
340 static void
os_flush_stderr(p)341 os_flush_stderr (p)
342 host_callback *p ATTRIBUTE_UNUSED;
343 {
344 fflush (stderr);
345 }
346
347 static int
os_rename(p,f1,f2)348 os_rename (p, f1, f2)
349 host_callback *p;
350 const char *f1;
351 const char *f2;
352 {
353 return wrap (p, rename (f1, f2));
354 }
355
356
357 static int
os_system(p,s)358 os_system (p, s)
359 host_callback *p;
360 const char *s;
361 {
362 return wrap (p, system (s));
363 }
364
365 static long
os_time(p,t)366 os_time (p, t)
367 host_callback *p;
368 long *t;
369 {
370 return wrap (p, time (t));
371 }
372
373
374 static int
os_unlink(p,f1)375 os_unlink (p, f1)
376 host_callback *p;
377 const char *f1;
378 {
379 return wrap (p, unlink (f1));
380 }
381
382 static int
os_stat(p,file,buf)383 os_stat (p, file, buf)
384 host_callback *p;
385 const char *file;
386 struct stat *buf;
387 {
388 /* ??? There is an issue of when to translate to the target layout.
389 One could do that inside this function, or one could have the
390 caller do it. It's more flexible to let the caller do it, though
391 I'm not sure the flexibility will ever be useful. */
392 return wrap (p, stat (file, buf));
393 }
394
395 static int
os_fstat(p,fd,buf)396 os_fstat (p, fd, buf)
397 host_callback *p;
398 int fd;
399 struct stat *buf;
400 {
401 if (fdbad (p, fd))
402 return -1;
403 /* ??? There is an issue of when to translate to the target layout.
404 One could do that inside this function, or one could have the
405 caller do it. It's more flexible to let the caller do it, though
406 I'm not sure the flexibility will ever be useful. */
407 return wrap (p, fstat (fdmap (p, fd), buf));
408 }
409
410 static int
os_ftruncate(p,fd,len)411 os_ftruncate (p, fd, len)
412 host_callback *p;
413 int fd;
414 long len;
415 {
416 int result;
417
418 result = fdbad (p, fd);
419 if (result)
420 return result;
421 result = wrap (p, ftruncate (fdmap (p, fd), len));
422 return result;
423 }
424
425 static int
os_truncate(p,file,len)426 os_truncate (p, file, len)
427 host_callback *p;
428 const char *file;
429 long len;
430 {
431 return wrap (p, truncate (file, len));
432 }
433
434 static int
os_shutdown(p)435 os_shutdown (p)
436 host_callback *p;
437 {
438 int i, next, j;
439 for (i = 0; i < MAX_CALLBACK_FDS; i++)
440 {
441 int do_close = 1;
442
443 next = p->fd_buddy[i];
444 if (next < 0)
445 continue;
446 do
447 {
448 j = next;
449 if (j == MAX_CALLBACK_FDS)
450 do_close = 0;
451 next = p->fd_buddy[j];
452 p->fd_buddy[j] = -1;
453 /* At the initial call of os_init, we got -1, 0, 0, 0, ... */
454 if (next < 0)
455 {
456 p->fd_buddy[i] = -1;
457 do_close = 0;
458 break;
459 }
460 }
461 while (j != i);
462 if (do_close)
463 close (p->fdmap[i]);
464 }
465 return 1;
466 }
467
468 static int
os_init(p)469 os_init (p)
470 host_callback *p;
471 {
472 int i;
473
474 os_shutdown (p);
475 for (i = 0; i < 3; i++)
476 {
477 p->fdmap[i] = i;
478 p->fd_buddy[i] = i - 1;
479 }
480 p->fd_buddy[0] = MAX_CALLBACK_FDS;
481 p->fd_buddy[MAX_CALLBACK_FDS] = 2;
482
483 p->syscall_map = cb_init_syscall_map;
484 p->errno_map = cb_init_errno_map;
485 p->open_map = cb_init_open_map;
486
487 return 1;
488 }
489
490 /* DEPRECATED */
491
492 /* VARARGS */
493 static void
494 #ifdef ANSI_PROTOTYPES
os_printf_filtered(host_callback * p ATTRIBUTE_UNUSED,const char * format,...)495 os_printf_filtered (host_callback *p ATTRIBUTE_UNUSED, const char *format, ...)
496 #else
497 os_printf_filtered (p, va_alist)
498 host_callback *p;
499 va_dcl
500 #endif
501 {
502 va_list args;
503 #ifdef ANSI_PROTOTYPES
504 va_start (args, format);
505 #else
506 char *format;
507
508 va_start (args);
509 format = va_arg (args, char *);
510 #endif
511
512 vfprintf (stdout, format, args);
513 va_end (args);
514 }
515
516 /* VARARGS */
517 static void
518 #ifdef ANSI_PROTOTYPES
os_vprintf_filtered(host_callback * p ATTRIBUTE_UNUSED,const char * format,va_list args)519 os_vprintf_filtered (host_callback *p ATTRIBUTE_UNUSED, const char *format, va_list args)
520 #else
521 os_vprintf_filtered (p, format, args)
522 host_callback *p;
523 const char *format;
524 va_list args;
525 #endif
526 {
527 vprintf (format, args);
528 }
529
530 /* VARARGS */
531 static void
532 #ifdef ANSI_PROTOTYPES
os_evprintf_filtered(host_callback * p ATTRIBUTE_UNUSED,const char * format,va_list args)533 os_evprintf_filtered (host_callback *p ATTRIBUTE_UNUSED, const char *format, va_list args)
534 #else
535 os_evprintf_filtered (p, format, args)
536 host_callback *p;
537 const char *format;
538 va_list args;
539 #endif
540 {
541 vfprintf (stderr, format, args);
542 }
543
544 /* VARARGS */
545 static void
546 #ifdef ANSI_PROTOTYPES
os_error(host_callback * p ATTRIBUTE_UNUSED,const char * format,...)547 os_error (host_callback *p ATTRIBUTE_UNUSED, const char *format, ...)
548 #else
549 os_error (p, va_alist)
550 host_callback *p;
551 va_dcl
552 #endif
553 {
554 va_list args;
555 #ifdef ANSI_PROTOTYPES
556 va_start (args, format);
557 #else
558 char *format;
559
560 va_start (args);
561 format = va_arg (args, char *);
562 #endif
563
564 vfprintf (stderr, format, args);
565 fprintf (stderr, "\n");
566
567 va_end (args);
568 exit (1);
569 }
570
571 host_callback default_callback =
572 {
573 os_close,
574 os_get_errno,
575 os_isatty,
576 os_lseek,
577 os_open,
578 os_read,
579 os_read_stdin,
580 os_rename,
581 os_system,
582 os_time,
583 os_unlink,
584 os_write,
585 os_write_stdout,
586 os_flush_stdout,
587 os_write_stderr,
588 os_flush_stderr,
589
590 os_stat,
591 os_fstat,
592
593 os_ftruncate,
594 os_truncate,
595
596 os_poll_quit,
597
598 os_shutdown,
599 os_init,
600
601 os_printf_filtered, /* deprecated */
602
603 os_vprintf_filtered,
604 os_evprintf_filtered,
605 os_error,
606
607 0, /* last errno */
608
609 { 0, }, /* fdmap */
610 { -1, }, /* fd_buddy */
611
612 0, /* syscall_map */
613 0, /* errno_map */
614 0, /* open_map */
615 0, /* signal_map */
616 0, /* stat_map */
617
618 HOST_CALLBACK_MAGIC,
619 };
620
621 /* Read in a file describing the target's system call values.
622 E.g. maybe someone will want to use something other than newlib.
623 This assumes that the basic system call recognition and value passing/
624 returning is supported. So maybe some coding/recompilation will be
625 necessary, but not as much.
626
627 If an error occurs, the existing mapping is not changed. */
628
629 CB_RC
cb_read_target_syscall_maps(cb,file)630 cb_read_target_syscall_maps (cb, file)
631 host_callback *cb;
632 const char *file;
633 {
634 CB_TARGET_DEFS_MAP *syscall_map, *errno_map, *open_map, *signal_map;
635 const char *stat_map;
636 FILE *f;
637
638 if ((f = fopen (file, "r")) == NULL)
639 return CB_RC_ACCESS;
640
641 /* ... read in and parse file ... */
642
643 fclose (f);
644 return CB_RC_NO_MEM; /* FIXME:wip */
645
646 /* Free storage allocated for any existing maps. */
647 if (cb->syscall_map)
648 free (cb->syscall_map);
649 if (cb->errno_map)
650 free (cb->errno_map);
651 if (cb->open_map)
652 free (cb->open_map);
653 if (cb->signal_map)
654 free (cb->signal_map);
655 if (cb->stat_map)
656 free ((PTR) cb->stat_map);
657
658 cb->syscall_map = syscall_map;
659 cb->errno_map = errno_map;
660 cb->open_map = open_map;
661 cb->signal_map = signal_map;
662 cb->stat_map = stat_map;
663
664 return CB_RC_OK;
665 }
666
667 /* Translate the target's version of a syscall number to the host's.
668 This isn't actually the host's version, rather a canonical form.
669 ??? Perhaps this should be renamed to ..._canon_syscall. */
670
671 int
cb_target_to_host_syscall(cb,target_val)672 cb_target_to_host_syscall (cb, target_val)
673 host_callback *cb;
674 int target_val;
675 {
676 CB_TARGET_DEFS_MAP *m;
677
678 for (m = &cb->syscall_map[0]; m->target_val != -1; ++m)
679 if (m->target_val == target_val)
680 return m->host_val;
681
682 return -1;
683 }
684
685 /* FIXME: sort tables if large.
686 Alternatively, an obvious improvement for errno conversion is
687 to machine generate a function with a large switch(). */
688
689 /* Translate the host's version of errno to the target's. */
690
691 int
cb_host_to_target_errno(cb,host_val)692 cb_host_to_target_errno (cb, host_val)
693 host_callback *cb;
694 int host_val;
695 {
696 CB_TARGET_DEFS_MAP *m;
697
698 for (m = &cb->errno_map[0]; m->host_val; ++m)
699 if (m->host_val == host_val)
700 return m->target_val;
701
702 /* ??? Which error to return in this case is up for grabs.
703 Note that some missing values may have standard alternatives.
704 For now return 0 and require caller to deal with it. */
705 return 0;
706 }
707
708 /* Given a set of target bitmasks for the open system call,
709 return the host equivalent.
710 Mapping open flag values is best done by looping so there's no need
711 to machine generate this function. */
712
713 int
cb_target_to_host_open(cb,target_val)714 cb_target_to_host_open (cb, target_val)
715 host_callback *cb;
716 int target_val;
717 {
718 int host_val = 0;
719 CB_TARGET_DEFS_MAP *m;
720
721 for (m = &cb->open_map[0]; m->host_val != -1; ++m)
722 {
723 switch (m->target_val)
724 {
725 /* O_RDONLY can be (and usually is) 0 which needs to be treated
726 specially. */
727 case TARGET_O_RDONLY :
728 case TARGET_O_WRONLY :
729 case TARGET_O_RDWR :
730 if ((target_val & (TARGET_O_RDONLY | TARGET_O_WRONLY | TARGET_O_RDWR))
731 == m->target_val)
732 host_val |= m->host_val;
733 /* Handle the host/target differentiating between binary and
734 text mode. Only one case is of importance */
735 #if ! defined (TARGET_O_BINARY) && defined (O_BINARY)
736 host_val |= O_BINARY;
737 #endif
738 break;
739 default :
740 if ((m->target_val & target_val) == m->target_val)
741 host_val |= m->host_val;
742 break;
743 }
744 }
745
746 return host_val;
747 }
748
749 /* Utility for cb_host_to_target_stat to store values in the target's
750 stat struct. */
751
752 static void
store(p,size,val,big_p)753 store (p, size, val, big_p)
754 char *p;
755 int size;
756 long val; /* ??? must be as big as target word size */
757 int big_p;
758 {
759 if (big_p)
760 {
761 p += size;
762 while (size-- > 0)
763 {
764 *--p = val;
765 val >>= 8;
766 }
767 }
768 else
769 {
770 while (size-- > 0)
771 {
772 *p++ = val;
773 val >>= 8;
774 }
775 }
776 }
777
778 /* Translate a host's stat struct into a target's.
779 If HS is NULL, just compute the length of the buffer required,
780 TS is ignored.
781
782 The result is the size of the target's stat struct,
783 or zero if an error occurred during the translation. */
784
785 int
cb_host_to_target_stat(cb,hs,ts)786 cb_host_to_target_stat (cb, hs, ts)
787 host_callback *cb;
788 const struct stat *hs;
789 PTR ts;
790 {
791 const char *m = cb->stat_map;
792 char *p;
793 int big_p = 0;
794
795 if (hs == NULL)
796 ts = NULL;
797 p = ts;
798
799 while (m)
800 {
801 char *q = strchr (m, ',');
802 int size;
803
804 /* FIXME: Use sscanf? */
805 if (q == NULL)
806 {
807 /* FIXME: print error message */
808 return 0;
809 }
810 size = atoi (q + 1);
811 if (size == 0)
812 {
813 /* FIXME: print error message */
814 return 0;
815 }
816
817 if (hs != NULL)
818 {
819 if (strncmp (m, "st_dev", q - m) == 0)
820 store (p, size, hs->st_dev, big_p);
821 else if (strncmp (m, "st_ino", q - m) == 0)
822 store (p, size, hs->st_ino, big_p);
823 /* FIXME:wip */
824 else
825 store (p, size, 0, big_p); /* unsupported field, store 0 */
826 }
827
828 p += size;
829 m = strchr (q, ':');
830 if (m)
831 ++m;
832 }
833
834 return p - (char *) ts;
835 }
836
837 /* Cover functions to the vfprintf callbacks.
838
839 ??? If one thinks of the callbacks as a subsystem onto itself [or part of
840 a larger "remote target subsystem"] with a well defined interface, then
841 one would think that the subsystem would provide these. However, until
842 one is allowed to create such a subsystem (with its own source tree
843 independent of any particular user), such a critter can't exist. Thus
844 these functions are here for the time being. */
845
846 void
sim_cb_printf(host_callback * p,const char * fmt,...)847 sim_cb_printf (host_callback *p, const char *fmt, ...)
848 {
849 va_list ap;
850
851 va_start (ap, fmt);
852 p->vprintf_filtered (p, fmt, ap);
853 va_end (ap);
854 }
855
856 void
sim_cb_eprintf(host_callback * p,const char * fmt,...)857 sim_cb_eprintf (host_callback *p, const char *fmt, ...)
858 {
859 va_list ap;
860
861 va_start (ap, fmt);
862 p->evprintf_filtered (p, fmt, ap);
863 va_end (ap);
864 }
865