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