Automatic Copyright Year update after running gdb/copyright.py
[deliverable/binutils-gdb.git] / sim / common / callback.c
CommitLineData
c906108c 1/* Remote target callback routines.
88b9d363 2 Copyright 1995-2022 Free Software Foundation, Inc.
c906108c
SS
3 Contributed by Cygnus Solutions.
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
4744ac1b 9 the Free Software Foundation; either version 3 of the License, or
c906108c
SS
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
4744ac1b 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
c906108c
SS
19
20/* This file provides a standard way for targets to talk to the host OS
21 level. */
22
6df01ab8
MF
23/* This must come before any other includes. */
24#include "defs.h"
25
c906108c 26#include "ansidecl.h"
c906108c 27#include <stdarg.h>
c906108c 28#include <stdio.h>
c906108c 29#include <stdlib.h>
c906108c 30#include <string.h>
97f669ed
HPN
31/* For PIPE_BUF. */
32#include <limits.h>
c906108c
SS
33#include <errno.h>
34#include <fcntl.h>
cc40b4f2 35#include <signal.h>
c906108c
SS
36#include <time.h>
37#include <sys/types.h>
38#include <sys/stat.h>
df68e12b 39#include "sim/callback.h"
c906108c 40#include "targ-vals.h"
97f669ed
HPN
41/* For xmalloc. */
42#include "libiberty.h"
c906108c
SS
43
44#ifdef HAVE_UNISTD_H
45#include <unistd.h>
46#endif
47
33aa0cbb
PB
48#ifndef PIPE_BUF
49#define PIPE_BUF 512
50#endif
51
c906108c
SS
52extern CB_TARGET_DEFS_MAP cb_init_syscall_map[];
53extern CB_TARGET_DEFS_MAP cb_init_errno_map[];
cc40b4f2 54extern CB_TARGET_DEFS_MAP cb_init_signal_map[];
c906108c
SS
55extern CB_TARGET_DEFS_MAP cb_init_open_map[];
56
c906108c
SS
57/* Make sure the FD provided is ok. If not, return non-zero
58 and set errno. */
59
028f6515 60static int
1a8a700e 61fdbad (host_callback *p, int fd)
c906108c 62{
594ee3a7 63 if (fd < 0 || fd > MAX_CALLBACK_FDS || p->fd_buddy[fd] < 0)
c906108c 64 {
fee17b35 65 p->last_errno = EBADF;
c906108c
SS
66 return -1;
67 }
68 return 0;
69}
70
028f6515 71static int
1a8a700e 72fdmap (host_callback *p, int fd)
c906108c
SS
73{
74 return p->fdmap[fd];
75}
76
028f6515 77static int
1a8a700e 78os_close (host_callback *p, int fd)
c906108c
SS
79{
80 int result;
594ee3a7 81 int i, next;
c906108c
SS
82
83 result = fdbad (p, fd);
84 if (result)
85 return result;
594ee3a7
JR
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
97f669ed
HPN
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
ccf2e592
MF
133 result = close (fdmap (p, fd));
134 p->last_errno = errno;
97f669ed 135 }
594ee3a7 136 p->fd_buddy[fd] = -1;
c906108c
SS
137
138 return result;
139}
140
141
142/* taken from gdb/util.c:notice_quit() - should be in a library */
143
144
54e66d16 145#if defined(_MSC_VER)
c906108c 146static int
1a8a700e 147os_poll_quit (host_callback *p)
c906108c 148{
c906108c 149 /* NB - this will not compile! */
34b47c38 150 int k = win32pollquit ();
c906108c
SS
151 if (k == 1)
152 return 1;
153 else if (k == 2)
154 return 1;
c906108c
SS
155 return 0;
156}
157#else
158#define os_poll_quit 0
54e66d16 159#endif /* defined(_MSC_VER) */
c906108c 160
028f6515 161static int
1a8a700e 162os_get_errno (host_callback *p)
c906108c
SS
163{
164 return cb_host_to_target_errno (p, p->last_errno);
165}
166
167
028f6515 168static int
1a8a700e 169os_isatty (host_callback *p, int fd)
c906108c
SS
170{
171 int result;
172
173 result = fdbad (p, fd);
174 if (result)
175 return result;
c906108c 176
ccf2e592
MF
177 result = isatty (fdmap (p, fd));
178 p->last_errno = errno;
c906108c
SS
179 return result;
180}
181
2fbe9507
MF
182static int64_t
183os_lseek (host_callback *p, int fd, int64_t off, int way)
c906108c 184{
2fbe9507 185 int64_t result;
c906108c
SS
186
187 result = fdbad (p, fd);
188 if (result)
189 return result;
ccf2e592
MF
190
191 result = lseek (fdmap (p, fd), off, way);
192 p->last_errno = errno;
c906108c
SS
193 return result;
194}
195
028f6515 196static int
1a8a700e 197os_open (host_callback *p, const char *name, int flags)
c906108c
SS
198{
199 int i;
200 for (i = 0; i < MAX_CALLBACK_FDS; i++)
201 {
594ee3a7 202 if (p->fd_buddy[i] < 0)
c906108c
SS
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 }
594ee3a7 210 p->fd_buddy[i] = i;
c906108c
SS
211 p->fdmap[i] = f;
212 return i;
213 }
214 }
215 p->last_errno = EMFILE;
216 return -1;
217}
218
028f6515 219static int
1a8a700e 220os_read (host_callback *p, int fd, char *buf, int len)
c906108c
SS
221{
222 int result;
223
224 result = fdbad (p, fd);
225 if (result)
226 return result;
97f669ed
HPN
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
ccf2e592
MF
268 result = read (fdmap (p, fd), buf, len);
269 p->last_errno = errno;
c906108c
SS
270 return result;
271}
272
028f6515 273static int
1a8a700e 274os_read_stdin (host_callback *p, char *buf, int len)
c906108c 275{
ccf2e592
MF
276 int result;
277
278 result = read (0, buf, len);
279 p->last_errno = errno;
280 return result;
c906108c
SS
281}
282
028f6515 283static int
1a8a700e 284os_write (host_callback *p, int fd, const char *buf, int len)
c906108c
SS
285{
286 int result;
287 int real_fd;
288
289 result = fdbad (p, fd);
290 if (result)
291 return result;
97f669ed
HPN
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
c906108c
SS
335 real_fd = fdmap (p, fd);
336 switch (real_fd)
337 {
338 default:
ccf2e592
MF
339 result = write (real_fd, buf, len);
340 p->last_errno = errno;
c906108c
SS
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
028f6515 352static int
1a8a700e 353os_write_stdout (host_callback *p ATTRIBUTE_UNUSED, const char *buf, int len)
c906108c
SS
354{
355 return fwrite (buf, 1, len, stdout);
356}
357
358static void
1a8a700e 359os_flush_stdout (host_callback *p ATTRIBUTE_UNUSED)
c906108c
SS
360{
361 fflush (stdout);
362}
363
028f6515 364static int
1a8a700e 365os_write_stderr (host_callback *p ATTRIBUTE_UNUSED, const char *buf, int len)
c906108c
SS
366{
367 return fwrite (buf, 1, len, stderr);
368}
369
370static void
1a8a700e 371os_flush_stderr (host_callback *p ATTRIBUTE_UNUSED)
c906108c
SS
372{
373 fflush (stderr);
374}
375
028f6515 376static int
1a8a700e 377os_rename (host_callback *p, const char *f1, const char *f2)
c906108c 378{
ccf2e592
MF
379 int result;
380
381 result = rename (f1, f2);
382 p->last_errno = errno;
383 return result;
c906108c
SS
384}
385
386
387static int
1a8a700e 388os_system (host_callback *p, const char *s)
c906108c 389{
ccf2e592
MF
390 int result;
391
392 result = system (s);
393 p->last_errno = errno;
394 return result;
c906108c
SS
395}
396
00330cd1
MF
397static int64_t
398os_time (host_callback *p)
c906108c 399{
00330cd1 400 int64_t result;
ccf2e592 401
00330cd1 402 result = time (NULL);
ccf2e592
MF
403 p->last_errno = errno;
404 return result;
c906108c
SS
405}
406
407
028f6515 408static int
1a8a700e 409os_unlink (host_callback *p, const char *f1)
c906108c 410{
ccf2e592
MF
411 int result;
412
413 result = unlink (f1);
414 p->last_errno = errno;
415 return result;
c906108c
SS
416}
417
418static int
1a8a700e 419os_stat (host_callback *p, const char *file, struct stat *buf)
c906108c 420{
ccf2e592
MF
421 int result;
422
c906108c
SS
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. */
ccf2e592
MF
427 result = stat (file, buf);
428 p->last_errno = errno;
429 return result;
c906108c
SS
430}
431
432static int
1a8a700e 433os_fstat (host_callback *p, int fd, struct stat *buf)
c906108c 434{
ccf2e592
MF
435 int result;
436
c906108c
SS
437 if (fdbad (p, fd))
438 return -1;
97f669ed
HPN
439
440 if (p->ispipe[fd])
441 {
0c4507fd 442#if defined (HAVE_STRUCT_STAT_ST_ATIME) || defined (HAVE_STRUCT_STAT_ST_CTIME) || defined (HAVE_STRUCT_STAT_ST_MTIME)
00330cd1 443 time_t t = (*p->time) (p);
0c4507fd 444#endif
97f669ed
HPN
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
c906108c
SS
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. */
ccf2e592
MF
475 result = fstat (fdmap (p, fd), buf);
476 p->last_errno = errno;
477 return result;
c906108c
SS
478}
479
0d3cd463 480static int
1a8a700e 481os_lstat (host_callback *p, const char *file, struct stat *buf)
0d3cd463 482{
ccf2e592
MF
483 int result;
484
0d3cd463 485 /* NOTE: hpn/2004-12-12: Same issue here as with os_fstat. */
33aa0cbb 486#ifdef HAVE_LSTAT
ccf2e592 487 result = lstat (file, buf);
33aa0cbb 488#else
ccf2e592 489 result = stat (file, buf);
33aa0cbb 490#endif
ccf2e592
MF
491 p->last_errno = errno;
492 return result;
0d3cd463
HPN
493}
494
028f6515 495static int
2fbe9507 496os_ftruncate (host_callback *p, int fd, int64_t len)
8822d001
JR
497{
498 int result;
499
500 result = fdbad (p, fd);
97f669ed
HPN
501 if (p->ispipe[fd])
502 {
503 p->last_errno = EINVAL;
504 return -1;
505 }
8822d001
JR
506 if (result)
507 return result;
33aa0cbb 508#ifdef HAVE_FTRUNCATE
ccf2e592
MF
509 result = ftruncate (fdmap (p, fd), len);
510 p->last_errno = errno;
33aa0cbb
PB
511#else
512 p->last_errno = EINVAL;
513 result = -1;
514#endif
8822d001
JR
515 return result;
516}
517
518static int
2fbe9507 519os_truncate (host_callback *p, const char *file, int64_t len)
8822d001 520{
33aa0cbb 521#ifdef HAVE_TRUNCATE
ccf2e592
MF
522 int result;
523
524 result = truncate (file, len);
525 p->last_errno = errno;
526 return result;
33aa0cbb
PB
527#else
528 p->last_errno = EINVAL;
529 return -1;
530#endif
8822d001
JR
531}
532
c45cffdb
MF
533static int
534os_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
d394a6ef
MF
544static int
545os_kill (host_callback *p, int pid, int signum)
546{
999b474b 547#ifdef HAVE_KILL
d394a6ef
MF
548 int result;
549
550 result = kill (pid, signum);
551 p->last_errno = errno;
552 return result;
999b474b
MF
553#else
554 p->last_errno = ENOSYS;
555 return -1;
556#endif
d394a6ef
MF
557}
558
97f669ed 559static int
1a8a700e 560os_pipe (host_callback *p, int *filedes)
97f669ed
HPN
561{
562 int i;
563
564 /* We deliberately don't use fd 0. It's probably stdin anyway. */
565 for (i = 1; i < MAX_CALLBACK_FDS; i++)
566 {
567 int j;
568
569 if (p->fd_buddy[i] < 0)
570 for (j = i + 1; j < MAX_CALLBACK_FDS; j++)
571 if (p->fd_buddy[j] < 0)
572 {
573 /* Found two free fd:s. Set stat to allocated and mark
574 pipeness. */
575 p->fd_buddy[i] = i;
576 p->fd_buddy[j] = j;
577 p->ispipe[i] = j;
578 p->ispipe[j] = -i;
579 filedes[0] = i;
580 filedes[1] = j;
581
582 /* Poison the FD map to make bugs apparent. */
583 p->fdmap[i] = -1;
584 p->fdmap[j] = -1;
585 return 0;
586 }
587 }
588
589 p->last_errno = EMFILE;
590 return -1;
591}
592
593/* Stub functions for pipe support. They should always be overridden in
594 targets using the pipe support, but that's up to the target. */
595
596/* Called when the simulator says that the pipe at (reader, writer) is
597 now empty (so the writer should leave its waiting state). */
598
599static void
1a8a700e 600os_pipe_empty (host_callback *p, int reader, int writer)
97f669ed
HPN
601{
602}
603
604/* Called when the simulator says the pipe at (reader, writer) is now
605 non-empty (so the writer should wait). */
606
607static void
1a8a700e 608os_pipe_nonempty (host_callback *p, int reader, int writer)
97f669ed
HPN
609{
610}
611
c906108c 612static int
1a8a700e 613os_shutdown (host_callback *p)
c906108c 614{
594ee3a7 615 int i, next, j;
c906108c
SS
616 for (i = 0; i < MAX_CALLBACK_FDS; i++)
617 {
594ee3a7
JR
618 int do_close = 1;
619
97f669ed
HPN
620 /* Zero out all pipe state. Don't call callbacks for non-empty
621 pipes; the target program has likely terminated at this point
622 or we're called at initialization time. */
623 p->ispipe[i] = 0;
624 p->pipe_buffer[i].size = 0;
625 p->pipe_buffer[i].buffer = NULL;
626
594ee3a7
JR
627 next = p->fd_buddy[i];
628 if (next < 0)
629 continue;
630 do
631 {
632 j = next;
633 if (j == MAX_CALLBACK_FDS)
634 do_close = 0;
635 next = p->fd_buddy[j];
636 p->fd_buddy[j] = -1;
637 /* At the initial call of os_init, we got -1, 0, 0, 0, ... */
638 if (next < 0)
639 {
0242f9ea 640 p->fd_buddy[i] = -1;
594ee3a7
JR
641 do_close = 0;
642 break;
643 }
644 }
645 while (j != i);
646 if (do_close)
c906108c 647 close (p->fdmap[i]);
c906108c
SS
648 }
649 return 1;
650}
651
652static int
1a8a700e 653os_init (host_callback *p)
c906108c
SS
654{
655 int i;
656
657 os_shutdown (p);
658 for (i = 0; i < 3; i++)
659 {
660 p->fdmap[i] = i;
594ee3a7 661 p->fd_buddy[i] = i - 1;
c906108c 662 }
594ee3a7
JR
663 p->fd_buddy[0] = MAX_CALLBACK_FDS;
664 p->fd_buddy[MAX_CALLBACK_FDS] = 2;
c906108c
SS
665
666 p->syscall_map = cb_init_syscall_map;
667 p->errno_map = cb_init_errno_map;
cc40b4f2 668 p->signal_map = cb_init_signal_map;
c906108c
SS
669 p->open_map = cb_init_open_map;
670
671 return 1;
672}
673
5accf1ff 674/* DEPRECATED */
c906108c
SS
675
676/* VARARGS */
2f632133 677static void ATTRIBUTE_PRINTF (2, 3)
6d358e86 678os_printf_filtered (host_callback *p ATTRIBUTE_UNUSED, const char *format, ...)
c906108c
SS
679{
680 va_list args;
c906108c 681 va_start (args, format);
c906108c
SS
682
683 vfprintf (stdout, format, args);
684 va_end (args);
685}
686
687/* VARARGS */
2f632133 688static void ATTRIBUTE_PRINTF (2, 0)
6d358e86 689os_vprintf_filtered (host_callback *p ATTRIBUTE_UNUSED, const char *format, va_list args)
c906108c
SS
690{
691 vprintf (format, args);
692}
693
694/* VARARGS */
2f632133 695static void ATTRIBUTE_PRINTF (2, 0)
6d358e86 696os_evprintf_filtered (host_callback *p ATTRIBUTE_UNUSED, const char *format, va_list args)
c906108c
SS
697{
698 vfprintf (stderr, format, args);
699}
700
701/* VARARGS */
f0c4dc40 702static void ATTRIBUTE_PRINTF (2, 3) ATTRIBUTE_NORETURN
6d358e86 703os_error (host_callback *p ATTRIBUTE_UNUSED, const char *format, ...)
c906108c
SS
704{
705 va_list args;
c906108c 706 va_start (args, format);
c906108c
SS
707
708 vfprintf (stderr, format, args);
709 fprintf (stderr, "\n");
710
711 va_end (args);
712 exit (1);
713}
714
715host_callback default_callback =
716{
717 os_close,
718 os_get_errno,
719 os_isatty,
720 os_lseek,
721 os_open,
722 os_read,
723 os_read_stdin,
724 os_rename,
725 os_system,
726 os_time,
727 os_unlink,
728 os_write,
729 os_write_stdout,
730 os_flush_stdout,
731 os_write_stderr,
732 os_flush_stderr,
733
734 os_stat,
735 os_fstat,
0d3cd463 736 os_lstat,
c906108c 737
8822d001
JR
738 os_ftruncate,
739 os_truncate,
740
c45cffdb 741 os_getpid,
d394a6ef 742 os_kill,
c45cffdb 743
97f669ed
HPN
744 os_pipe,
745 os_pipe_empty,
746 os_pipe_nonempty,
747
c906108c
SS
748 os_poll_quit,
749
750 os_shutdown,
751 os_init,
752
753 os_printf_filtered, /* deprecated */
754
755 os_vprintf_filtered,
756 os_evprintf_filtered,
757 os_error,
758
759 0, /* last errno */
760
761 { 0, }, /* fdmap */
594ee3a7 762 { -1, }, /* fd_buddy */
97f669ed
HPN
763 { 0, }, /* ispipe */
764 { { 0, 0 }, }, /* pipe_buffer */
c906108c
SS
765
766 0, /* syscall_map */
767 0, /* errno_map */
768 0, /* open_map */
769 0, /* signal_map */
770 0, /* stat_map */
028f6515 771
f4f8cce4
HPN
772 /* Defaults expected to be overridden at initialization, where needed. */
773 BFD_ENDIAN_UNKNOWN, /* target_endian */
97f669ed 774 4, /* target_sizeof_int */
f4f8cce4 775
c906108c
SS
776 HOST_CALLBACK_MAGIC,
777};
778\f
779/* Read in a file describing the target's system call values.
780 E.g. maybe someone will want to use something other than newlib.
781 This assumes that the basic system call recognition and value passing/
782 returning is supported. So maybe some coding/recompilation will be
783 necessary, but not as much.
784
785 If an error occurs, the existing mapping is not changed. */
786
787CB_RC
1a8a700e 788cb_read_target_syscall_maps (host_callback *cb, const char *file)
c906108c
SS
789{
790 CB_TARGET_DEFS_MAP *syscall_map, *errno_map, *open_map, *signal_map;
791 const char *stat_map;
792 FILE *f;
793
794 if ((f = fopen (file, "r")) == NULL)
795 return CB_RC_ACCESS;
796
797 /* ... read in and parse file ... */
798
799 fclose (f);
800 return CB_RC_NO_MEM; /* FIXME:wip */
801
802 /* Free storage allocated for any existing maps. */
803 if (cb->syscall_map)
804 free (cb->syscall_map);
805 if (cb->errno_map)
806 free (cb->errno_map);
807 if (cb->open_map)
808 free (cb->open_map);
809 if (cb->signal_map)
810 free (cb->signal_map);
811 if (cb->stat_map)
812 free ((PTR) cb->stat_map);
813
814 cb->syscall_map = syscall_map;
815 cb->errno_map = errno_map;
816 cb->open_map = open_map;
817 cb->signal_map = signal_map;
818 cb->stat_map = stat_map;
819
820 return CB_RC_OK;
821}
822
6362a3f8
MF
823/* General utility functions to search a map for a value. */
824
825static const CB_TARGET_DEFS_MAP *
826cb_target_map_entry (const CB_TARGET_DEFS_MAP map[], int target_val)
827{
828 const CB_TARGET_DEFS_MAP *m;
829
7aec3bb9 830 for (m = &map[0]; m->target_val != -1; ++m)
6362a3f8
MF
831 if (m->target_val == target_val)
832 return m;
833
834 return NULL;
835}
836
837static const CB_TARGET_DEFS_MAP *
838cb_host_map_entry (const CB_TARGET_DEFS_MAP map[], int host_val)
839{
840 const CB_TARGET_DEFS_MAP *m;
841
7aec3bb9 842 for (m = &map[0]; m->host_val != -1; ++m)
6362a3f8
MF
843 if (m->host_val == host_val)
844 return m;
845
846 return NULL;
847}
848
c906108c
SS
849/* Translate the target's version of a syscall number to the host's.
850 This isn't actually the host's version, rather a canonical form.
851 ??? Perhaps this should be renamed to ..._canon_syscall. */
852
853int
1a8a700e 854cb_target_to_host_syscall (host_callback *cb, int target_val)
c906108c 855{
6362a3f8
MF
856 const CB_TARGET_DEFS_MAP *m =
857 cb_target_map_entry (cb->syscall_map, target_val);
c906108c 858
6362a3f8 859 return m ? m->host_val : -1;
c906108c
SS
860}
861
862/* FIXME: sort tables if large.
863 Alternatively, an obvious improvement for errno conversion is
864 to machine generate a function with a large switch(). */
865
866/* Translate the host's version of errno to the target's. */
867
868int
1a8a700e 869cb_host_to_target_errno (host_callback *cb, int host_val)
c906108c 870{
6362a3f8 871 const CB_TARGET_DEFS_MAP *m = cb_host_map_entry (cb->errno_map, host_val);
c906108c
SS
872
873 /* ??? Which error to return in this case is up for grabs.
874 Note that some missing values may have standard alternatives.
875 For now return 0 and require caller to deal with it. */
6362a3f8 876 return m ? m->target_val : 0;
c906108c
SS
877}
878
879/* Given a set of target bitmasks for the open system call,
880 return the host equivalent.
881 Mapping open flag values is best done by looping so there's no need
882 to machine generate this function. */
883
884int
1a8a700e 885cb_target_to_host_open (host_callback *cb, int target_val)
c906108c
SS
886{
887 int host_val = 0;
888 CB_TARGET_DEFS_MAP *m;
889
890 for (m = &cb->open_map[0]; m->host_val != -1; ++m)
891 {
892 switch (m->target_val)
893 {
894 /* O_RDONLY can be (and usually is) 0 which needs to be treated
895 specially. */
896 case TARGET_O_RDONLY :
897 case TARGET_O_WRONLY :
898 case TARGET_O_RDWR :
899 if ((target_val & (TARGET_O_RDONLY | TARGET_O_WRONLY | TARGET_O_RDWR))
900 == m->target_val)
901 host_val |= m->host_val;
902 /* Handle the host/target differentiating between binary and
903 text mode. Only one case is of importance */
904#if ! defined (TARGET_O_BINARY) && defined (O_BINARY)
905 host_val |= O_BINARY;
906#endif
907 break;
908 default :
909 if ((m->target_val & target_val) == m->target_val)
910 host_val |= m->host_val;
911 break;
912 }
913 }
914
915 return host_val;
916}
917
13b0d6e5
MF
918/* Translate the target's version of a signal number to the host's.
919 This isn't actually the host's version, rather a canonical form.
920 ??? Perhaps this should be renamed to ..._canon_signal. */
921
922int
923cb_target_to_host_signal (host_callback *cb, int target_val)
924{
925 const CB_TARGET_DEFS_MAP *m =
926 cb_target_map_entry (cb->signal_map, target_val);
927
928 return m ? m->host_val : -1;
929}
930
f4f8cce4 931/* Utility for e.g. cb_host_to_target_stat to store values in the target's
1a8a700e
MF
932 stat struct.
933
934 ??? The "val" must be as big as target word size. */
c906108c 935
f4f8cce4 936void
1a8a700e 937cb_store_target_endian (host_callback *cb, char *p, int size, long val)
c906108c 938{
f4f8cce4 939 if (cb->target_endian == BFD_ENDIAN_BIG)
c906108c
SS
940 {
941 p += size;
942 while (size-- > 0)
943 {
944 *--p = val;
945 val >>= 8;
946 }
947 }
948 else
949 {
950 while (size-- > 0)
951 {
952 *p++ = val;
953 val >>= 8;
954 }
955 }
956}
957
958/* Translate a host's stat struct into a target's.
959 If HS is NULL, just compute the length of the buffer required,
960 TS is ignored.
961
962 The result is the size of the target's stat struct,
6439295f 963 or zero if an error occurred during the translation. */
c906108c
SS
964
965int
64654371 966cb_host_to_target_stat (host_callback *cb, const struct stat *hs, void *ts)
c906108c
SS
967{
968 const char *m = cb->stat_map;
969 char *p;
c906108c
SS
970
971 if (hs == NULL)
972 ts = NULL;
973 p = ts;
974
975 while (m)
976 {
977 char *q = strchr (m, ',');
978 int size;
979
980 /* FIXME: Use sscanf? */
981 if (q == NULL)
982 {
983 /* FIXME: print error message */
984 return 0;
985 }
986 size = atoi (q + 1);
987 if (size == 0)
988 {
989 /* FIXME: print error message */
990 return 0;
991 }
992
993 if (hs != NULL)
994 {
e1591da4 995 if (0)
697afb65
HPN
996 ;
997 /* Defined here to avoid emacs indigestion on a lone "else". */
998#undef ST_x
999#define ST_x(FLD) \
1000 else if (strncmp (m, #FLD, q - m) == 0) \
f4f8cce4 1001 cb_store_target_endian (cb, p, size, hs->FLD)
697afb65
HPN
1002
1003#ifdef HAVE_STRUCT_STAT_ST_DEV
1004 ST_x (st_dev);
1005#endif
1006#ifdef HAVE_STRUCT_STAT_ST_INO
1007 ST_x (st_ino);
1008#endif
1009#ifdef HAVE_STRUCT_STAT_ST_MODE
1010 ST_x (st_mode);
1011#endif
1012#ifdef HAVE_STRUCT_STAT_ST_NLINK
1013 ST_x (st_nlink);
1014#endif
1015#ifdef HAVE_STRUCT_STAT_ST_UID
1016 ST_x (st_uid);
1017#endif
1018#ifdef HAVE_STRUCT_STAT_ST_GID
1019 ST_x (st_gid);
1020#endif
1021#ifdef HAVE_STRUCT_STAT_ST_RDEV
1022 ST_x (st_rdev);
1023#endif
1024#ifdef HAVE_STRUCT_STAT_ST_SIZE
1025 ST_x (st_size);
1026#endif
1027#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
1028 ST_x (st_blksize);
1029#endif
1030#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
1031 ST_x (st_blocks);
1032#endif
1033#ifdef HAVE_STRUCT_STAT_ST_ATIME
1034 ST_x (st_atime);
1035#endif
1036#ifdef HAVE_STRUCT_STAT_ST_MTIME
1037 ST_x (st_mtime);
1038#endif
1039#ifdef HAVE_STRUCT_STAT_ST_CTIME
1040 ST_x (st_ctime);
1041#endif
1042#undef ST_x
c906108c
SS
1043 /* FIXME:wip */
1044 else
f4f8cce4
HPN
1045 /* Unsupported field, store 0. */
1046 cb_store_target_endian (cb, p, size, 0);
c906108c
SS
1047 }
1048
1049 p += size;
1050 m = strchr (q, ':');
1051 if (m)
1052 ++m;
1053 }
1054
1055 return p - (char *) ts;
1056}
1057\f
b981d709
DJ
1058int
1059cb_is_stdin (host_callback *cb, int fd)
1060{
1061 return fdbad (cb, fd) ? 0 : fdmap (cb, fd) == 0;
1062}
1063
eb639c50
DJ
1064int
1065cb_is_stdout (host_callback *cb, int fd)
1066{
1067 return fdbad (cb, fd) ? 0 : fdmap (cb, fd) == 1;
1068}
1069
1070int
1071cb_is_stderr (host_callback *cb, int fd)
1072{
1073 return fdbad (cb, fd) ? 0 : fdmap (cb, fd) == 2;
1074}
6362a3f8
MF
1075\f
1076const char *
1077cb_host_str_syscall (host_callback *cb, int host_val)
1078{
1079 const CB_TARGET_DEFS_MAP *m = cb_host_map_entry (cb->syscall_map, host_val);
1080
1081 return m ? m->name : NULL;
1082}
1083
1084const char *
1085cb_host_str_errno (host_callback *cb, int host_val)
1086{
1087 const CB_TARGET_DEFS_MAP *m = cb_host_map_entry (cb->errno_map, host_val);
1088
1089 return m ? m->name : NULL;
1090}
1091
1092const char *
1093cb_host_str_signal (host_callback *cb, int host_val)
1094{
1095 const CB_TARGET_DEFS_MAP *m = cb_host_map_entry (cb->signal_map, host_val);
1096
1097 return m ? m->name : NULL;
1098}
1099
1100const char *
1101cb_target_str_syscall (host_callback *cb, int target_val)
1102{
1103 const CB_TARGET_DEFS_MAP *m =
1104 cb_target_map_entry (cb->syscall_map, target_val);
1105
1106 return m ? m->name : NULL;
1107}
1108
1109const char *
1110cb_target_str_errno (host_callback *cb, int target_val)
1111{
1112 const CB_TARGET_DEFS_MAP *m =
1113 cb_target_map_entry (cb->errno_map, target_val);
1114
1115 return m ? m->name : NULL;
1116}
1117
1118const char *
1119cb_target_str_signal (host_callback *cb, int target_val)
1120{
1121 const CB_TARGET_DEFS_MAP *m =
1122 cb_target_map_entry (cb->signal_map, target_val);
1123
1124 return m ? m->name : NULL;
1125}
This page took 1.13863 seconds and 4 git commands to generate.