198b9484cSchristos /* Remote target callback routines. 2*889f3bb0Schristos Copyright 1995-2024 Free Software Foundation, Inc. 398b9484cSchristos Contributed by Cygnus Solutions. 498b9484cSchristos 598b9484cSchristos This file is part of GDB. 698b9484cSchristos 798b9484cSchristos This program is free software; you can redistribute it and/or modify 898b9484cSchristos it under the terms of the GNU General Public License as published by 998b9484cSchristos the Free Software Foundation; either version 3 of the License, or 1098b9484cSchristos (at your option) any later version. 1198b9484cSchristos 1298b9484cSchristos This program is distributed in the hope that it will be useful, 1398b9484cSchristos but WITHOUT ANY WARRANTY; without even the implied warranty of 1498b9484cSchristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1598b9484cSchristos GNU General Public License for more details. 1698b9484cSchristos 1798b9484cSchristos You should have received a copy of the GNU General Public License 1898b9484cSchristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 1998b9484cSchristos 2098b9484cSchristos /* This file provides a standard way for targets to talk to the host OS 2198b9484cSchristos level. */ 2298b9484cSchristos 23924795e6Schristos /* This must come before any other includes. */ 24924795e6Schristos #include "defs.h" 25924795e6Schristos 2698b9484cSchristos #include <errno.h> 2798b9484cSchristos #include <fcntl.h> 28924795e6Schristos /* For PIPE_BUF. */ 29924795e6Schristos #include <limits.h> 30924795e6Schristos #include <signal.h> 31924795e6Schristos #include <stdarg.h> 32924795e6Schristos #include <stdint.h> 33924795e6Schristos #include <stdio.h> 34924795e6Schristos #include <stdlib.h> 35924795e6Schristos #include <string.h> 3698b9484cSchristos #include <time.h> 3798b9484cSchristos #include <unistd.h> 38924795e6Schristos #include <sys/stat.h> 39924795e6Schristos #include <sys/types.h> 40924795e6Schristos 41924795e6Schristos #include "ansidecl.h" 42924795e6Schristos /* For xmalloc. */ 43924795e6Schristos #include "libiberty.h" 44924795e6Schristos 45924795e6Schristos #include "sim/callback.h" 4698b9484cSchristos 4798b9484cSchristos #ifndef PIPE_BUF 4898b9484cSchristos #define PIPE_BUF 512 4998b9484cSchristos #endif 5098b9484cSchristos 5198b9484cSchristos extern CB_TARGET_DEFS_MAP cb_init_syscall_map[]; 5298b9484cSchristos extern CB_TARGET_DEFS_MAP cb_init_errno_map[]; 53924795e6Schristos extern CB_TARGET_DEFS_MAP cb_init_signal_map[]; 5498b9484cSchristos extern CB_TARGET_DEFS_MAP cb_init_open_map[]; 5598b9484cSchristos 5698b9484cSchristos /* Make sure the FD provided is ok. If not, return non-zero 5798b9484cSchristos and set errno. */ 5898b9484cSchristos 5998b9484cSchristos static int 609d1da10bSchristos fdbad (host_callback *p, int fd) 6198b9484cSchristos { 6298b9484cSchristos if (fd < 0 || fd > MAX_CALLBACK_FDS || p->fd_buddy[fd] < 0) 6398b9484cSchristos { 6498b9484cSchristos p->last_errno = EBADF; 6598b9484cSchristos return -1; 6698b9484cSchristos } 6798b9484cSchristos return 0; 6898b9484cSchristos } 6998b9484cSchristos 7098b9484cSchristos static int 719d1da10bSchristos fdmap (host_callback *p, int fd) 7298b9484cSchristos { 7398b9484cSchristos return p->fdmap[fd]; 7498b9484cSchristos } 7598b9484cSchristos 7698b9484cSchristos static int 779d1da10bSchristos os_close (host_callback *p, int fd) 7898b9484cSchristos { 7998b9484cSchristos int result; 8098b9484cSchristos int i, next; 8198b9484cSchristos 8298b9484cSchristos result = fdbad (p, fd); 8398b9484cSchristos if (result) 8498b9484cSchristos return result; 8598b9484cSchristos /* If this file descripter has one or more buddies (originals / 8698b9484cSchristos duplicates from a dup), just remove it from the circular list. */ 8798b9484cSchristos for (i = fd; (next = p->fd_buddy[i]) != fd; ) 8898b9484cSchristos i = next; 8998b9484cSchristos if (fd != i) 9098b9484cSchristos p->fd_buddy[i] = p->fd_buddy[fd]; 9198b9484cSchristos else 9298b9484cSchristos { 9398b9484cSchristos if (p->ispipe[fd]) 9498b9484cSchristos { 9598b9484cSchristos int other = p->ispipe[fd]; 9698b9484cSchristos int reader, writer; 9798b9484cSchristos 9898b9484cSchristos if (other > 0) 9998b9484cSchristos { 10098b9484cSchristos /* Closing the read side. */ 10198b9484cSchristos reader = fd; 10298b9484cSchristos writer = other; 10398b9484cSchristos } 10498b9484cSchristos else 10598b9484cSchristos { 10698b9484cSchristos /* Closing the write side. */ 10798b9484cSchristos writer = fd; 10898b9484cSchristos reader = -other; 10998b9484cSchristos } 11098b9484cSchristos 11198b9484cSchristos /* If there was data in the buffer, make a last "now empty" 11298b9484cSchristos call, then deallocate data. */ 11398b9484cSchristos if (p->pipe_buffer[writer].buffer != NULL) 11498b9484cSchristos { 11598b9484cSchristos (*p->pipe_empty) (p, reader, writer); 11698b9484cSchristos free (p->pipe_buffer[writer].buffer); 11798b9484cSchristos p->pipe_buffer[writer].buffer = NULL; 11898b9484cSchristos } 11998b9484cSchristos 12098b9484cSchristos /* Clear pipe data for this side. */ 12198b9484cSchristos p->pipe_buffer[fd].size = 0; 12298b9484cSchristos p->ispipe[fd] = 0; 12398b9484cSchristos 12498b9484cSchristos /* If this was the first close, mark the other side as the 12598b9484cSchristos only remaining side. */ 12698b9484cSchristos if (fd != abs (other)) 12798b9484cSchristos p->ispipe[abs (other)] = -other; 12898b9484cSchristos p->fd_buddy[fd] = -1; 12998b9484cSchristos return 0; 13098b9484cSchristos } 13198b9484cSchristos 132924795e6Schristos result = close (fdmap (p, fd)); 133924795e6Schristos p->last_errno = errno; 13498b9484cSchristos } 13598b9484cSchristos p->fd_buddy[fd] = -1; 13698b9484cSchristos 13798b9484cSchristos return result; 13898b9484cSchristos } 13998b9484cSchristos 14098b9484cSchristos 14198b9484cSchristos /* taken from gdb/util.c:notice_quit() - should be in a library */ 14298b9484cSchristos 14398b9484cSchristos 144924795e6Schristos #if defined(_MSC_VER) 14598b9484cSchristos static int 1469d1da10bSchristos os_poll_quit (host_callback *p) 14798b9484cSchristos { 14898b9484cSchristos /* NB - this will not compile! */ 14998b9484cSchristos int k = win32pollquit (); 15098b9484cSchristos if (k == 1) 15198b9484cSchristos return 1; 15298b9484cSchristos else if (k == 2) 15398b9484cSchristos return 1; 15498b9484cSchristos return 0; 15598b9484cSchristos } 15698b9484cSchristos #else 15798b9484cSchristos #define os_poll_quit 0 158924795e6Schristos #endif /* defined(_MSC_VER) */ 15998b9484cSchristos 16098b9484cSchristos static int 1619d1da10bSchristos os_get_errno (host_callback *p) 16298b9484cSchristos { 16398b9484cSchristos return cb_host_to_target_errno (p, p->last_errno); 16498b9484cSchristos } 16598b9484cSchristos 16698b9484cSchristos 16798b9484cSchristos static int 1689d1da10bSchristos os_isatty (host_callback *p, int fd) 16998b9484cSchristos { 17098b9484cSchristos int result; 17198b9484cSchristos 17298b9484cSchristos result = fdbad (p, fd); 17398b9484cSchristos if (result) 17498b9484cSchristos return result; 17598b9484cSchristos 176924795e6Schristos result = isatty (fdmap (p, fd)); 177924795e6Schristos p->last_errno = errno; 17898b9484cSchristos return result; 17998b9484cSchristos } 18098b9484cSchristos 181924795e6Schristos static int64_t 182924795e6Schristos os_lseek (host_callback *p, int fd, int64_t off, int way) 18398b9484cSchristos { 184924795e6Schristos int64_t result; 18598b9484cSchristos 18698b9484cSchristos result = fdbad (p, fd); 18798b9484cSchristos if (result) 18898b9484cSchristos return result; 189924795e6Schristos 190924795e6Schristos result = lseek (fdmap (p, fd), off, way); 191924795e6Schristos p->last_errno = errno; 19298b9484cSchristos return result; 19398b9484cSchristos } 19498b9484cSchristos 19598b9484cSchristos static int 1969d1da10bSchristos os_open (host_callback *p, const char *name, int flags) 19798b9484cSchristos { 19898b9484cSchristos int i; 19998b9484cSchristos for (i = 0; i < MAX_CALLBACK_FDS; i++) 20098b9484cSchristos { 20198b9484cSchristos if (p->fd_buddy[i] < 0) 20298b9484cSchristos { 20398b9484cSchristos int f = open (name, cb_target_to_host_open (p, flags), 0644); 20498b9484cSchristos if (f < 0) 20598b9484cSchristos { 20698b9484cSchristos p->last_errno = errno; 20798b9484cSchristos return f; 20898b9484cSchristos } 20998b9484cSchristos p->fd_buddy[i] = i; 21098b9484cSchristos p->fdmap[i] = f; 21198b9484cSchristos return i; 21298b9484cSchristos } 21398b9484cSchristos } 21498b9484cSchristos p->last_errno = EMFILE; 21598b9484cSchristos return -1; 21698b9484cSchristos } 21798b9484cSchristos 21898b9484cSchristos static int 2199d1da10bSchristos os_read (host_callback *p, int fd, char *buf, int len) 22098b9484cSchristos { 22198b9484cSchristos int result; 22298b9484cSchristos 22398b9484cSchristos result = fdbad (p, fd); 22498b9484cSchristos if (result) 22598b9484cSchristos return result; 22698b9484cSchristos if (p->ispipe[fd]) 22798b9484cSchristos { 22898b9484cSchristos int writer = p->ispipe[fd]; 22998b9484cSchristos 23098b9484cSchristos /* Can't read from the write-end. */ 23198b9484cSchristos if (writer < 0) 23298b9484cSchristos { 23398b9484cSchristos p->last_errno = EBADF; 23498b9484cSchristos return -1; 23598b9484cSchristos } 23698b9484cSchristos 23798b9484cSchristos /* Nothing to read if nothing is written. */ 23898b9484cSchristos if (p->pipe_buffer[writer].size == 0) 23998b9484cSchristos return 0; 24098b9484cSchristos 24198b9484cSchristos /* Truncate read request size to buffer size minus what's already 24298b9484cSchristos read. */ 24398b9484cSchristos if (len > p->pipe_buffer[writer].size - p->pipe_buffer[fd].size) 24498b9484cSchristos len = p->pipe_buffer[writer].size - p->pipe_buffer[fd].size; 24598b9484cSchristos 24698b9484cSchristos memcpy (buf, p->pipe_buffer[writer].buffer + p->pipe_buffer[fd].size, 24798b9484cSchristos len); 24898b9484cSchristos 24998b9484cSchristos /* Account for what we just read. */ 25098b9484cSchristos p->pipe_buffer[fd].size += len; 25198b9484cSchristos 25298b9484cSchristos /* If we've read everything, empty and deallocate the buffer and 25398b9484cSchristos signal buffer-empty to client. (This isn't expected to be a 25498b9484cSchristos hot path in the simulator, so we don't hold on to the buffer.) */ 25598b9484cSchristos if (p->pipe_buffer[fd].size == p->pipe_buffer[writer].size) 25698b9484cSchristos { 25798b9484cSchristos free (p->pipe_buffer[writer].buffer); 25898b9484cSchristos p->pipe_buffer[writer].buffer = NULL; 25998b9484cSchristos p->pipe_buffer[fd].size = 0; 26098b9484cSchristos p->pipe_buffer[writer].size = 0; 26198b9484cSchristos (*p->pipe_empty) (p, fd, writer); 26298b9484cSchristos } 26398b9484cSchristos 26498b9484cSchristos return len; 26598b9484cSchristos } 26698b9484cSchristos 267924795e6Schristos result = read (fdmap (p, fd), buf, len); 268924795e6Schristos p->last_errno = errno; 26998b9484cSchristos return result; 27098b9484cSchristos } 27198b9484cSchristos 27298b9484cSchristos static int 2739d1da10bSchristos os_read_stdin (host_callback *p, char *buf, int len) 27498b9484cSchristos { 275924795e6Schristos int result; 276924795e6Schristos 277924795e6Schristos result = read (0, buf, len); 278924795e6Schristos p->last_errno = errno; 279924795e6Schristos return result; 28098b9484cSchristos } 28198b9484cSchristos 28298b9484cSchristos static int 2839d1da10bSchristos os_write (host_callback *p, int fd, const char *buf, int len) 28498b9484cSchristos { 28598b9484cSchristos int result; 28698b9484cSchristos int real_fd; 28798b9484cSchristos 28898b9484cSchristos result = fdbad (p, fd); 28998b9484cSchristos if (result) 29098b9484cSchristos return result; 29198b9484cSchristos 29298b9484cSchristos if (p->ispipe[fd]) 29398b9484cSchristos { 29498b9484cSchristos int reader = -p->ispipe[fd]; 29598b9484cSchristos 29698b9484cSchristos /* Can't write to the read-end. */ 29798b9484cSchristos if (reader < 0) 29898b9484cSchristos { 29998b9484cSchristos p->last_errno = EBADF; 30098b9484cSchristos return -1; 30198b9484cSchristos } 30298b9484cSchristos 30398b9484cSchristos /* Can't write to pipe with closed read end. 30498b9484cSchristos FIXME: We should send a SIGPIPE. */ 30598b9484cSchristos if (reader == fd) 30698b9484cSchristos { 30798b9484cSchristos p->last_errno = EPIPE; 30898b9484cSchristos return -1; 30998b9484cSchristos } 31098b9484cSchristos 31198b9484cSchristos /* As a sanity-check, we bail out it the buffered contents is much 31298b9484cSchristos larger than the size of the buffer on the host. We don't want 31398b9484cSchristos to run out of memory in the simulator due to a target program 31498b9484cSchristos bug if we can help it. Unfortunately, regarding the value that 31598b9484cSchristos reaches the simulated program, it's no use returning *less* 31698b9484cSchristos than the requested amount, because cb_syscall loops calling 31798b9484cSchristos this function until the whole amount is done. */ 31898b9484cSchristos if (p->pipe_buffer[fd].size + len > 10 * PIPE_BUF) 31998b9484cSchristos { 32098b9484cSchristos p->last_errno = EFBIG; 32198b9484cSchristos return -1; 32298b9484cSchristos } 32398b9484cSchristos 32498b9484cSchristos p->pipe_buffer[fd].buffer 32598b9484cSchristos = xrealloc (p->pipe_buffer[fd].buffer, p->pipe_buffer[fd].size + len); 32698b9484cSchristos memcpy (p->pipe_buffer[fd].buffer + p->pipe_buffer[fd].size, 32798b9484cSchristos buf, len); 32898b9484cSchristos p->pipe_buffer[fd].size += len; 32998b9484cSchristos 33098b9484cSchristos (*p->pipe_nonempty) (p, reader, fd); 33198b9484cSchristos return len; 33298b9484cSchristos } 33398b9484cSchristos 33498b9484cSchristos real_fd = fdmap (p, fd); 33598b9484cSchristos switch (real_fd) 33698b9484cSchristos { 33798b9484cSchristos default: 338924795e6Schristos result = write (real_fd, buf, len); 339924795e6Schristos p->last_errno = errno; 34098b9484cSchristos break; 34198b9484cSchristos case 1: 34298b9484cSchristos result = p->write_stdout (p, buf, len); 34398b9484cSchristos break; 34498b9484cSchristos case 2: 34598b9484cSchristos result = p->write_stderr (p, buf, len); 34698b9484cSchristos break; 34798b9484cSchristos } 34898b9484cSchristos return result; 34998b9484cSchristos } 35098b9484cSchristos 35198b9484cSchristos static int 3529d1da10bSchristos os_write_stdout (host_callback *p ATTRIBUTE_UNUSED, const char *buf, int len) 35398b9484cSchristos { 35498b9484cSchristos return fwrite (buf, 1, len, stdout); 35598b9484cSchristos } 35698b9484cSchristos 35798b9484cSchristos static void 3589d1da10bSchristos os_flush_stdout (host_callback *p ATTRIBUTE_UNUSED) 35998b9484cSchristos { 36098b9484cSchristos fflush (stdout); 36198b9484cSchristos } 36298b9484cSchristos 36398b9484cSchristos static int 3649d1da10bSchristos os_write_stderr (host_callback *p ATTRIBUTE_UNUSED, const char *buf, int len) 36598b9484cSchristos { 36698b9484cSchristos return fwrite (buf, 1, len, stderr); 36798b9484cSchristos } 36898b9484cSchristos 36998b9484cSchristos static void 3709d1da10bSchristos os_flush_stderr (host_callback *p ATTRIBUTE_UNUSED) 37198b9484cSchristos { 37298b9484cSchristos fflush (stderr); 37398b9484cSchristos } 37498b9484cSchristos 37598b9484cSchristos static int 3769d1da10bSchristos os_rename (host_callback *p, const char *f1, const char *f2) 37798b9484cSchristos { 378924795e6Schristos int result; 379924795e6Schristos 380924795e6Schristos result = rename (f1, f2); 381924795e6Schristos p->last_errno = errno; 382924795e6Schristos return result; 38398b9484cSchristos } 38498b9484cSchristos 38598b9484cSchristos 38698b9484cSchristos static int 3879d1da10bSchristos os_system (host_callback *p, const char *s) 38898b9484cSchristos { 389924795e6Schristos int result; 390924795e6Schristos 391924795e6Schristos result = system (s); 392924795e6Schristos p->last_errno = errno; 393924795e6Schristos return result; 39498b9484cSchristos } 39598b9484cSchristos 396924795e6Schristos static int64_t 397924795e6Schristos os_time (host_callback *p) 39898b9484cSchristos { 399924795e6Schristos int64_t result; 400acd0381cSchristos 401924795e6Schristos result = time (NULL); 402924795e6Schristos p->last_errno = errno; 403924795e6Schristos return result; 40498b9484cSchristos } 40598b9484cSchristos 40698b9484cSchristos 40798b9484cSchristos static int 4089d1da10bSchristos os_unlink (host_callback *p, const char *f1) 40998b9484cSchristos { 410924795e6Schristos int result; 411924795e6Schristos 412924795e6Schristos result = unlink (f1); 413924795e6Schristos p->last_errno = errno; 414924795e6Schristos return result; 41598b9484cSchristos } 41698b9484cSchristos 41798b9484cSchristos static int 4189d1da10bSchristos os_stat (host_callback *p, const char *file, struct stat *buf) 41998b9484cSchristos { 420924795e6Schristos int result; 421924795e6Schristos 42298b9484cSchristos /* ??? There is an issue of when to translate to the target layout. 42398b9484cSchristos One could do that inside this function, or one could have the 42498b9484cSchristos caller do it. It's more flexible to let the caller do it, though 42598b9484cSchristos I'm not sure the flexibility will ever be useful. */ 426924795e6Schristos result = stat (file, buf); 427924795e6Schristos p->last_errno = errno; 428924795e6Schristos return result; 42998b9484cSchristos } 43098b9484cSchristos 43198b9484cSchristos static int 4329d1da10bSchristos os_fstat (host_callback *p, int fd, struct stat *buf) 43398b9484cSchristos { 434924795e6Schristos int result; 435924795e6Schristos 43698b9484cSchristos if (fdbad (p, fd)) 43798b9484cSchristos return -1; 43898b9484cSchristos 43998b9484cSchristos if (p->ispipe[fd]) 44098b9484cSchristos { 44198b9484cSchristos #if defined (HAVE_STRUCT_STAT_ST_ATIME) || defined (HAVE_STRUCT_STAT_ST_CTIME) || defined (HAVE_STRUCT_STAT_ST_MTIME) 442924795e6Schristos time_t t = (*p->time) (p); 44398b9484cSchristos #endif 44498b9484cSchristos 44598b9484cSchristos /* We have to fake the struct stat contents, since the pipe is 44698b9484cSchristos made up in the simulator. */ 44798b9484cSchristos memset (buf, 0, sizeof (*buf)); 44898b9484cSchristos 44998b9484cSchristos #ifdef HAVE_STRUCT_STAT_ST_MODE 45098b9484cSchristos buf->st_mode = S_IFIFO; 45198b9484cSchristos #endif 45298b9484cSchristos 45398b9484cSchristos /* If more accurate tracking than current-time is needed (for 45498b9484cSchristos example, on GNU/Linux we get accurate numbers), the p->time 45598b9484cSchristos callback (which may be something other than os_time) should 45698b9484cSchristos happen for each read and write, and we'd need to keep track of 45798b9484cSchristos atime, ctime and mtime. */ 45898b9484cSchristos #ifdef HAVE_STRUCT_STAT_ST_ATIME 45998b9484cSchristos buf->st_atime = t; 46098b9484cSchristos #endif 46198b9484cSchristos #ifdef HAVE_STRUCT_STAT_ST_CTIME 46298b9484cSchristos buf->st_ctime = t; 46398b9484cSchristos #endif 46498b9484cSchristos #ifdef HAVE_STRUCT_STAT_ST_MTIME 46598b9484cSchristos buf->st_mtime = t; 46698b9484cSchristos #endif 46798b9484cSchristos return 0; 46898b9484cSchristos } 46998b9484cSchristos 47098b9484cSchristos /* ??? There is an issue of when to translate to the target layout. 47198b9484cSchristos One could do that inside this function, or one could have the 47298b9484cSchristos caller do it. It's more flexible to let the caller do it, though 47398b9484cSchristos I'm not sure the flexibility will ever be useful. */ 474924795e6Schristos result = fstat (fdmap (p, fd), buf); 475924795e6Schristos p->last_errno = errno; 476924795e6Schristos return result; 47798b9484cSchristos } 47898b9484cSchristos 47998b9484cSchristos static int 4809d1da10bSchristos os_lstat (host_callback *p, const char *file, struct stat *buf) 48198b9484cSchristos { 482924795e6Schristos int result; 483924795e6Schristos 48498b9484cSchristos /* NOTE: hpn/2004-12-12: Same issue here as with os_fstat. */ 48598b9484cSchristos #ifdef HAVE_LSTAT 486924795e6Schristos result = lstat (file, buf); 48798b9484cSchristos #else 488924795e6Schristos result = stat (file, buf); 48998b9484cSchristos #endif 490924795e6Schristos p->last_errno = errno; 491924795e6Schristos return result; 49298b9484cSchristos } 49398b9484cSchristos 49498b9484cSchristos static int 495924795e6Schristos os_ftruncate (host_callback *p, int fd, int64_t len) 49698b9484cSchristos { 49798b9484cSchristos int result; 49898b9484cSchristos 49998b9484cSchristos result = fdbad (p, fd); 50098b9484cSchristos if (p->ispipe[fd]) 50198b9484cSchristos { 50298b9484cSchristos p->last_errno = EINVAL; 50398b9484cSchristos return -1; 50498b9484cSchristos } 50598b9484cSchristos if (result) 50698b9484cSchristos return result; 50798b9484cSchristos #ifdef HAVE_FTRUNCATE 508924795e6Schristos result = ftruncate (fdmap (p, fd), len); 509924795e6Schristos p->last_errno = errno; 51098b9484cSchristos #else 51198b9484cSchristos p->last_errno = EINVAL; 51298b9484cSchristos result = -1; 51398b9484cSchristos #endif 51498b9484cSchristos return result; 51598b9484cSchristos } 51698b9484cSchristos 51798b9484cSchristos static int 518924795e6Schristos os_truncate (host_callback *p, const char *file, int64_t len) 51998b9484cSchristos { 52098b9484cSchristos #ifdef HAVE_TRUNCATE 521924795e6Schristos int result; 522924795e6Schristos 523924795e6Schristos result = truncate (file, len); 524924795e6Schristos p->last_errno = errno; 525924795e6Schristos return result; 52698b9484cSchristos #else 52798b9484cSchristos p->last_errno = EINVAL; 52898b9484cSchristos return -1; 52998b9484cSchristos #endif 53098b9484cSchristos } 53198b9484cSchristos 53298b9484cSchristos static int 533924795e6Schristos os_getpid (host_callback *p) 534924795e6Schristos { 535924795e6Schristos int result; 536924795e6Schristos 537924795e6Schristos result = getpid (); 538924795e6Schristos /* POSIX says getpid always succeeds. */ 539924795e6Schristos p->last_errno = 0; 540924795e6Schristos return result; 541924795e6Schristos } 542924795e6Schristos 543924795e6Schristos static int 544924795e6Schristos os_kill (host_callback *p, int pid, int signum) 545924795e6Schristos { 546924795e6Schristos #ifdef HAVE_KILL 547924795e6Schristos int result; 548924795e6Schristos 549924795e6Schristos result = kill (pid, signum); 550924795e6Schristos p->last_errno = errno; 551924795e6Schristos return result; 552924795e6Schristos #else 553924795e6Schristos p->last_errno = ENOSYS; 554924795e6Schristos return -1; 555924795e6Schristos #endif 556924795e6Schristos } 557924795e6Schristos 558924795e6Schristos static int 5599d1da10bSchristos os_pipe (host_callback *p, int *filedes) 56098b9484cSchristos { 56198b9484cSchristos int i; 56298b9484cSchristos 56398b9484cSchristos /* We deliberately don't use fd 0. It's probably stdin anyway. */ 56498b9484cSchristos for (i = 1; i < MAX_CALLBACK_FDS; i++) 56598b9484cSchristos { 56698b9484cSchristos int j; 56798b9484cSchristos 56898b9484cSchristos if (p->fd_buddy[i] < 0) 56998b9484cSchristos for (j = i + 1; j < MAX_CALLBACK_FDS; j++) 57098b9484cSchristos if (p->fd_buddy[j] < 0) 57198b9484cSchristos { 57298b9484cSchristos /* Found two free fd:s. Set stat to allocated and mark 57398b9484cSchristos pipeness. */ 57498b9484cSchristos p->fd_buddy[i] = i; 57598b9484cSchristos p->fd_buddy[j] = j; 57698b9484cSchristos p->ispipe[i] = j; 57798b9484cSchristos p->ispipe[j] = -i; 57898b9484cSchristos filedes[0] = i; 57998b9484cSchristos filedes[1] = j; 58098b9484cSchristos 58198b9484cSchristos /* Poison the FD map to make bugs apparent. */ 58298b9484cSchristos p->fdmap[i] = -1; 58398b9484cSchristos p->fdmap[j] = -1; 58498b9484cSchristos return 0; 58598b9484cSchristos } 58698b9484cSchristos } 58798b9484cSchristos 58898b9484cSchristos p->last_errno = EMFILE; 58998b9484cSchristos return -1; 59098b9484cSchristos } 59198b9484cSchristos 59298b9484cSchristos /* Stub functions for pipe support. They should always be overridden in 59398b9484cSchristos targets using the pipe support, but that's up to the target. */ 59498b9484cSchristos 59598b9484cSchristos /* Called when the simulator says that the pipe at (reader, writer) is 59698b9484cSchristos now empty (so the writer should leave its waiting state). */ 59798b9484cSchristos 59898b9484cSchristos static void 5999d1da10bSchristos os_pipe_empty (host_callback *p, int reader, int writer) 60098b9484cSchristos { 60198b9484cSchristos } 60298b9484cSchristos 60398b9484cSchristos /* Called when the simulator says the pipe at (reader, writer) is now 60498b9484cSchristos non-empty (so the writer should wait). */ 60598b9484cSchristos 60698b9484cSchristos static void 6079d1da10bSchristos os_pipe_nonempty (host_callback *p, int reader, int writer) 60898b9484cSchristos { 60998b9484cSchristos } 61098b9484cSchristos 61198b9484cSchristos static int 6129d1da10bSchristos os_shutdown (host_callback *p) 61398b9484cSchristos { 61498b9484cSchristos int i, next, j; 61598b9484cSchristos for (i = 0; i < MAX_CALLBACK_FDS; i++) 61698b9484cSchristos { 61798b9484cSchristos int do_close = 1; 61898b9484cSchristos 61998b9484cSchristos /* Zero out all pipe state. Don't call callbacks for non-empty 62098b9484cSchristos pipes; the target program has likely terminated at this point 62198b9484cSchristos or we're called at initialization time. */ 62298b9484cSchristos p->ispipe[i] = 0; 62398b9484cSchristos p->pipe_buffer[i].size = 0; 62498b9484cSchristos p->pipe_buffer[i].buffer = NULL; 62598b9484cSchristos 62698b9484cSchristos next = p->fd_buddy[i]; 62798b9484cSchristos if (next < 0) 62898b9484cSchristos continue; 62998b9484cSchristos do 63098b9484cSchristos { 63198b9484cSchristos j = next; 63298b9484cSchristos if (j == MAX_CALLBACK_FDS) 63398b9484cSchristos do_close = 0; 63498b9484cSchristos next = p->fd_buddy[j]; 63598b9484cSchristos p->fd_buddy[j] = -1; 63698b9484cSchristos /* At the initial call of os_init, we got -1, 0, 0, 0, ... */ 63798b9484cSchristos if (next < 0) 63898b9484cSchristos { 63998b9484cSchristos p->fd_buddy[i] = -1; 64098b9484cSchristos do_close = 0; 64198b9484cSchristos break; 64298b9484cSchristos } 64398b9484cSchristos } 64498b9484cSchristos while (j != i); 64598b9484cSchristos if (do_close) 64698b9484cSchristos close (p->fdmap[i]); 64798b9484cSchristos } 64898b9484cSchristos return 1; 64998b9484cSchristos } 65098b9484cSchristos 65198b9484cSchristos static int 6529d1da10bSchristos os_init (host_callback *p) 65398b9484cSchristos { 65498b9484cSchristos int i; 65598b9484cSchristos 65698b9484cSchristos os_shutdown (p); 65798b9484cSchristos for (i = 0; i < 3; i++) 65898b9484cSchristos { 65998b9484cSchristos p->fdmap[i] = i; 66098b9484cSchristos p->fd_buddy[i] = i - 1; 66198b9484cSchristos } 66298b9484cSchristos p->fd_buddy[0] = MAX_CALLBACK_FDS; 66398b9484cSchristos p->fd_buddy[MAX_CALLBACK_FDS] = 2; 66498b9484cSchristos 66598b9484cSchristos p->syscall_map = cb_init_syscall_map; 66698b9484cSchristos p->errno_map = cb_init_errno_map; 667924795e6Schristos p->signal_map = cb_init_signal_map; 66898b9484cSchristos p->open_map = cb_init_open_map; 66998b9484cSchristos 67098b9484cSchristos return 1; 67198b9484cSchristos } 67298b9484cSchristos 67398b9484cSchristos /* DEPRECATED */ 67498b9484cSchristos 67598b9484cSchristos /* VARARGS */ 676924795e6Schristos static void ATTRIBUTE_PRINTF (2, 3) 67798b9484cSchristos os_printf_filtered (host_callback *p ATTRIBUTE_UNUSED, const char *format, ...) 67898b9484cSchristos { 67998b9484cSchristos va_list args; 68098b9484cSchristos va_start (args, format); 68198b9484cSchristos 68298b9484cSchristos vfprintf (stdout, format, args); 68398b9484cSchristos va_end (args); 68498b9484cSchristos } 68598b9484cSchristos 68698b9484cSchristos /* VARARGS */ 687924795e6Schristos static void ATTRIBUTE_PRINTF (2, 0) 68898b9484cSchristos os_vprintf_filtered (host_callback *p ATTRIBUTE_UNUSED, const char *format, va_list args) 68998b9484cSchristos { 69098b9484cSchristos vprintf (format, args); 69198b9484cSchristos } 69298b9484cSchristos 69398b9484cSchristos /* VARARGS */ 694924795e6Schristos static void ATTRIBUTE_PRINTF (2, 0) 69598b9484cSchristos os_evprintf_filtered (host_callback *p ATTRIBUTE_UNUSED, const char *format, va_list args) 69698b9484cSchristos { 69798b9484cSchristos vfprintf (stderr, format, args); 69898b9484cSchristos } 69998b9484cSchristos 70098b9484cSchristos /* VARARGS */ 701924795e6Schristos static void ATTRIBUTE_PRINTF (2, 3) ATTRIBUTE_NORETURN 70298b9484cSchristos os_error (host_callback *p ATTRIBUTE_UNUSED, const char *format, ...) 70398b9484cSchristos { 70498b9484cSchristos va_list args; 70598b9484cSchristos va_start (args, format); 70698b9484cSchristos 70798b9484cSchristos vfprintf (stderr, format, args); 70898b9484cSchristos fprintf (stderr, "\n"); 70998b9484cSchristos 71098b9484cSchristos va_end (args); 71198b9484cSchristos exit (1); 71298b9484cSchristos } 71398b9484cSchristos 71498b9484cSchristos host_callback default_callback = 71598b9484cSchristos { 71698b9484cSchristos os_close, 71798b9484cSchristos os_get_errno, 71898b9484cSchristos os_isatty, 71998b9484cSchristos os_lseek, 72098b9484cSchristos os_open, 72198b9484cSchristos os_read, 72298b9484cSchristos os_read_stdin, 72398b9484cSchristos os_rename, 72498b9484cSchristos os_system, 72598b9484cSchristos os_time, 72698b9484cSchristos os_unlink, 72798b9484cSchristos os_write, 72898b9484cSchristos os_write_stdout, 72998b9484cSchristos os_flush_stdout, 73098b9484cSchristos os_write_stderr, 73198b9484cSchristos os_flush_stderr, 73298b9484cSchristos 73398b9484cSchristos os_stat, 73498b9484cSchristos os_fstat, 73598b9484cSchristos os_lstat, 73698b9484cSchristos 73798b9484cSchristos os_ftruncate, 73898b9484cSchristos os_truncate, 73998b9484cSchristos 740924795e6Schristos os_getpid, 741924795e6Schristos os_kill, 742924795e6Schristos 74398b9484cSchristos os_pipe, 74498b9484cSchristos os_pipe_empty, 74598b9484cSchristos os_pipe_nonempty, 74698b9484cSchristos 74798b9484cSchristos os_poll_quit, 74898b9484cSchristos 74998b9484cSchristos os_shutdown, 75098b9484cSchristos os_init, 75198b9484cSchristos 75298b9484cSchristos os_printf_filtered, /* deprecated */ 75398b9484cSchristos 75498b9484cSchristos os_vprintf_filtered, 75598b9484cSchristos os_evprintf_filtered, 75698b9484cSchristos os_error, 75798b9484cSchristos 75898b9484cSchristos 0, /* last errno */ 75998b9484cSchristos 76098b9484cSchristos { 0, }, /* fdmap */ 76198b9484cSchristos { -1, }, /* fd_buddy */ 76298b9484cSchristos { 0, }, /* ispipe */ 76398b9484cSchristos { { 0, 0 }, }, /* pipe_buffer */ 76498b9484cSchristos 76598b9484cSchristos 0, /* syscall_map */ 76698b9484cSchristos 0, /* errno_map */ 76798b9484cSchristos 0, /* open_map */ 76898b9484cSchristos 0, /* signal_map */ 76998b9484cSchristos 0, /* stat_map */ 77098b9484cSchristos 77198b9484cSchristos /* Defaults expected to be overridden at initialization, where needed. */ 77298b9484cSchristos BFD_ENDIAN_UNKNOWN, /* target_endian */ 773924795e6Schristos NULL, /* argv */ 774924795e6Schristos NULL, /* envp */ 77598b9484cSchristos 4, /* target_sizeof_int */ 77698b9484cSchristos 77798b9484cSchristos HOST_CALLBACK_MAGIC, 77898b9484cSchristos }; 77998b9484cSchristos 78098b9484cSchristos /* Read in a file describing the target's system call values. 78198b9484cSchristos E.g. maybe someone will want to use something other than newlib. 78298b9484cSchristos This assumes that the basic system call recognition and value passing/ 78398b9484cSchristos returning is supported. So maybe some coding/recompilation will be 78498b9484cSchristos necessary, but not as much. 78598b9484cSchristos 78698b9484cSchristos If an error occurs, the existing mapping is not changed. */ 78798b9484cSchristos 78898b9484cSchristos CB_RC 7899d1da10bSchristos cb_read_target_syscall_maps (host_callback *cb, const char *file) 79098b9484cSchristos { 79198b9484cSchristos CB_TARGET_DEFS_MAP *syscall_map, *errno_map, *open_map, *signal_map; 79298b9484cSchristos const char *stat_map; 79398b9484cSchristos FILE *f; 79498b9484cSchristos 79598b9484cSchristos if ((f = fopen (file, "r")) == NULL) 79698b9484cSchristos return CB_RC_ACCESS; 79798b9484cSchristos 79898b9484cSchristos /* ... read in and parse file ... */ 79998b9484cSchristos 80098b9484cSchristos fclose (f); 80198b9484cSchristos return CB_RC_NO_MEM; /* FIXME:wip */ 80298b9484cSchristos 80398b9484cSchristos /* Free storage allocated for any existing maps. */ 80498b9484cSchristos if (cb->syscall_map) 80598b9484cSchristos free (cb->syscall_map); 80698b9484cSchristos if (cb->errno_map) 80798b9484cSchristos free (cb->errno_map); 80898b9484cSchristos if (cb->open_map) 80998b9484cSchristos free (cb->open_map); 81098b9484cSchristos if (cb->signal_map) 81198b9484cSchristos free (cb->signal_map); 81298b9484cSchristos if (cb->stat_map) 813924795e6Schristos free ((void *) cb->stat_map); 81498b9484cSchristos 81598b9484cSchristos cb->syscall_map = syscall_map; 81698b9484cSchristos cb->errno_map = errno_map; 81798b9484cSchristos cb->open_map = open_map; 81898b9484cSchristos cb->signal_map = signal_map; 81998b9484cSchristos cb->stat_map = stat_map; 82098b9484cSchristos 82198b9484cSchristos return CB_RC_OK; 82298b9484cSchristos } 82398b9484cSchristos 8247a93e43bSchristos /* General utility functions to search a map for a value. */ 8257a93e43bSchristos 8267a93e43bSchristos static const CB_TARGET_DEFS_MAP * 8277a93e43bSchristos cb_target_map_entry (const CB_TARGET_DEFS_MAP map[], int target_val) 8287a93e43bSchristos { 8297a93e43bSchristos const CB_TARGET_DEFS_MAP *m; 8307a93e43bSchristos 8317a93e43bSchristos for (m = &map[0]; m->target_val != -1; ++m) 8327a93e43bSchristos if (m->target_val == target_val) 8337a93e43bSchristos return m; 8347a93e43bSchristos 8357a93e43bSchristos return NULL; 8367a93e43bSchristos } 8377a93e43bSchristos 8387a93e43bSchristos static const CB_TARGET_DEFS_MAP * 8397a93e43bSchristos cb_host_map_entry (const CB_TARGET_DEFS_MAP map[], int host_val) 8407a93e43bSchristos { 8417a93e43bSchristos const CB_TARGET_DEFS_MAP *m; 8427a93e43bSchristos 8437a93e43bSchristos for (m = &map[0]; m->host_val != -1; ++m) 8447a93e43bSchristos if (m->host_val == host_val) 8457a93e43bSchristos return m; 8467a93e43bSchristos 8477a93e43bSchristos return NULL; 8487a93e43bSchristos } 8497a93e43bSchristos 85098b9484cSchristos /* Translate the target's version of a syscall number to the host's. 85198b9484cSchristos This isn't actually the host's version, rather a canonical form. 85298b9484cSchristos ??? Perhaps this should be renamed to ..._canon_syscall. */ 85398b9484cSchristos 85498b9484cSchristos int 8559d1da10bSchristos cb_target_to_host_syscall (host_callback *cb, int target_val) 85698b9484cSchristos { 8577a93e43bSchristos const CB_TARGET_DEFS_MAP *m = 8587a93e43bSchristos cb_target_map_entry (cb->syscall_map, target_val); 85998b9484cSchristos 8607a93e43bSchristos return m ? m->host_val : -1; 86198b9484cSchristos } 86298b9484cSchristos 86398b9484cSchristos /* FIXME: sort tables if large. 86498b9484cSchristos Alternatively, an obvious improvement for errno conversion is 86598b9484cSchristos to machine generate a function with a large switch(). */ 86698b9484cSchristos 86798b9484cSchristos /* Translate the host's version of errno to the target's. */ 86898b9484cSchristos 86998b9484cSchristos int 8709d1da10bSchristos cb_host_to_target_errno (host_callback *cb, int host_val) 87198b9484cSchristos { 8727a93e43bSchristos const CB_TARGET_DEFS_MAP *m = cb_host_map_entry (cb->errno_map, host_val); 87398b9484cSchristos 87498b9484cSchristos /* ??? Which error to return in this case is up for grabs. 87598b9484cSchristos Note that some missing values may have standard alternatives. 87698b9484cSchristos For now return 0 and require caller to deal with it. */ 8777a93e43bSchristos return m ? m->target_val : 0; 87898b9484cSchristos } 87998b9484cSchristos 88098b9484cSchristos /* Given a set of target bitmasks for the open system call, 88198b9484cSchristos return the host equivalent. 88298b9484cSchristos Mapping open flag values is best done by looping so there's no need 88398b9484cSchristos to machine generate this function. */ 88498b9484cSchristos 88598b9484cSchristos int 8869d1da10bSchristos cb_target_to_host_open (host_callback *cb, int target_val) 88798b9484cSchristos { 88898b9484cSchristos int host_val = 0; 88998b9484cSchristos CB_TARGET_DEFS_MAP *m; 890924795e6Schristos int o_rdonly = 0; 891924795e6Schristos int o_wronly = 0; 892924795e6Schristos int o_rdwr = 0; 893924795e6Schristos int o_binary = 0; 894924795e6Schristos int o_rdwrmask; 895924795e6Schristos 896924795e6Schristos /* O_RDONLY can be (and usually is) 0 which needs to be treated specially. */ 897924795e6Schristos for (m = &cb->open_map[0]; m->host_val != -1; ++m) 898924795e6Schristos { 899924795e6Schristos if (!strcmp (m->name, "O_RDONLY")) 900924795e6Schristos o_rdonly = m->target_val; 901924795e6Schristos else if (!strcmp (m->name, "O_WRONLY")) 902924795e6Schristos o_wronly = m->target_val; 903924795e6Schristos else if (!strcmp (m->name, "O_RDWR")) 904924795e6Schristos o_rdwr = m->target_val; 905924795e6Schristos else if (!strcmp (m->name, "O_BINARY")) 906924795e6Schristos o_binary = m->target_val; 907924795e6Schristos } 908924795e6Schristos o_rdwrmask = o_rdonly | o_wronly | o_rdwr; 90998b9484cSchristos 91098b9484cSchristos for (m = &cb->open_map[0]; m->host_val != -1; ++m) 91198b9484cSchristos { 912924795e6Schristos if (m->target_val == o_rdonly || m->target_val == o_wronly 913924795e6Schristos || m->target_val == o_rdwr) 91498b9484cSchristos { 915924795e6Schristos if ((target_val & o_rdwrmask) == m->target_val) 91698b9484cSchristos host_val |= m->host_val; 91798b9484cSchristos /* Handle the host/target differentiating between binary and 91898b9484cSchristos text mode. Only one case is of importance */ 919924795e6Schristos #ifdef O_BINARY 920924795e6Schristos if (o_binary == 0) 92198b9484cSchristos host_val |= O_BINARY; 92298b9484cSchristos #endif 923924795e6Schristos } 924924795e6Schristos else 925924795e6Schristos { 92698b9484cSchristos if ((m->target_val & target_val) == m->target_val) 92798b9484cSchristos host_val |= m->host_val; 92898b9484cSchristos } 92998b9484cSchristos } 93098b9484cSchristos 93198b9484cSchristos return host_val; 93298b9484cSchristos } 93398b9484cSchristos 934924795e6Schristos /* Translate the target's version of a signal number to the host's. 935924795e6Schristos This isn't actually the host's version, rather a canonical form. 936924795e6Schristos ??? Perhaps this should be renamed to ..._canon_signal. */ 937924795e6Schristos 938924795e6Schristos int 939924795e6Schristos cb_target_to_host_signal (host_callback *cb, int target_val) 940924795e6Schristos { 941924795e6Schristos const CB_TARGET_DEFS_MAP *m = 942924795e6Schristos cb_target_map_entry (cb->signal_map, target_val); 943924795e6Schristos 944924795e6Schristos return m ? m->host_val : -1; 945924795e6Schristos } 946924795e6Schristos 94798b9484cSchristos /* Utility for e.g. cb_host_to_target_stat to store values in the target's 9489d1da10bSchristos stat struct. 9499d1da10bSchristos 9509d1da10bSchristos ??? The "val" must be as big as target word size. */ 95198b9484cSchristos 95298b9484cSchristos void 9539d1da10bSchristos cb_store_target_endian (host_callback *cb, char *p, int size, long val) 95498b9484cSchristos { 95598b9484cSchristos if (cb->target_endian == BFD_ENDIAN_BIG) 95698b9484cSchristos { 95798b9484cSchristos p += size; 95898b9484cSchristos while (size-- > 0) 95998b9484cSchristos { 96098b9484cSchristos *--p = val; 96198b9484cSchristos val >>= 8; 96298b9484cSchristos } 96398b9484cSchristos } 96498b9484cSchristos else 96598b9484cSchristos { 96698b9484cSchristos while (size-- > 0) 96798b9484cSchristos { 96898b9484cSchristos *p++ = val; 96998b9484cSchristos val >>= 8; 97098b9484cSchristos } 97198b9484cSchristos } 97298b9484cSchristos } 97398b9484cSchristos 97498b9484cSchristos /* Translate a host's stat struct into a target's. 97598b9484cSchristos If HS is NULL, just compute the length of the buffer required, 97698b9484cSchristos TS is ignored. 97798b9484cSchristos 97898b9484cSchristos The result is the size of the target's stat struct, 97998b9484cSchristos or zero if an error occurred during the translation. */ 98098b9484cSchristos 98198b9484cSchristos int 982924795e6Schristos cb_host_to_target_stat (host_callback *cb, const struct stat *hs, void *ts) 98398b9484cSchristos { 98498b9484cSchristos const char *m = cb->stat_map; 98598b9484cSchristos char *p; 98698b9484cSchristos 98798b9484cSchristos if (hs == NULL) 98898b9484cSchristos ts = NULL; 98998b9484cSchristos p = ts; 99098b9484cSchristos 99198b9484cSchristos while (m) 99298b9484cSchristos { 99398b9484cSchristos char *q = strchr (m, ','); 99498b9484cSchristos int size; 99598b9484cSchristos 99698b9484cSchristos /* FIXME: Use sscanf? */ 99798b9484cSchristos if (q == NULL) 99898b9484cSchristos { 99998b9484cSchristos /* FIXME: print error message */ 100098b9484cSchristos return 0; 100198b9484cSchristos } 100298b9484cSchristos size = atoi (q + 1); 100398b9484cSchristos if (size == 0) 100498b9484cSchristos { 100598b9484cSchristos /* FIXME: print error message */ 100698b9484cSchristos return 0; 100798b9484cSchristos } 100898b9484cSchristos 100998b9484cSchristos if (hs != NULL) 101098b9484cSchristos { 101198b9484cSchristos if (0) 101298b9484cSchristos ; 101398b9484cSchristos /* Defined here to avoid emacs indigestion on a lone "else". */ 101498b9484cSchristos #undef ST_x 101598b9484cSchristos #define ST_x(FLD) \ 101698b9484cSchristos else if (strncmp (m, #FLD, q - m) == 0) \ 101798b9484cSchristos cb_store_target_endian (cb, p, size, hs->FLD) 101898b9484cSchristos 101998b9484cSchristos #ifdef HAVE_STRUCT_STAT_ST_DEV 102098b9484cSchristos ST_x (st_dev); 102198b9484cSchristos #endif 102298b9484cSchristos #ifdef HAVE_STRUCT_STAT_ST_INO 102398b9484cSchristos ST_x (st_ino); 102498b9484cSchristos #endif 102598b9484cSchristos #ifdef HAVE_STRUCT_STAT_ST_MODE 102698b9484cSchristos ST_x (st_mode); 102798b9484cSchristos #endif 102898b9484cSchristos #ifdef HAVE_STRUCT_STAT_ST_NLINK 102998b9484cSchristos ST_x (st_nlink); 103098b9484cSchristos #endif 103198b9484cSchristos #ifdef HAVE_STRUCT_STAT_ST_UID 103298b9484cSchristos ST_x (st_uid); 103398b9484cSchristos #endif 103498b9484cSchristos #ifdef HAVE_STRUCT_STAT_ST_GID 103598b9484cSchristos ST_x (st_gid); 103698b9484cSchristos #endif 103798b9484cSchristos #ifdef HAVE_STRUCT_STAT_ST_RDEV 103898b9484cSchristos ST_x (st_rdev); 103998b9484cSchristos #endif 104098b9484cSchristos #ifdef HAVE_STRUCT_STAT_ST_SIZE 104198b9484cSchristos ST_x (st_size); 104298b9484cSchristos #endif 104398b9484cSchristos #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE 104498b9484cSchristos ST_x (st_blksize); 104598b9484cSchristos #endif 104698b9484cSchristos #ifdef HAVE_STRUCT_STAT_ST_BLOCKS 104798b9484cSchristos ST_x (st_blocks); 104898b9484cSchristos #endif 104998b9484cSchristos #ifdef HAVE_STRUCT_STAT_ST_ATIME 105098b9484cSchristos ST_x (st_atime); 105198b9484cSchristos #endif 105298b9484cSchristos #ifdef HAVE_STRUCT_STAT_ST_MTIME 105398b9484cSchristos ST_x (st_mtime); 105498b9484cSchristos #endif 105598b9484cSchristos #ifdef HAVE_STRUCT_STAT_ST_CTIME 105698b9484cSchristos ST_x (st_ctime); 105798b9484cSchristos #endif 105898b9484cSchristos #undef ST_x 105998b9484cSchristos /* FIXME:wip */ 106098b9484cSchristos else 106198b9484cSchristos /* Unsupported field, store 0. */ 106298b9484cSchristos cb_store_target_endian (cb, p, size, 0); 106398b9484cSchristos } 106498b9484cSchristos 106598b9484cSchristos p += size; 106698b9484cSchristos m = strchr (q, ':'); 106798b9484cSchristos if (m) 106898b9484cSchristos ++m; 106998b9484cSchristos } 107098b9484cSchristos 107198b9484cSchristos return p - (char *) ts; 107298b9484cSchristos } 107398b9484cSchristos 107498b9484cSchristos int 107598b9484cSchristos cb_is_stdin (host_callback *cb, int fd) 107698b9484cSchristos { 107798b9484cSchristos return fdbad (cb, fd) ? 0 : fdmap (cb, fd) == 0; 107898b9484cSchristos } 107998b9484cSchristos 108098b9484cSchristos int 108198b9484cSchristos cb_is_stdout (host_callback *cb, int fd) 108298b9484cSchristos { 108398b9484cSchristos return fdbad (cb, fd) ? 0 : fdmap (cb, fd) == 1; 108498b9484cSchristos } 108598b9484cSchristos 108698b9484cSchristos int 108798b9484cSchristos cb_is_stderr (host_callback *cb, int fd) 108898b9484cSchristos { 108998b9484cSchristos return fdbad (cb, fd) ? 0 : fdmap (cb, fd) == 2; 109098b9484cSchristos } 10917a93e43bSchristos 10927a93e43bSchristos const char * 10937a93e43bSchristos cb_host_str_syscall (host_callback *cb, int host_val) 10947a93e43bSchristos { 10957a93e43bSchristos const CB_TARGET_DEFS_MAP *m = cb_host_map_entry (cb->syscall_map, host_val); 10967a93e43bSchristos 10977a93e43bSchristos return m ? m->name : NULL; 10987a93e43bSchristos } 10997a93e43bSchristos 11007a93e43bSchristos const char * 11017a93e43bSchristos cb_host_str_errno (host_callback *cb, int host_val) 11027a93e43bSchristos { 11037a93e43bSchristos const CB_TARGET_DEFS_MAP *m = cb_host_map_entry (cb->errno_map, host_val); 11047a93e43bSchristos 11057a93e43bSchristos return m ? m->name : NULL; 11067a93e43bSchristos } 11077a93e43bSchristos 11087a93e43bSchristos const char * 11097a93e43bSchristos cb_host_str_signal (host_callback *cb, int host_val) 11107a93e43bSchristos { 11117a93e43bSchristos const CB_TARGET_DEFS_MAP *m = cb_host_map_entry (cb->signal_map, host_val); 11127a93e43bSchristos 11137a93e43bSchristos return m ? m->name : NULL; 11147a93e43bSchristos } 11157a93e43bSchristos 11167a93e43bSchristos const char * 11177a93e43bSchristos cb_target_str_syscall (host_callback *cb, int target_val) 11187a93e43bSchristos { 11197a93e43bSchristos const CB_TARGET_DEFS_MAP *m = 11207a93e43bSchristos cb_target_map_entry (cb->syscall_map, target_val); 11217a93e43bSchristos 11227a93e43bSchristos return m ? m->name : NULL; 11237a93e43bSchristos } 11247a93e43bSchristos 11257a93e43bSchristos const char * 11267a93e43bSchristos cb_target_str_errno (host_callback *cb, int target_val) 11277a93e43bSchristos { 11287a93e43bSchristos const CB_TARGET_DEFS_MAP *m = 11297a93e43bSchristos cb_target_map_entry (cb->errno_map, target_val); 11307a93e43bSchristos 11317a93e43bSchristos return m ? m->name : NULL; 11327a93e43bSchristos } 11337a93e43bSchristos 11347a93e43bSchristos const char * 11357a93e43bSchristos cb_target_str_signal (host_callback *cb, int target_val) 11367a93e43bSchristos { 11377a93e43bSchristos const CB_TARGET_DEFS_MAP *m = 11387a93e43bSchristos cb_target_map_entry (cb->signal_map, target_val); 11397a93e43bSchristos 11407a93e43bSchristos return m ? m->name : NULL; 11417a93e43bSchristos } 1142