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