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