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