OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [sim/] [common/] [syscall.c] - Blame information for rev 1771

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/* Remote target system call support.
2
   Copyright 1997, 1998 Free Software Foundation, Inc.
3
   Contributed by Cygnus Solutions.
4
 
5
   This file is part of GDB.
6
 
7
   This program is free software; you can redistribute it and/or modify
8
   it under the terms of the GNU General Public License as published by
9
   the Free Software Foundation; either version 2 of the License, or
10
   (at your option) any later version.
11
 
12
   This program is distributed in the hope that it will be useful,
13
   but WITHOUT ANY WARRANTY; without even the implied warranty of
14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
   GNU General Public License for more details.
16
 
17
   You should have received a copy of the GNU General Public License
18
   along with GAS; see the file COPYING.  If not, write to the Free Software
19
   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
 
21
/* This interface isn't intended to be specific to any particular kind
22
   of remote (hardware, simulator, whatever).  As such, support for it
23
   (e.g. sim/common/callback.c) should *not* live in the simulator source
24
   tree, nor should it live in the gdb source tree.  K&R C must be
25
   supported.  */
26
 
27
#ifdef HAVE_CONFIG_H
28
#include "config.h"
29
#endif
30
#include "ansidecl.h"
31
#include "libiberty.h"
32
#ifdef ANSI_PROTOTYPES
33
#include <stdarg.h>
34
#else
35
#include <varargs.h>
36
#endif
37
#include <stdio.h>
38
#ifdef HAVE_STDLIB_H
39
#include <stdlib.h>
40
#endif
41
#ifdef HAVE_UNISTD_H
42
#include <unistd.h>
43
#endif
44
#include <errno.h>
45
#include <fcntl.h>
46
#include <time.h>
47
#include <sys/types.h>
48
#include <sys/stat.h>
49
#include "callback.h"
50
#include "targ-vals.h"
51
 
52
#ifndef ENOSYS
53
#define ENOSYS EINVAL
54
#endif
55
#ifndef ENAMETOOLONG
56
#define ENAMETOOLONG EINVAL
57
#endif
58
 
59
/* Maximum length of a path name.  */
60
#ifndef MAX_PATH_LEN
61
#define MAX_PATH_LEN 1024
62
#endif
63
 
64
/* When doing file read/writes, do this many bytes at a time.  */
65
#define FILE_XFR_SIZE 4096
66
 
67
/* FIXME: for now, need to consider target word size.  */
68
#define TWORD long
69
#define TADDR unsigned long
70
 
71
/* Utility of cb_syscall to fetch a path name or other string from the target.
72
   The result is 0 for success or a host errno value.  */
73
 
74
static int
75
get_string (cb, sc, buf, buflen, addr)
76
     host_callback *cb;
77
     CB_SYSCALL *sc;
78
     char *buf;
79
     int buflen;
80
     TADDR addr;
81
{
82
  char *p, *pend;
83
 
84
  for (p = buf, pend = buf + buflen; p < pend; ++p, ++addr)
85
    {
86
      /* No, it isn't expected that this would cause one transaction with
87
         the remote target for each byte.  The target could send the
88
         path name along with the syscall request, and cache the file
89
         name somewhere (or otherwise tweak this as desired).  */
90
      unsigned int count = (*sc->read_mem) (cb, sc, addr, p, 1);
91
 
92
      if (count != 1)
93
        return EINVAL;
94
      if (*p == 0)
95
        break;
96
    }
97
  if (p == pend)
98
    return ENAMETOOLONG;
99
  return 0;
100
}
101
 
102
/* Utility of cb_syscall to fetch a path name.
103
   The buffer is malloc'd and the address is stored in BUFP.
104
   The result is that of get_string.
105
   If an error occurs, no buffer is left malloc'd.  */
106
 
107
static int
108
get_path (cb, sc, addr, bufp)
109
     host_callback *cb;
110
     CB_SYSCALL *sc;
111
     TADDR addr;
112
     char **bufp;
113
{
114
  char *buf = xmalloc (MAX_PATH_LEN);
115
  int result;
116
 
117
  result = get_string (cb, sc, buf, MAX_PATH_LEN, addr);
118
  if (result == 0)
119
    *bufp = buf;
120
  else
121
    free (buf);
122
  return result;
123
}
124
 
125
/* Perform a system call on behalf of the target.  */
126
 
127
CB_RC
128
cb_syscall (cb, sc)
129
     host_callback *cb;
130
     CB_SYSCALL *sc;
131
{
132
  TWORD result = 0, errcode = 0;
133
 
134
  if (sc->magic != CB_SYSCALL_MAGIC)
135
    abort ();
136
 
137
  switch (cb_target_to_host_syscall (cb, sc->func))
138
    {
139
#if 0 /* FIXME: wip */
140
    case CB_SYS_argvlen :
141
      {
142
        /* Compute how much space is required to store the argv,envp
143
           strings so that the program can allocate the space and then
144
           call SYS_argv to fetch the values.  */
145
        int addr_size = cb->addr_size;
146
        int argc,envc,arglen,envlen;
147
        const char **argv = cb->init_argv;
148
        const char **envp = cb->init_envp;
149
 
150
        argc = arglen = 0;
151
        if (argv)
152
          {
153
            for ( ; argv[argc]; ++argc)
154
              arglen += strlen (argv[argc]) + 1;
155
          }
156
        envc = envlen = 0;
157
        if (envp)
158
          {
159
            for ( ; envp[envc]; ++envc)
160
              envlen += strlen (envp[envc]) + 1;
161
          }
162
        result = arglen + envlen;
163
        break;
164
      }
165
 
166
    case CB_SYS_argv :
167
      {
168
        /* Pointer to target's buffer.  */
169
        TADDR tbuf = sc->arg1;
170
        /* Buffer size.  */
171
        int bufsize = sc->arg2;
172
        /* Q is the target address of where all the strings go.  */
173
        TADDR q;
174
        int word_size = cb->word_size;
175
        int i,argc,envc,len;
176
        const char **argv = cb->init_argv;
177
        const char **envp = cb->init_envp;
178
 
179
        argc = 0;
180
        if (argv)
181
          {
182
            for ( ; argv[argc]; ++argc)
183
              {
184
                int len = strlen (argv[argc]);
185
                int written = (*sc->write_mem) (cb, sc, tbuf, argv[argc], len + 1);
186
                if (written != len)
187
                  {
188
                    result = -1;
189
                    errcode = EINVAL;
190
                    goto FinishSyscall;
191
                  }
192
                tbuf = len + 1;
193
              }
194
          }
195
        if ((*sc->write_mem) (cb, sc, tbuf, "", 1) != 1)
196
          {
197
            result = -1;
198
            errcode = EINVAL;
199
            goto FinishSyscall;
200
          }
201
        tbuf++;
202
        envc = 0;
203
        if (envp)
204
          {
205
            for ( ; envp[envc]; ++envc)
206
              {
207
                int len = strlen (envp[envc]);
208
                int written = (*sc->write_mem) (cb, sc, tbuf, envp[envc], len + 1);
209
                if (written != len)
210
                  {
211
                    result = -1;
212
                    errcode = EINVAL;
213
                    goto FinishSyscall;
214
                  }
215
                tbuf = len + 1;
216
              }
217
          }
218
        if ((*sc->write_mem) (cb, sc, tbuf, "", 1) != 1)
219
          {
220
            result = -1;
221
            errcode = EINVAL;
222
            goto FinishSyscall;
223
          }
224
        result = argc;
225
        sc->result2 = envc;
226
        break;
227
      }
228
#endif /* wip */
229
 
230
    case CB_SYS_exit :
231
      /* Caller must catch and handle.  */
232
      break;
233
 
234
    case CB_SYS_open :
235
      {
236
        char *path;
237
 
238
        errcode = get_path (cb, sc, sc->arg1, &path);
239
        if (errcode != 0)
240
          {
241
            result = -1;
242
            goto FinishSyscall;
243
          }
244
        result = (*cb->open) (cb, path, sc->arg2 /*, sc->arg3*/);
245
        free (path);
246
        if (result < 0)
247
          goto ErrorFinish;
248
      }
249
      break;
250
 
251
    case CB_SYS_close :
252
      result = (*cb->close) (cb, sc->arg1);
253
      if (result < 0)
254
        goto ErrorFinish;
255
      break;
256
 
257
    case CB_SYS_read :
258
      {
259
        /* ??? Perfect handling of error conditions may require only one
260
           call to cb->read.  One can't assume all the data is
261
           contiguously stored in host memory so that would require
262
           malloc'ing/free'ing the space.  Maybe later.  */
263
        char buf[FILE_XFR_SIZE];
264
        int fd = sc->arg1;
265
        TADDR addr = sc->arg2;
266
        size_t count = sc->arg3;
267
        size_t bytes_read = 0;
268
        int bytes_written;
269
 
270
        while (count > 0)
271
          {
272
            if (fd == 0)
273
              result = (int) (*cb->read_stdin) (cb, buf,
274
                                                (count < FILE_XFR_SIZE
275
                                                 ? count : FILE_XFR_SIZE));
276
            else
277
              result = (int) (*cb->read) (cb, fd, buf,
278
                                          (count < FILE_XFR_SIZE
279
                                           ? count : FILE_XFR_SIZE));
280
            if (result == -1)
281
              goto ErrorFinish;
282
            if (result == 0)     /* EOF */
283
              break;
284
            bytes_written = (*sc->write_mem) (cb, sc, addr, buf, result);
285
            if (bytes_written != result)
286
              {
287
                result = -1;
288
                errcode = EINVAL;
289
                goto FinishSyscall;
290
              }
291
            bytes_read += result;
292
            count -= result;
293
            addr += result;
294
            /* If this is a short read, don't go back for more */
295
            if (result != FILE_XFR_SIZE)
296
              break;
297
          }
298
        result = bytes_read;
299
      }
300
      break;
301
 
302
    case CB_SYS_write :
303
      {
304
        /* ??? Perfect handling of error conditions may require only one
305
           call to cb->write.  One can't assume all the data is
306
           contiguously stored in host memory so that would require
307
           malloc'ing/free'ing the space.  Maybe later.  */
308
        char buf[FILE_XFR_SIZE];
309
        int fd = sc->arg1;
310
        TADDR addr = sc->arg2;
311
        size_t count = sc->arg3;
312
        int bytes_read;
313
        size_t bytes_written = 0;
314
 
315
        while (count > 0)
316
          {
317
            int bytes_to_read = count < FILE_XFR_SIZE ? count : FILE_XFR_SIZE;
318
            bytes_read = (*sc->read_mem) (cb, sc, addr, buf, bytes_to_read);
319
            if (bytes_read != bytes_to_read)
320
              {
321
                result = -1;
322
                errcode = EINVAL;
323
                goto FinishSyscall;
324
              }
325
            if (fd == 1)
326
              {
327
                result = (int) (*cb->write_stdout) (cb, buf, bytes_read);
328
                (*cb->flush_stdout) (cb);
329
              }
330
            else if (fd == 2)
331
              {
332
                result = (int) (*cb->write_stderr) (cb, buf, bytes_read);
333
                (*cb->flush_stderr) (cb);
334
              }
335
            else
336
              result = (int) (*cb->write) (cb, fd, buf, bytes_read);
337
            if (result == -1)
338
              goto ErrorFinish;
339
            bytes_written += result;
340
            count -= result;
341
            addr += result;
342
          }
343
        result = bytes_written;
344
      }
345
      break;
346
 
347
    case CB_SYS_lseek :
348
      {
349
        int fd = sc->arg1;
350
        unsigned long offset = sc->arg2;
351
        int whence = sc->arg3;
352
 
353
        result = (*cb->lseek) (cb, fd, offset, whence);
354
        if (result < 0)
355
          goto ErrorFinish;
356
      }
357
      break;
358
 
359
    case CB_SYS_unlink :
360
      {
361
        char *path;
362
 
363
        errcode = get_path (cb, sc, sc->arg1, &path);
364
        if (errcode != 0)
365
          {
366
            result = -1;
367
            goto FinishSyscall;
368
          }
369
        result = (*cb->unlink) (cb, path);
370
        free (path);
371
        if (result < 0)
372
          goto ErrorFinish;
373
      }
374
      break;
375
 
376
    case CB_SYS_stat :
377
      {
378
        char *path,*buf;
379
        int buflen;
380
        struct stat statbuf;
381
        TADDR addr = sc->arg2;
382
 
383
        errcode = get_path (cb, sc, sc->arg1, &path);
384
        if (errcode != 0)
385
          {
386
            result = -1;
387
            goto FinishSyscall;
388
          }
389
        result = (*cb->stat) (cb, path, &statbuf);
390
        free (path);
391
        if (result < 0)
392
          goto ErrorFinish;
393
        buflen = cb_host_to_target_stat (cb, NULL, NULL);
394
        buf = xmalloc (buflen);
395
        if (cb_host_to_target_stat (cb, &statbuf, buf) != buflen)
396
          {
397
            /* The translation failed.  This is due to an internal
398
               host program error, not the target's fault.  */
399
            free (buf);
400
            errcode = ENOSYS;
401
            result = -1;
402
            goto FinishSyscall;
403
          }
404
        if ((*sc->write_mem) (cb, sc, addr, buf, buflen) != buflen)
405
          {
406
            free (buf);
407
            errcode = EINVAL;
408
            result = -1;
409
            goto FinishSyscall;
410
          }
411
        free (buf);
412
      }
413
      break;
414
 
415
    case CB_SYS_fstat :
416
      {
417
        char *buf;
418
        int buflen;
419
        struct stat statbuf;
420
        TADDR addr = sc->arg2;
421
 
422
        result = (*cb->fstat) (cb, sc->arg1, &statbuf);
423
        if (result < 0)
424
          goto ErrorFinish;
425
        buflen = cb_host_to_target_stat (cb, NULL, NULL);
426
        buf = xmalloc (buflen);
427
        if (cb_host_to_target_stat (cb, &statbuf, buf) != buflen)
428
          {
429
            /* The translation failed.  This is due to an internal
430
               host program error, not the target's fault.  */
431
            free (buf);
432
            errcode = ENOSYS;
433
            result = -1;
434
            goto FinishSyscall;
435
          }
436
        if ((*sc->write_mem) (cb, sc, addr, buf, buflen) != buflen)
437
          {
438
            free (buf);
439
            errcode = EINVAL;
440
            result = -1;
441
            goto FinishSyscall;
442
          }
443
        free (buf);
444
      }
445
      break;
446
 
447
    case CB_SYS_time :
448
      {
449
        /* FIXME: May wish to change CB_SYS_time to something else.
450
           We might also want gettimeofday or times, but if system calls
451
           can be built on others, we can keep the number we have to support
452
           here down.  */
453
        time_t t = (*cb->time) (cb, (time_t *) 0);
454
        result = t;
455
        /* It is up to target code to process the argument to time().  */
456
      }
457
      break;
458
 
459
    case CB_SYS_chdir :
460
    case CB_SYS_chmod :
461
    case CB_SYS_utime :
462
      /* fall through for now */
463
 
464
    default :
465
      result = -1;
466
      errcode = ENOSYS;
467
      break;
468
    }
469
 
470
 FinishSyscall:
471
  sc->result = result;
472
  if (errcode == 0)
473
    sc->errcode = 0;
474
  else
475
    sc->errcode = cb_host_to_target_errno (cb, errcode);
476
  return CB_RC_OK;
477
 
478
 ErrorFinish:
479
  sc->result = result;
480
  sc->errcode = (*cb->get_errno) (cb);
481
  return CB_RC_OK;
482
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.