Commit | Line | Data |
---|---|---|
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 | ||
23 | #ifdef HAVE_CONFIG_H | |
a6ff997c | 24 | #include "config.h" |
936df756 | 25 | #endif |
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> | |
3c25f8c7 | 38 | #include "gdb/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 |
54 | void sim_cb_printf (host_callback *, const char *, ...); |
55 | void sim_cb_eprintf (host_callback *, const char *, ...); | |
c906108c SS |
56 | |
57 | extern CB_TARGET_DEFS_MAP cb_init_syscall_map[]; | |
58 | extern CB_TARGET_DEFS_MAP cb_init_errno_map[]; | |
59 | extern 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 | 64 | static int |
1a8a700e | 65 | fdbad (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 | 75 | static int |
1a8a700e | 76 | fdmap (host_callback *p, int fd) |
c906108c SS |
77 | { |
78 | return p->fdmap[fd]; | |
79 | } | |
80 | ||
028f6515 | 81 | static int |
1a8a700e | 82 | os_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) | |
150 | static int | |
1a8a700e | 151 | os_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 | 187 | static int |
1a8a700e | 188 | os_get_errno (host_callback *p) |
c906108c SS |
189 | { |
190 | return cb_host_to_target_errno (p, p->last_errno); | |
191 | } | |
192 | ||
193 | ||
028f6515 | 194 | static int |
1a8a700e | 195 | os_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 | ||
028f6515 | 208 | static int |
1a8a700e | 209 | os_lseek (host_callback *p, int fd, long off, int way) |
c906108c SS |
210 | { |
211 | int result; | |
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 | 222 | static int |
1a8a700e | 223 | os_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 | 245 | static int |
1a8a700e | 246 | os_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 | 299 | static int |
1a8a700e | 300 | os_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 | 309 | static int |
1a8a700e | 310 | os_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 | 378 | static int |
1a8a700e | 379 | os_write_stdout (host_callback *p ATTRIBUTE_UNUSED, const char *buf, int len) |
c906108c SS |
380 | { |
381 | return fwrite (buf, 1, len, stdout); | |
382 | } | |
383 | ||
384 | static void | |
1a8a700e | 385 | os_flush_stdout (host_callback *p ATTRIBUTE_UNUSED) |
c906108c SS |
386 | { |
387 | fflush (stdout); | |
388 | } | |
389 | ||
028f6515 | 390 | static int |
1a8a700e | 391 | os_write_stderr (host_callback *p ATTRIBUTE_UNUSED, const char *buf, int len) |
c906108c SS |
392 | { |
393 | return fwrite (buf, 1, len, stderr); | |
394 | } | |
395 | ||
396 | static void | |
1a8a700e | 397 | os_flush_stderr (host_callback *p ATTRIBUTE_UNUSED) |
c906108c SS |
398 | { |
399 | fflush (stderr); | |
400 | } | |
401 | ||
028f6515 | 402 | static int |
1a8a700e | 403 | os_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 | ||
413 | static int | |
1a8a700e | 414 | os_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 | ||
028f6515 | 423 | static long |
1a8a700e | 424 | os_time (host_callback *p, long *t) |
c906108c | 425 | { |
ccf2e592 MF |
426 | long result; |
427 | ||
428 | result = time (t); | |
429 | p->last_errno = errno; | |
430 | return result; | |
c906108c SS |
431 | } |
432 | ||
433 | ||
028f6515 | 434 | static int |
1a8a700e | 435 | os_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 | ||
444 | static int | |
1a8a700e | 445 | os_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 | ||
458 | static int | |
1a8a700e | 459 | os_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) |
97f669ed | 469 | time_t t = (*p->time) (p, NULL); |
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 | 506 | static int |
1a8a700e | 507 | os_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 | 521 | static int |
1a8a700e | 522 | os_ftruncate (host_callback *p, int fd, long 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 | ||
544 | static int | |
1a8a700e | 545 | os_truncate (host_callback *p, const char *file, long 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 | ||
97f669ed | 559 | static int |
1a8a700e | 560 | os_pipe (host_callback *p, int *filedes) |
97f669ed HPN |
561 | { |
562 | int i; | |
563 | ||
564 | /* We deliberately don't use fd 0. It's probably stdin anyway. */ | |
565 | for (i = 1; i < MAX_CALLBACK_FDS; i++) | |
566 | { | |
567 | int j; | |
568 | ||
569 | if (p->fd_buddy[i] < 0) | |
570 | for (j = i + 1; j < MAX_CALLBACK_FDS; j++) | |
571 | if (p->fd_buddy[j] < 0) | |
572 | { | |
573 | /* Found two free fd:s. Set stat to allocated and mark | |
574 | pipeness. */ | |
575 | p->fd_buddy[i] = i; | |
576 | p->fd_buddy[j] = j; | |
577 | p->ispipe[i] = j; | |
578 | p->ispipe[j] = -i; | |
579 | filedes[0] = i; | |
580 | filedes[1] = j; | |
581 | ||
582 | /* Poison the FD map to make bugs apparent. */ | |
583 | p->fdmap[i] = -1; | |
584 | p->fdmap[j] = -1; | |
585 | return 0; | |
586 | } | |
587 | } | |
588 | ||
589 | p->last_errno = EMFILE; | |
590 | return -1; | |
591 | } | |
592 | ||
593 | /* Stub functions for pipe support. They should always be overridden in | |
594 | targets using the pipe support, but that's up to the target. */ | |
595 | ||
596 | /* Called when the simulator says that the pipe at (reader, writer) is | |
597 | now empty (so the writer should leave its waiting state). */ | |
598 | ||
599 | static void | |
1a8a700e | 600 | os_pipe_empty (host_callback *p, int reader, int writer) |
97f669ed HPN |
601 | { |
602 | } | |
603 | ||
604 | /* Called when the simulator says the pipe at (reader, writer) is now | |
605 | non-empty (so the writer should wait). */ | |
606 | ||
607 | static void | |
1a8a700e | 608 | os_pipe_nonempty (host_callback *p, int reader, int writer) |
97f669ed HPN |
609 | { |
610 | } | |
611 | ||
c906108c | 612 | static int |
1a8a700e | 613 | os_shutdown (host_callback *p) |
c906108c | 614 | { |
594ee3a7 | 615 | int i, next, j; |
c906108c SS |
616 | for (i = 0; i < MAX_CALLBACK_FDS; i++) |
617 | { | |
594ee3a7 JR |
618 | int do_close = 1; |
619 | ||
97f669ed HPN |
620 | /* Zero out all pipe state. Don't call callbacks for non-empty |
621 | pipes; the target program has likely terminated at this point | |
622 | or we're called at initialization time. */ | |
623 | p->ispipe[i] = 0; | |
624 | p->pipe_buffer[i].size = 0; | |
625 | p->pipe_buffer[i].buffer = NULL; | |
626 | ||
594ee3a7 JR |
627 | next = p->fd_buddy[i]; |
628 | if (next < 0) | |
629 | continue; | |
630 | do | |
631 | { | |
632 | j = next; | |
633 | if (j == MAX_CALLBACK_FDS) | |
634 | do_close = 0; | |
635 | next = p->fd_buddy[j]; | |
636 | p->fd_buddy[j] = -1; | |
637 | /* At the initial call of os_init, we got -1, 0, 0, 0, ... */ | |
638 | if (next < 0) | |
639 | { | |
0242f9ea | 640 | p->fd_buddy[i] = -1; |
594ee3a7 JR |
641 | do_close = 0; |
642 | break; | |
643 | } | |
644 | } | |
645 | while (j != i); | |
646 | if (do_close) | |
c906108c | 647 | close (p->fdmap[i]); |
c906108c SS |
648 | } |
649 | return 1; | |
650 | } | |
651 | ||
652 | static int | |
1a8a700e | 653 | os_init (host_callback *p) |
c906108c SS |
654 | { |
655 | int i; | |
656 | ||
657 | os_shutdown (p); | |
658 | for (i = 0; i < 3; i++) | |
659 | { | |
660 | p->fdmap[i] = i; | |
594ee3a7 | 661 | p->fd_buddy[i] = i - 1; |
c906108c | 662 | } |
594ee3a7 JR |
663 | p->fd_buddy[0] = MAX_CALLBACK_FDS; |
664 | p->fd_buddy[MAX_CALLBACK_FDS] = 2; | |
c906108c SS |
665 | |
666 | p->syscall_map = cb_init_syscall_map; | |
667 | p->errno_map = cb_init_errno_map; | |
668 | p->open_map = cb_init_open_map; | |
669 | ||
670 | return 1; | |
671 | } | |
672 | ||
5accf1ff | 673 | /* DEPRECATED */ |
c906108c SS |
674 | |
675 | /* VARARGS */ | |
2f632133 | 676 | static void ATTRIBUTE_PRINTF (2, 3) |
6d358e86 | 677 | os_printf_filtered (host_callback *p ATTRIBUTE_UNUSED, const char *format, ...) |
c906108c SS |
678 | { |
679 | va_list args; | |
c906108c | 680 | va_start (args, format); |
c906108c SS |
681 | |
682 | vfprintf (stdout, format, args); | |
683 | va_end (args); | |
684 | } | |
685 | ||
686 | /* VARARGS */ | |
2f632133 | 687 | static void ATTRIBUTE_PRINTF (2, 0) |
6d358e86 | 688 | os_vprintf_filtered (host_callback *p ATTRIBUTE_UNUSED, const char *format, va_list args) |
c906108c SS |
689 | { |
690 | vprintf (format, args); | |
691 | } | |
692 | ||
693 | /* VARARGS */ | |
2f632133 | 694 | static void ATTRIBUTE_PRINTF (2, 0) |
6d358e86 | 695 | os_evprintf_filtered (host_callback *p ATTRIBUTE_UNUSED, const char *format, va_list args) |
c906108c SS |
696 | { |
697 | vfprintf (stderr, format, args); | |
698 | } | |
699 | ||
700 | /* VARARGS */ | |
f0c4dc40 | 701 | static void ATTRIBUTE_PRINTF (2, 3) ATTRIBUTE_NORETURN |
6d358e86 | 702 | os_error (host_callback *p ATTRIBUTE_UNUSED, const char *format, ...) |
c906108c SS |
703 | { |
704 | va_list args; | |
c906108c | 705 | va_start (args, format); |
c906108c SS |
706 | |
707 | vfprintf (stderr, format, args); | |
708 | fprintf (stderr, "\n"); | |
709 | ||
710 | va_end (args); | |
711 | exit (1); | |
712 | } | |
713 | ||
714 | host_callback default_callback = | |
715 | { | |
716 | os_close, | |
717 | os_get_errno, | |
718 | os_isatty, | |
719 | os_lseek, | |
720 | os_open, | |
721 | os_read, | |
722 | os_read_stdin, | |
723 | os_rename, | |
724 | os_system, | |
725 | os_time, | |
726 | os_unlink, | |
727 | os_write, | |
728 | os_write_stdout, | |
729 | os_flush_stdout, | |
730 | os_write_stderr, | |
731 | os_flush_stderr, | |
732 | ||
733 | os_stat, | |
734 | os_fstat, | |
0d3cd463 | 735 | os_lstat, |
c906108c | 736 | |
8822d001 JR |
737 | os_ftruncate, |
738 | os_truncate, | |
739 | ||
97f669ed HPN |
740 | os_pipe, |
741 | os_pipe_empty, | |
742 | os_pipe_nonempty, | |
743 | ||
c906108c SS |
744 | os_poll_quit, |
745 | ||
746 | os_shutdown, | |
747 | os_init, | |
748 | ||
749 | os_printf_filtered, /* deprecated */ | |
750 | ||
751 | os_vprintf_filtered, | |
752 | os_evprintf_filtered, | |
753 | os_error, | |
754 | ||
755 | 0, /* last errno */ | |
756 | ||
757 | { 0, }, /* fdmap */ | |
594ee3a7 | 758 | { -1, }, /* fd_buddy */ |
97f669ed HPN |
759 | { 0, }, /* ispipe */ |
760 | { { 0, 0 }, }, /* pipe_buffer */ | |
c906108c SS |
761 | |
762 | 0, /* syscall_map */ | |
763 | 0, /* errno_map */ | |
764 | 0, /* open_map */ | |
765 | 0, /* signal_map */ | |
766 | 0, /* stat_map */ | |
028f6515 | 767 | |
f4f8cce4 HPN |
768 | /* Defaults expected to be overridden at initialization, where needed. */ |
769 | BFD_ENDIAN_UNKNOWN, /* target_endian */ | |
97f669ed | 770 | 4, /* target_sizeof_int */ |
f4f8cce4 | 771 | |
c906108c SS |
772 | HOST_CALLBACK_MAGIC, |
773 | }; | |
774 | \f | |
775 | /* Read in a file describing the target's system call values. | |
776 | E.g. maybe someone will want to use something other than newlib. | |
777 | This assumes that the basic system call recognition and value passing/ | |
778 | returning is supported. So maybe some coding/recompilation will be | |
779 | necessary, but not as much. | |
780 | ||
781 | If an error occurs, the existing mapping is not changed. */ | |
782 | ||
783 | CB_RC | |
1a8a700e | 784 | cb_read_target_syscall_maps (host_callback *cb, const char *file) |
c906108c SS |
785 | { |
786 | CB_TARGET_DEFS_MAP *syscall_map, *errno_map, *open_map, *signal_map; | |
787 | const char *stat_map; | |
788 | FILE *f; | |
789 | ||
790 | if ((f = fopen (file, "r")) == NULL) | |
791 | return CB_RC_ACCESS; | |
792 | ||
793 | /* ... read in and parse file ... */ | |
794 | ||
795 | fclose (f); | |
796 | return CB_RC_NO_MEM; /* FIXME:wip */ | |
797 | ||
798 | /* Free storage allocated for any existing maps. */ | |
799 | if (cb->syscall_map) | |
800 | free (cb->syscall_map); | |
801 | if (cb->errno_map) | |
802 | free (cb->errno_map); | |
803 | if (cb->open_map) | |
804 | free (cb->open_map); | |
805 | if (cb->signal_map) | |
806 | free (cb->signal_map); | |
807 | if (cb->stat_map) | |
808 | free ((PTR) cb->stat_map); | |
809 | ||
810 | cb->syscall_map = syscall_map; | |
811 | cb->errno_map = errno_map; | |
812 | cb->open_map = open_map; | |
813 | cb->signal_map = signal_map; | |
814 | cb->stat_map = stat_map; | |
815 | ||
816 | return CB_RC_OK; | |
817 | } | |
818 | ||
6362a3f8 MF |
819 | /* General utility functions to search a map for a value. */ |
820 | ||
821 | static const CB_TARGET_DEFS_MAP * | |
822 | cb_target_map_entry (const CB_TARGET_DEFS_MAP map[], int target_val) | |
823 | { | |
824 | const CB_TARGET_DEFS_MAP *m; | |
825 | ||
7aec3bb9 | 826 | for (m = &map[0]; m->target_val != -1; ++m) |
6362a3f8 MF |
827 | if (m->target_val == target_val) |
828 | return m; | |
829 | ||
830 | return NULL; | |
831 | } | |
832 | ||
833 | static const CB_TARGET_DEFS_MAP * | |
834 | cb_host_map_entry (const CB_TARGET_DEFS_MAP map[], int host_val) | |
835 | { | |
836 | const CB_TARGET_DEFS_MAP *m; | |
837 | ||
7aec3bb9 | 838 | for (m = &map[0]; m->host_val != -1; ++m) |
6362a3f8 MF |
839 | if (m->host_val == host_val) |
840 | return m; | |
841 | ||
842 | return NULL; | |
843 | } | |
844 | ||
c906108c SS |
845 | /* Translate the target's version of a syscall number to the host's. |
846 | This isn't actually the host's version, rather a canonical form. | |
847 | ??? Perhaps this should be renamed to ..._canon_syscall. */ | |
848 | ||
849 | int | |
1a8a700e | 850 | cb_target_to_host_syscall (host_callback *cb, int target_val) |
c906108c | 851 | { |
6362a3f8 MF |
852 | const CB_TARGET_DEFS_MAP *m = |
853 | cb_target_map_entry (cb->syscall_map, target_val); | |
c906108c | 854 | |
6362a3f8 | 855 | return m ? m->host_val : -1; |
c906108c SS |
856 | } |
857 | ||
858 | /* FIXME: sort tables if large. | |
859 | Alternatively, an obvious improvement for errno conversion is | |
860 | to machine generate a function with a large switch(). */ | |
861 | ||
862 | /* Translate the host's version of errno to the target's. */ | |
863 | ||
864 | int | |
1a8a700e | 865 | cb_host_to_target_errno (host_callback *cb, int host_val) |
c906108c | 866 | { |
6362a3f8 | 867 | const CB_TARGET_DEFS_MAP *m = cb_host_map_entry (cb->errno_map, host_val); |
c906108c SS |
868 | |
869 | /* ??? Which error to return in this case is up for grabs. | |
870 | Note that some missing values may have standard alternatives. | |
871 | For now return 0 and require caller to deal with it. */ | |
6362a3f8 | 872 | return m ? m->target_val : 0; |
c906108c SS |
873 | } |
874 | ||
875 | /* Given a set of target bitmasks for the open system call, | |
876 | return the host equivalent. | |
877 | Mapping open flag values is best done by looping so there's no need | |
878 | to machine generate this function. */ | |
879 | ||
880 | int | |
1a8a700e | 881 | cb_target_to_host_open (host_callback *cb, int target_val) |
c906108c SS |
882 | { |
883 | int host_val = 0; | |
884 | CB_TARGET_DEFS_MAP *m; | |
885 | ||
886 | for (m = &cb->open_map[0]; m->host_val != -1; ++m) | |
887 | { | |
888 | switch (m->target_val) | |
889 | { | |
890 | /* O_RDONLY can be (and usually is) 0 which needs to be treated | |
891 | specially. */ | |
892 | case TARGET_O_RDONLY : | |
893 | case TARGET_O_WRONLY : | |
894 | case TARGET_O_RDWR : | |
895 | if ((target_val & (TARGET_O_RDONLY | TARGET_O_WRONLY | TARGET_O_RDWR)) | |
896 | == m->target_val) | |
897 | host_val |= m->host_val; | |
898 | /* Handle the host/target differentiating between binary and | |
899 | text mode. Only one case is of importance */ | |
900 | #if ! defined (TARGET_O_BINARY) && defined (O_BINARY) | |
901 | host_val |= O_BINARY; | |
902 | #endif | |
903 | break; | |
904 | default : | |
905 | if ((m->target_val & target_val) == m->target_val) | |
906 | host_val |= m->host_val; | |
907 | break; | |
908 | } | |
909 | } | |
910 | ||
911 | return host_val; | |
912 | } | |
913 | ||
f4f8cce4 | 914 | /* Utility for e.g. cb_host_to_target_stat to store values in the target's |
1a8a700e MF |
915 | stat struct. |
916 | ||
917 | ??? The "val" must be as big as target word size. */ | |
c906108c | 918 | |
f4f8cce4 | 919 | void |
1a8a700e | 920 | cb_store_target_endian (host_callback *cb, char *p, int size, long val) |
c906108c | 921 | { |
f4f8cce4 | 922 | if (cb->target_endian == BFD_ENDIAN_BIG) |
c906108c SS |
923 | { |
924 | p += size; | |
925 | while (size-- > 0) | |
926 | { | |
927 | *--p = val; | |
928 | val >>= 8; | |
929 | } | |
930 | } | |
931 | else | |
932 | { | |
933 | while (size-- > 0) | |
934 | { | |
935 | *p++ = val; | |
936 | val >>= 8; | |
937 | } | |
938 | } | |
939 | } | |
940 | ||
941 | /* Translate a host's stat struct into a target's. | |
942 | If HS is NULL, just compute the length of the buffer required, | |
943 | TS is ignored. | |
944 | ||
945 | The result is the size of the target's stat struct, | |
6439295f | 946 | or zero if an error occurred during the translation. */ |
c906108c SS |
947 | |
948 | int | |
1a8a700e | 949 | cb_host_to_target_stat (host_callback *cb, const struct stat *hs, PTR ts) |
c906108c SS |
950 | { |
951 | const char *m = cb->stat_map; | |
952 | char *p; | |
c906108c SS |
953 | |
954 | if (hs == NULL) | |
955 | ts = NULL; | |
956 | p = ts; | |
957 | ||
958 | while (m) | |
959 | { | |
960 | char *q = strchr (m, ','); | |
961 | int size; | |
962 | ||
963 | /* FIXME: Use sscanf? */ | |
964 | if (q == NULL) | |
965 | { | |
966 | /* FIXME: print error message */ | |
967 | return 0; | |
968 | } | |
969 | size = atoi (q + 1); | |
970 | if (size == 0) | |
971 | { | |
972 | /* FIXME: print error message */ | |
973 | return 0; | |
974 | } | |
975 | ||
976 | if (hs != NULL) | |
977 | { | |
e1591da4 | 978 | if (0) |
697afb65 HPN |
979 | ; |
980 | /* Defined here to avoid emacs indigestion on a lone "else". */ | |
981 | #undef ST_x | |
982 | #define ST_x(FLD) \ | |
983 | else if (strncmp (m, #FLD, q - m) == 0) \ | |
f4f8cce4 | 984 | cb_store_target_endian (cb, p, size, hs->FLD) |
697afb65 HPN |
985 | |
986 | #ifdef HAVE_STRUCT_STAT_ST_DEV | |
987 | ST_x (st_dev); | |
988 | #endif | |
989 | #ifdef HAVE_STRUCT_STAT_ST_INO | |
990 | ST_x (st_ino); | |
991 | #endif | |
992 | #ifdef HAVE_STRUCT_STAT_ST_MODE | |
993 | ST_x (st_mode); | |
994 | #endif | |
995 | #ifdef HAVE_STRUCT_STAT_ST_NLINK | |
996 | ST_x (st_nlink); | |
997 | #endif | |
998 | #ifdef HAVE_STRUCT_STAT_ST_UID | |
999 | ST_x (st_uid); | |
1000 | #endif | |
1001 | #ifdef HAVE_STRUCT_STAT_ST_GID | |
1002 | ST_x (st_gid); | |
1003 | #endif | |
1004 | #ifdef HAVE_STRUCT_STAT_ST_RDEV | |
1005 | ST_x (st_rdev); | |
1006 | #endif | |
1007 | #ifdef HAVE_STRUCT_STAT_ST_SIZE | |
1008 | ST_x (st_size); | |
1009 | #endif | |
1010 | #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE | |
1011 | ST_x (st_blksize); | |
1012 | #endif | |
1013 | #ifdef HAVE_STRUCT_STAT_ST_BLOCKS | |
1014 | ST_x (st_blocks); | |
1015 | #endif | |
1016 | #ifdef HAVE_STRUCT_STAT_ST_ATIME | |
1017 | ST_x (st_atime); | |
1018 | #endif | |
1019 | #ifdef HAVE_STRUCT_STAT_ST_MTIME | |
1020 | ST_x (st_mtime); | |
1021 | #endif | |
1022 | #ifdef HAVE_STRUCT_STAT_ST_CTIME | |
1023 | ST_x (st_ctime); | |
1024 | #endif | |
1025 | #undef ST_x | |
c906108c SS |
1026 | /* FIXME:wip */ |
1027 | else | |
f4f8cce4 HPN |
1028 | /* Unsupported field, store 0. */ |
1029 | cb_store_target_endian (cb, p, size, 0); | |
c906108c SS |
1030 | } |
1031 | ||
1032 | p += size; | |
1033 | m = strchr (q, ':'); | |
1034 | if (m) | |
1035 | ++m; | |
1036 | } | |
1037 | ||
1038 | return p - (char *) ts; | |
1039 | } | |
1040 | \f | |
1041 | /* Cover functions to the vfprintf callbacks. | |
1042 | ||
1043 | ??? If one thinks of the callbacks as a subsystem onto itself [or part of | |
1044 | a larger "remote target subsystem"] with a well defined interface, then | |
1045 | one would think that the subsystem would provide these. However, until | |
1046 | one is allowed to create such a subsystem (with its own source tree | |
1047 | independent of any particular user), such a critter can't exist. Thus | |
1048 | these functions are here for the time being. */ | |
1049 | ||
1050 | void | |
1051 | sim_cb_printf (host_callback *p, const char *fmt, ...) | |
1052 | { | |
1053 | va_list ap; | |
1054 | ||
1055 | va_start (ap, fmt); | |
1056 | p->vprintf_filtered (p, fmt, ap); | |
1057 | va_end (ap); | |
1058 | } | |
1059 | ||
1060 | void | |
1061 | sim_cb_eprintf (host_callback *p, const char *fmt, ...) | |
1062 | { | |
1063 | va_list ap; | |
1064 | ||
1065 | va_start (ap, fmt); | |
1066 | p->evprintf_filtered (p, fmt, ap); | |
1067 | va_end (ap); | |
1068 | } | |
b981d709 DJ |
1069 | |
1070 | int | |
1071 | cb_is_stdin (host_callback *cb, int fd) | |
1072 | { | |
1073 | return fdbad (cb, fd) ? 0 : fdmap (cb, fd) == 0; | |
1074 | } | |
1075 | ||
eb639c50 DJ |
1076 | int |
1077 | cb_is_stdout (host_callback *cb, int fd) | |
1078 | { | |
1079 | return fdbad (cb, fd) ? 0 : fdmap (cb, fd) == 1; | |
1080 | } | |
1081 | ||
1082 | int | |
1083 | cb_is_stderr (host_callback *cb, int fd) | |
1084 | { | |
1085 | return fdbad (cb, fd) ? 0 : fdmap (cb, fd) == 2; | |
1086 | } | |
6362a3f8 MF |
1087 | \f |
1088 | const char * | |
1089 | cb_host_str_syscall (host_callback *cb, int host_val) | |
1090 | { | |
1091 | const CB_TARGET_DEFS_MAP *m = cb_host_map_entry (cb->syscall_map, host_val); | |
1092 | ||
1093 | return m ? m->name : NULL; | |
1094 | } | |
1095 | ||
1096 | const char * | |
1097 | cb_host_str_errno (host_callback *cb, int host_val) | |
1098 | { | |
1099 | const CB_TARGET_DEFS_MAP *m = cb_host_map_entry (cb->errno_map, host_val); | |
1100 | ||
1101 | return m ? m->name : NULL; | |
1102 | } | |
1103 | ||
1104 | const char * | |
1105 | cb_host_str_signal (host_callback *cb, int host_val) | |
1106 | { | |
1107 | const CB_TARGET_DEFS_MAP *m = cb_host_map_entry (cb->signal_map, host_val); | |
1108 | ||
1109 | return m ? m->name : NULL; | |
1110 | } | |
1111 | ||
1112 | const char * | |
1113 | cb_target_str_syscall (host_callback *cb, int target_val) | |
1114 | { | |
1115 | const CB_TARGET_DEFS_MAP *m = | |
1116 | cb_target_map_entry (cb->syscall_map, target_val); | |
1117 | ||
1118 | return m ? m->name : NULL; | |
1119 | } | |
1120 | ||
1121 | const char * | |
1122 | cb_target_str_errno (host_callback *cb, int target_val) | |
1123 | { | |
1124 | const CB_TARGET_DEFS_MAP *m = | |
1125 | cb_target_map_entry (cb->errno_map, target_val); | |
1126 | ||
1127 | return m ? m->name : NULL; | |
1128 | } | |
1129 | ||
1130 | const char * | |
1131 | cb_target_str_signal (host_callback *cb, int target_val) | |
1132 | { | |
1133 | const CB_TARGET_DEFS_MAP *m = | |
1134 | cb_target_map_entry (cb->signal_map, target_val); | |
1135 | ||
1136 | return m ? m->name : NULL; | |
1137 | } |