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