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