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