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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gdb/] [gdb-6.8/] [sim/] [common/] [syscall.c] - Blame information for rev 26

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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