OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-7.1/] [sim/] [common/] [syscall.c] - Blame information for rev 293

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

Line No. Rev Author Line
1 227 jeremybenn
/* Remote target system call support.
2
   Copyright 1997, 1998, 2002, 2004, 2007, 2008, 2009, 2010
3
   Free Software Foundation, Inc.
4
   Contributed by Cygnus Solutions.
5
 
6
   This file is part of GDB.
7
 
8
   This program is free software; you can redistribute it and/or modify
9
   it under the terms of the GNU General Public License as published by
10
   the Free Software Foundation; either version 3 of the License, or
11
   (at your option) any later version.
12
 
13
   This program is distributed in the hope that it will be useful,
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
   GNU General Public License for more details.
17
 
18
   You should have received a copy of the GNU General Public License
19
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
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 "cconfig.h"
29
#endif
30
#include "ansidecl.h"
31
#include "libiberty.h"
32
#include <stdarg.h>
33
#include <stdio.h>
34
#ifdef HAVE_STDLIB_H
35
#include <stdlib.h>
36
#endif
37
#ifdef HAVE_STRING_H
38
#include <string.h>
39
#elif defined (HAVE_STRINGS_H)
40
#include <strings.h>
41
#endif
42
#ifdef HAVE_UNISTD_H
43
#include <unistd.h>
44
#endif
45
#include <errno.h>
46
#include <fcntl.h>
47
#include <time.h>
48
#include <sys/types.h>
49
#include <sys/stat.h>
50
#include "gdb/callback.h"
51
#include "targ-vals.h"
52
 
53
#ifndef ENOSYS
54
#define ENOSYS EINVAL
55
#endif
56
#ifndef ENAMETOOLONG
57
#define ENAMETOOLONG EINVAL
58
#endif
59
 
60
/* Maximum length of a path name.  */
61
#ifndef MAX_PATH_LEN
62
#define MAX_PATH_LEN 1024
63
#endif
64
 
65
/* When doing file read/writes, do this many bytes at a time.  */
66
#define FILE_XFR_SIZE 4096
67
 
68
/* FIXME: for now, need to consider target word size.  */
69
#define TWORD long
70
#define TADDR unsigned long
71
 
72
/* Path to be prepended to syscalls with absolute paths, and to be
73
   chdir:ed at startup, if not empty.  */
74
char *simulator_sysroot = "";
75
 
76
/* Utility of cb_syscall to fetch a path name or other string from the target.
77
   The result is 0 for success or a host errno value.  */
78
 
79
static int
80
get_string (cb, sc, buf, buflen, addr)
81
     host_callback *cb;
82
     CB_SYSCALL *sc;
83
     char *buf;
84
     int buflen;
85
     TADDR addr;
86
{
87
  char *p, *pend;
88
 
89
  for (p = buf, pend = buf + buflen; p < pend; ++p, ++addr)
90
    {
91
      /* No, it isn't expected that this would cause one transaction with
92
         the remote target for each byte.  The target could send the
93
         path name along with the syscall request, and cache the file
94
         name somewhere (or otherwise tweak this as desired).  */
95
      unsigned int count = (*sc->read_mem) (cb, sc, addr, p, 1);
96
 
97
      if (count != 1)
98
        return EINVAL;
99
      if (*p == 0)
100
        break;
101
    }
102
  if (p == pend)
103
    return ENAMETOOLONG;
104
  return 0;
105
}
106
 
107
/* Utility of cb_syscall to fetch a path name.
108
   The buffer is malloc'd and the address is stored in BUFP.
109
   The result is that of get_string, but prepended with
110
   simulator_sysroot if the string starts with '/'.
111
   If an error occurs, no buffer is left malloc'd.  */
112
 
113
static int
114
get_path (cb, sc, addr, bufp)
115
     host_callback *cb;
116
     CB_SYSCALL *sc;
117
     TADDR addr;
118
     char **bufp;
119
{
120
  char *buf = xmalloc (MAX_PATH_LEN);
121
  int result;
122
  int sysroot_len = strlen (simulator_sysroot);
123
 
124
  result = get_string (cb, sc, buf, MAX_PATH_LEN - sysroot_len, addr);
125
  if (result == 0)
126
    {
127
      /* Prepend absolute paths with simulator_sysroot.  Relative paths
128
         are supposed to be relative to a chdir within that path, but at
129
         this point unknown where.  */
130
      if (simulator_sysroot[0] != '\0' && *buf == '/')
131
        {
132
          /* Considering expected rareness of syscalls with absolute
133
             file paths (compared to relative file paths and insn
134
             execution), it does not seem worthwhile to rearrange things
135
             to get rid of the string moves here; we'd need at least an
136
             extra call to check the initial '/' in the path.  */
137
          memmove (buf + sysroot_len, buf, sysroot_len);
138
          memcpy (buf, simulator_sysroot, sysroot_len);
139
        }
140
 
141
      *bufp = buf;
142
    }
143
  else
144
    free (buf);
145
  return result;
146
}
147
 
148
/* Perform a system call on behalf of the target.  */
149
 
150
CB_RC
151
cb_syscall (cb, sc)
152
     host_callback *cb;
153
     CB_SYSCALL *sc;
154
{
155
  TWORD result = 0, errcode = 0;
156
 
157
  if (sc->magic != CB_SYSCALL_MAGIC)
158
    abort ();
159
 
160
  switch (cb_target_to_host_syscall (cb, sc->func))
161
    {
162
#if 0 /* FIXME: wip */
163
    case CB_SYS_argvlen :
164
      {
165
        /* Compute how much space is required to store the argv,envp
166
           strings so that the program can allocate the space and then
167
           call SYS_argv to fetch the values.  */
168
        int addr_size = cb->addr_size;
169
        int argc,envc,arglen,envlen;
170
        const char **argv = cb->init_argv;
171
        const char **envp = cb->init_envp;
172
 
173
        argc = arglen = 0;
174
        if (argv)
175
          {
176
            for ( ; argv[argc]; ++argc)
177
              arglen += strlen (argv[argc]) + 1;
178
          }
179
        envc = envlen = 0;
180
        if (envp)
181
          {
182
            for ( ; envp[envc]; ++envc)
183
              envlen += strlen (envp[envc]) + 1;
184
          }
185
        result = arglen + envlen;
186
        break;
187
      }
188
 
189
    case CB_SYS_argv :
190
      {
191
        /* Pointer to target's buffer.  */
192
        TADDR tbuf = sc->arg1;
193
        /* Buffer size.  */
194
        int bufsize = sc->arg2;
195
        /* Q is the target address of where all the strings go.  */
196
        TADDR q;
197
        int word_size = cb->word_size;
198
        int i,argc,envc,len;
199
        const char **argv = cb->init_argv;
200
        const char **envp = cb->init_envp;
201
 
202
        argc = 0;
203
        if (argv)
204
          {
205
            for ( ; argv[argc]; ++argc)
206
              {
207
                int len = strlen (argv[argc]);
208
                int written = (*sc->write_mem) (cb, sc, tbuf, argv[argc], 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
        tbuf++;
225
        envc = 0;
226
        if (envp)
227
          {
228
            for ( ; envp[envc]; ++envc)
229
              {
230
                int len = strlen (envp[envc]);
231
                int written = (*sc->write_mem) (cb, sc, tbuf, envp[envc], len + 1);
232
                if (written != len)
233
                  {
234
                    result = -1;
235
                    errcode = EINVAL;
236
                    goto FinishSyscall;
237
                  }
238
                tbuf = len + 1;
239
              }
240
          }
241
        if ((*sc->write_mem) (cb, sc, tbuf, "", 1) != 1)
242
          {
243
            result = -1;
244
            errcode = EINVAL;
245
            goto FinishSyscall;
246
          }
247
        result = argc;
248
        sc->result2 = envc;
249
        break;
250
      }
251
#endif /* wip */
252
 
253
    case CB_SYS_exit :
254
      /* Caller must catch and handle.  */
255
      break;
256
 
257
    case CB_SYS_open :
258
      {
259
        char *path;
260
 
261
        errcode = get_path (cb, sc, sc->arg1, &path);
262
        if (errcode != 0)
263
          {
264
            result = -1;
265
            goto FinishSyscall;
266
          }
267
        result = (*cb->open) (cb, path, sc->arg2 /*, sc->arg3*/);
268
        free (path);
269
        if (result < 0)
270
          goto ErrorFinish;
271
      }
272
      break;
273
 
274
    case CB_SYS_close :
275
      result = (*cb->close) (cb, sc->arg1);
276
      if (result < 0)
277
        goto ErrorFinish;
278
      break;
279
 
280
    case CB_SYS_read :
281
      {
282
        /* ??? Perfect handling of error conditions may require only one
283
           call to cb->read.  One can't assume all the data is
284
           contiguously stored in host memory so that would require
285
           malloc'ing/free'ing the space.  Maybe later.  */
286
        char buf[FILE_XFR_SIZE];
287
        int fd = sc->arg1;
288
        TADDR addr = sc->arg2;
289
        size_t count = sc->arg3;
290
        size_t bytes_read = 0;
291
        int bytes_written;
292
 
293
        while (count > 0)
294
          {
295
            if (cb_is_stdin (cb, fd))
296
              result = (int) (*cb->read_stdin) (cb, buf,
297
                                                (count < FILE_XFR_SIZE
298
                                                 ? count : FILE_XFR_SIZE));
299
            else
300
              result = (int) (*cb->read) (cb, fd, buf,
301
                                          (count < FILE_XFR_SIZE
302
                                           ? count : FILE_XFR_SIZE));
303
            if (result == -1)
304
              goto ErrorFinish;
305
            if (result == 0)     /* EOF */
306
              break;
307
            bytes_written = (*sc->write_mem) (cb, sc, addr, buf, result);
308
            if (bytes_written != result)
309
              {
310
                result = -1;
311
                errcode = EINVAL;
312
                goto FinishSyscall;
313
              }
314
            bytes_read += result;
315
            count -= result;
316
            addr += result;
317
            /* If this is a short read, don't go back for more */
318
            if (result != FILE_XFR_SIZE)
319
              break;
320
          }
321
        result = bytes_read;
322
      }
323
      break;
324
 
325
    case CB_SYS_write :
326
      {
327
        /* ??? Perfect handling of error conditions may require only one
328
           call to cb->write.  One can't assume all the data is
329
           contiguously stored in host memory so that would require
330
           malloc'ing/free'ing the space.  Maybe later.  */
331
        char buf[FILE_XFR_SIZE];
332
        int fd = sc->arg1;
333
        TADDR addr = sc->arg2;
334
        size_t count = sc->arg3;
335
        int bytes_read;
336
        size_t bytes_written = 0;
337
 
338
        while (count > 0)
339
          {
340
            int bytes_to_read = count < FILE_XFR_SIZE ? count : FILE_XFR_SIZE;
341
            bytes_read = (*sc->read_mem) (cb, sc, addr, buf, bytes_to_read);
342
            if (bytes_read != bytes_to_read)
343
              {
344
                result = -1;
345
                errcode = EINVAL;
346
                goto FinishSyscall;
347
              }
348
            if (cb_is_stdout(cb, fd))
349
              {
350
                result = (int) (*cb->write_stdout) (cb, buf, bytes_read);
351
                (*cb->flush_stdout) (cb);
352
              }
353
            else if (cb_is_stderr(cb, fd))
354
              {
355
                result = (int) (*cb->write_stderr) (cb, buf, bytes_read);
356
                (*cb->flush_stderr) (cb);
357
              }
358
            else
359
              result = (int) (*cb->write) (cb, fd, buf, bytes_read);
360
            if (result == -1)
361
              goto ErrorFinish;
362
            bytes_written += result;
363
            count -= result;
364
            addr += result;
365
          }
366
        result = bytes_written;
367
      }
368
      break;
369
 
370
    case CB_SYS_lseek :
371
      {
372
        int fd = sc->arg1;
373
        unsigned long offset = sc->arg2;
374
        int whence = sc->arg3;
375
 
376
        result = (*cb->lseek) (cb, fd, offset, whence);
377
        if (result < 0)
378
          goto ErrorFinish;
379
      }
380
      break;
381
 
382
    case CB_SYS_unlink :
383
      {
384
        char *path;
385
 
386
        errcode = get_path (cb, sc, sc->arg1, &path);
387
        if (errcode != 0)
388
          {
389
            result = -1;
390
            goto FinishSyscall;
391
          }
392
        result = (*cb->unlink) (cb, path);
393
        free (path);
394
        if (result < 0)
395
          goto ErrorFinish;
396
      }
397
      break;
398
 
399
    case CB_SYS_truncate :
400
      {
401
        char *path;
402
        long len = sc->arg2;
403
 
404
        errcode = get_path (cb, sc, sc->arg1, &path);
405
        if (errcode != 0)
406
          {
407
            result = -1;
408
            errcode = EFAULT;
409
            goto FinishSyscall;
410
          }
411
        result = (*cb->truncate) (cb, path, len);
412
        free (path);
413
        if (result < 0)
414
          goto ErrorFinish;
415
      }
416
      break;
417
 
418
    case CB_SYS_ftruncate :
419
      {
420
        int fd = sc->arg1;
421
        long len = sc->arg2;
422
 
423
        result = (*cb->ftruncate) (cb, fd, len);
424
        if (result < 0)
425
          goto ErrorFinish;
426
      }
427
      break;
428
 
429
    case CB_SYS_rename :
430
      {
431
        char *path1, *path2;
432
 
433
        errcode = get_path (cb, sc, sc->arg1, &path1);
434
        if (errcode != 0)
435
          {
436
            result = -1;
437
            errcode = EFAULT;
438
            goto FinishSyscall;
439
          }
440
        errcode = get_path (cb, sc, sc->arg2, &path2);
441
        if (errcode != 0)
442
          {
443
            result = -1;
444
            errcode = EFAULT;
445
            free (path1);
446
            goto FinishSyscall;
447
          }
448
        result = (*cb->rename) (cb, path1, path2);
449
        free (path1);
450
        free (path2);
451
        if (result < 0)
452
          goto ErrorFinish;
453
      }
454
      break;
455
 
456
    case CB_SYS_stat :
457
      {
458
        char *path,*buf;
459
        int buflen;
460
        struct stat statbuf;
461
        TADDR addr = sc->arg2;
462
 
463
        errcode = get_path (cb, sc, sc->arg1, &path);
464
        if (errcode != 0)
465
          {
466
            result = -1;
467
            goto FinishSyscall;
468
          }
469
        result = (*cb->stat) (cb, path, &statbuf);
470
        free (path);
471
        if (result < 0)
472
          goto ErrorFinish;
473
        buflen = cb_host_to_target_stat (cb, NULL, NULL);
474
        buf = xmalloc (buflen);
475
        if (cb_host_to_target_stat (cb, &statbuf, buf) != buflen)
476
          {
477
            /* The translation failed.  This is due to an internal
478
               host program error, not the target's fault.  */
479
            free (buf);
480
            errcode = ENOSYS;
481
            result = -1;
482
            goto FinishSyscall;
483
          }
484
        if ((*sc->write_mem) (cb, sc, addr, buf, buflen) != buflen)
485
          {
486
            free (buf);
487
            errcode = EINVAL;
488
            result = -1;
489
            goto FinishSyscall;
490
          }
491
        free (buf);
492
      }
493
      break;
494
 
495
    case CB_SYS_fstat :
496
      {
497
        char *buf;
498
        int buflen;
499
        struct stat statbuf;
500
        TADDR addr = sc->arg2;
501
 
502
        result = (*cb->fstat) (cb, sc->arg1, &statbuf);
503
        if (result < 0)
504
          goto ErrorFinish;
505
        buflen = cb_host_to_target_stat (cb, NULL, NULL);
506
        buf = xmalloc (buflen);
507
        if (cb_host_to_target_stat (cb, &statbuf, buf) != buflen)
508
          {
509
            /* The translation failed.  This is due to an internal
510
               host program error, not the target's fault.  */
511
            free (buf);
512
            errcode = ENOSYS;
513
            result = -1;
514
            goto FinishSyscall;
515
          }
516
        if ((*sc->write_mem) (cb, sc, addr, buf, buflen) != buflen)
517
          {
518
            free (buf);
519
            errcode = EINVAL;
520
            result = -1;
521
            goto FinishSyscall;
522
          }
523
        free (buf);
524
      }
525
      break;
526
 
527
    case CB_SYS_lstat :
528
      {
529
        char *path, *buf;
530
        int buflen;
531
        struct stat statbuf;
532
        TADDR addr = sc->arg2;
533
 
534
        errcode = get_path (cb, sc, sc->arg1, &path);
535
        if (errcode != 0)
536
          {
537
            result = -1;
538
            goto FinishSyscall;
539
          }
540
        result = (*cb->lstat) (cb, path, &statbuf);
541
        free (path);
542
        if (result < 0)
543
          goto ErrorFinish;
544
 
545
        buflen = cb_host_to_target_stat (cb, NULL, NULL);
546
        buf = xmalloc (buflen);
547
        if (cb_host_to_target_stat (cb, &statbuf, buf) != buflen)
548
          {
549
            /* The translation failed.  This is due to an internal
550
               host program error, not the target's fault.
551
               Unfortunately, it's hard to test this case, so there's no
552
               test-case for this execution path.  */
553
            free (buf);
554
            errcode = ENOSYS;
555
            result = -1;
556
            goto FinishSyscall;
557
          }
558
 
559
        if ((*sc->write_mem) (cb, sc, addr, buf, buflen) != buflen)
560
          {
561
            free (buf);
562
            errcode = EINVAL;
563
            result = -1;
564
            goto FinishSyscall;
565
          }
566
 
567
        free (buf);
568
      }
569
      break;
570
 
571
    case CB_SYS_pipe :
572
      {
573
        int p[2];
574
        char *target_p = xcalloc (1, cb->target_sizeof_int * 2);
575
 
576
        result = (*cb->pipe) (cb, p);
577
        if (result != 0)
578
          goto ErrorFinish;
579
 
580
        cb_store_target_endian (cb, target_p, cb->target_sizeof_int, p[0]);
581
        cb_store_target_endian (cb, target_p + cb->target_sizeof_int,
582
                                cb->target_sizeof_int, p[1]);
583
        if ((*sc->write_mem) (cb, sc, sc->arg1, target_p,
584
                              cb->target_sizeof_int * 2)
585
            != cb->target_sizeof_int * 2)
586
          {
587
            /* Close the pipe fd:s.  */
588
            (*cb->close) (cb, p[0]);
589
            (*cb->close) (cb, p[1]);
590
            errcode = EFAULT;
591
            result = -1;
592
          }
593
 
594
        free (target_p);
595
      }
596
      break;
597
 
598
    case CB_SYS_time :
599
      {
600
        /* FIXME: May wish to change CB_SYS_time to something else.
601
           We might also want gettimeofday or times, but if system calls
602
           can be built on others, we can keep the number we have to support
603
           here down.  */
604
        time_t t = (*cb->time) (cb, (time_t *) 0);
605
        result = t;
606
        /* It is up to target code to process the argument to time().  */
607
      }
608
      break;
609
 
610
    case CB_SYS_chdir :
611
    case CB_SYS_chmod :
612
    case CB_SYS_utime :
613
      /* fall through for now */
614
 
615
    default :
616
      result = -1;
617
      errcode = ENOSYS;
618
      break;
619
    }
620
 
621
 FinishSyscall:
622
  sc->result = result;
623
  if (errcode == 0)
624
    sc->errcode = 0;
625
  else
626
    sc->errcode = cb_host_to_target_errno (cb, errcode);
627
  return CB_RC_OK;
628
 
629
 ErrorFinish:
630
  sc->result = result;
631
  sc->errcode = (*cb->get_errno) (cb);
632
  return CB_RC_OK;
633
}

powered by: WebSVN 2.1.0

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