source: rtems/c/src/lib/libbsp/arm/gdbarmsim/startup/syscalls.c @ 12072880

4.115
Last change on this file since 12072880 was b3fb2ff, checked in by Chris Johns <chrisj@…>, on 05/26/14 at 01:44:48

bsp/gdbarmsim: Change syscall functions to not clash with RTEMS functions.

The syscall functions overlapped with RTEMS, for example _write, _read, etc.
Change these to be internal to the BSP and avoid any clash with names in
RTEMS. Add support for SWI_Write0.

Change the console driver to use SWI_Write0. This outputs the character
to the host's stdout. Writing to file name 0 is not captured and managed
by GDB's simulation code while the SWI_Write0 is. The managed stdout
data is encapulated in the MI protocol while writes to file handle 0 are
dropped by GDB when in MI mode.

  • Property mode set to 100644
File size: 15.7 KB
Line 
1/*
2 *  Copied from libgloss 1 Oct 2009.
3 *  Minor modifications to work with RTEMS.
4 */
5
6/* Support files for GNU libc.  Files in the system namespace go here.
7   Files in the C namespace (ie those that do not start with an
8   underscore) go in .c.  */
9
10/*
11 * Rename all the functions present here to stop then clashing with RTEMS
12 * names.
13 */
14
15#include <_ansi.h>
16#include <sys/types.h>
17#include <sys/stat.h>
18#include <sys/fcntl.h>
19#include <stdio.h>
20#include <string.h>
21#include <time.h>
22#include <sys/time.h>
23#include <sys/times.h>
24#include <errno.h>
25#include <reent.h>
26#include <unistd.h>
27#include <sys/wait.h>
28#include <bsp/swi.h>
29
30#include <bsp.h>
31
32/* Forward prototypes.  */
33static int      checkerror(int);
34static int      error(int);
35static int      get_errno(void);
36
37/* Struct used to keep track of the file position, just so we
38   can implement fseek(fh,x,SEEK_CUR).  */
39struct fdent
40{
41  int handle;
42  int pos;
43};
44
45#define MAX_OPEN_FILES 20
46
47/* User file descriptors (fd) are integer indexes into
48   the openfiles[] array. Error checking is done by using
49   findslot().
50
51   This openfiles array is manipulated directly by only
52   these 5 functions:
53
54        findslot() - Translate entry.
55        newslot() - Find empty entry.
56        initilise_monitor_handles() - Initialize entries.
57        _swiopen() - Initialize entry.
58        _close() - Handle stdout == stderr case.
59
60   Every other function must use findslot().  */
61
62static struct fdent openfiles [MAX_OPEN_FILES];
63
64static struct fdent*    findslot (int);
65static int              newslot (void);
66
67/* Register name faking - works in collusion with the linker.  */
68register char * stack_ptr __asm__ ("sp");
69
70
71/* following is copied from libc/stdio/local.h to check std streams */
72extern void   _EXFUN(__sinit,(struct _reent *));
73#define CHECK_INIT(ptr) \
74  do                                            \
75    {                                           \
76      if ((ptr) && !(ptr)->__sdidinit)          \
77        __sinit (ptr);                          \
78    }                                           \
79  while (0)
80
81static int monitor_stdin;
82static int monitor_stdout;
83static int monitor_stderr;
84
85/* Return a pointer to the structure associated with
86   the user file descriptor fd. */
87static struct fdent*
88findslot (int fd)
89{
90  CHECK_INIT(_REENT);
91
92  /* User file descriptor is out of range. */
93  if ((unsigned int)fd >= MAX_OPEN_FILES)
94    return NULL;
95
96  /* User file descriptor is open? */
97  if (openfiles[fd].handle == -1)
98    return NULL;
99
100  /* Valid. */
101  return &openfiles[fd];
102}
103
104/* Return the next lowest numbered free file
105   structure, or -1 if we can't find one. */
106static int
107newslot (void)
108{
109  int i;
110
111  for (i = 0; i < MAX_OPEN_FILES; i++)
112    if (openfiles[i].handle == -1)
113      break;
114
115  if (i == MAX_OPEN_FILES)
116    return -1;
117
118  return i;
119}
120
121void
122initialise_monitor_handles (void)
123{
124  int i;
125
126  /* Open the standard file descriptors by opening the special
127   * teletype device, ":tt", read-only to obtain a descritpor for
128   * standard input and write-only to obtain a descriptor for standard
129   * output. Finally, open ":tt" in append mode to obtain a descriptor
130   * for standard error. Since this is a write mode, most kernels will
131   * probably return the same value as for standard output, but the
132   * kernel can differentiate the two using the mode flag and return a
133   * different descriptor for standard error.
134   */
135
136#ifdef ARM_RDI_MONITOR
137  int volatile block[3];
138
139  block[0] = (int) ":tt";
140  block[2] = 3;     /* length of filename */
141  block[1] = 0;     /* mode "r" */
142  monitor_stdin = do_AngelSWI (AngelSWI_Reason_Open, (void *) block);
143
144  block[0] = (int) ":tt";
145  block[2] = 3;     /* length of filename */
146  block[1] = 4;     /* mode "w" */
147  monitor_stdout = do_AngelSWI (AngelSWI_Reason_Open, (void *) block);
148
149  block[0] = (int) ":tt";
150  block[2] = 3;     /* length of filename */
151  block[1] = 8;     /* mode "a" */
152  monitor_stderr = do_AngelSWI (AngelSWI_Reason_Open, (void *) block);
153#else
154  int fh;
155  const char * name;
156
157  name = ":tt";
158  __asm__ ("mov r0,%2; mov r1, #0; swi %a1; mov %0, r0"
159       : "=r"(fh)
160       : "i" (SWI_Open),"r"(name)
161       : "r0","r1");
162  monitor_stdin = fh;
163
164  name = ":tt";
165  __asm__ ("mov r0,%2; mov r1, #4; swi %a1; mov %0, r0"
166       : "=r"(fh)
167       : "i" (SWI_Open),"r"(name)
168       : "r0","r1");
169  monitor_stdout = fh;
170
171  name = ":tt";
172  __asm__ ("mov r0,%2; mov r1, #8; swi %a1; mov %0, r0"
173       : "=r"(fh)
174       : "i" (SWI_Open),"r"(name)
175       : "r0","r1");
176  monitor_stderr = fh;
177#endif
178
179  /* If we failed to open stderr, redirect to stdout. */
180  if (monitor_stderr == -1)
181    monitor_stderr = monitor_stdout;
182
183  for (i = 0; i < MAX_OPEN_FILES; i ++)
184    openfiles[i].handle = -1;
185
186  openfiles[0].handle = monitor_stdin;
187  openfiles[0].pos = 0;
188  openfiles[1].handle = monitor_stdout;
189  openfiles[1].pos = 0;
190  openfiles[2].handle = monitor_stderr;
191  openfiles[2].pos = 0;
192}
193
194static int
195get_errno (void)
196{
197#ifdef ARM_RDI_MONITOR
198  return do_AngelSWI (AngelSWI_Reason_Errno, NULL);
199#else
200  register int r0 __asm__ ("r0");
201  __asm__ ("swi %a1" : "=r"(r0) : "i" (SWI_GetErrno));
202  return r0;
203#endif
204}
205
206/* Set errno and return result. */
207static int
208error (int result)
209{
210  errno = get_errno ();
211  return result;
212}
213
214/* Check the return and set errno appropriately. */
215static int
216checkerror (int result)
217{
218  if (result == -1)
219    return error (-1);
220  return result;
221}
222
223/* fh, is a valid internal file handle.
224   ptr, is a null terminated string.
225   len, is the length in bytes to read.
226   Returns the number of bytes *not* written. */
227int
228gdbarmsim_swiread (int fh,
229                   char * ptr,
230                   int len)
231{
232#ifdef ARM_RDI_MONITOR
233  int block[3];
234
235  block[0] = fh;
236  block[1] = (int) ptr;
237  block[2] = len;
238
239  return checkerror (do_AngelSWI (AngelSWI_Reason_Read, block));
240#else
241  register int r0 __asm__ ("r0");
242  register int r1 __asm__ ("r1");
243  register int r2 __asm__ ("r2");
244  r0 = fh;
245  r1 = (int)ptr;
246  r2 = len;
247  __asm__ ("swi %a4"
248       : "=r" (r0)
249       : "0"(r0), "r"(r1), "r"(r2), "i"(SWI_Read));
250  return checkerror (r0);
251#endif
252}
253
254/* fd, is a valid user file handle.
255   Translates the return of _swiread into
256   bytes read. */
257int
258gdbarmsim_read (int fd,
259                char * ptr,
260                int len)
261{
262  int res;
263  struct fdent *pfd;
264
265  pfd = findslot (fd);
266  if (pfd == NULL)
267    {
268      errno = EBADF;
269      return -1;
270    }
271
272  res = gdbarmsim_swiread (pfd->handle, ptr, len);
273
274  if (res == -1)
275    return res;
276
277  pfd->pos += len - res;
278
279  /* res == len is not an error,
280     at least if we want feof() to work.  */
281  return len - res;
282}
283
284/* fd, is a user file descriptor. */
285int
286gdbarmsim_swilseek (int fd,
287                    int ptr,
288                    int dir)
289{
290  int res;
291  struct fdent *pfd;
292
293  /* Valid file descriptor? */
294  pfd = findslot (fd);
295  if (pfd == NULL)
296    {
297      errno = EBADF;
298      return -1;
299    }
300
301  /* Valid whence? */
302  if ((dir != SEEK_CUR)
303      && (dir != SEEK_SET)
304      && (dir != SEEK_END))
305    {
306      errno = EINVAL;
307      return -1;
308    }
309
310  /* Convert SEEK_CUR to SEEK_SET */
311  if (dir == SEEK_CUR)
312    {
313      ptr = pfd->pos + ptr;
314      /* The resulting file offset would be negative. */
315      if (ptr < 0)
316        {
317          errno = EINVAL;
318          if ((pfd->pos > 0) && (ptr > 0))
319            errno = EOVERFLOW;
320          return -1;
321        }
322      dir = SEEK_SET;
323    }
324
325#ifdef ARM_RDI_MONITOR
326  int block[2];
327  if (dir == SEEK_END)
328    {
329      block[0] = pfd->handle;
330      res = checkerror (do_AngelSWI (AngelSWI_Reason_FLen, block));
331      if (res == -1)
332        return -1;
333      ptr += res;
334    }
335
336  /* This code only does absolute seeks.  */
337  block[0] = pfd->handle;
338  block[1] = ptr;
339  res = checkerror (do_AngelSWI (AngelSWI_Reason_Seek, block));
340#else
341  if (dir == SEEK_END)
342    {
343      __asm__ ("mov r0, %2; swi %a1; mov %0, r0"
344           : "=r" (res)
345           : "i" (SWI_Flen), "r" (pfd->handle)
346           : "r0");
347      checkerror (res);
348      if (res == -1)
349        return -1;
350      ptr += res;
351    }
352
353  /* This code only does absolute seeks.  */
354  __asm__ ("mov r0, %2; mov r1, %3; swi %a1; mov %0, r0"
355       : "=r" (res)
356       : "i" (SWI_Seek), "r" (pfd->handle), "r" (ptr)
357       : "r0", "r1");
358  checkerror (res);
359#endif
360  /* At this point ptr is the current file position. */
361  if (res >= 0)
362    {
363      pfd->pos = ptr;
364      return ptr;
365    }
366  else
367    return -1;
368}
369
370int
371gdbarmsim_lseek (int fd,
372                 int ptr,
373                 int dir)
374{
375  return gdbarmsim_swilseek (fd, ptr, dir);
376}
377
378/* write a single character out the hosts stdout */
379int
380gdbarmsim_writec (const char c)
381{
382#ifdef ARM_RDI_MONITOR
383  int block[1];
384
385  block[0] = ((int) c) & 0xff;;
386
387  return checkerror (do_AngelSWI (AngelSWI_Reason_WriteC, block));
388#else
389  register int r0 __asm__ ("r0");
390  r0 = ((int) c) & 0xff;
391  __asm__ ("swi %a2"
392       : "=r" (r0)
393       : "0"(r0), "i"(SWI_WriteC));
394  return checkerror (r0);
395#endif
396}
397
398/* fh, is a valid internal file handle.
399   Returns the number of bytes *not* written. */
400int
401gdbarmsim_swiwrite (int    fh,
402                    char * ptr,
403                    int    len)
404{
405#ifdef ARM_RDI_MONITOR
406  int block[3];
407
408  block[0] = fh;
409  block[1] = (int) ptr;
410  block[2] = len;
411
412  return checkerror (do_AngelSWI (AngelSWI_Reason_Write, block));
413#else
414  register int r0 __asm__ ("r0");
415  register int r1 __asm__ ("r1");
416  register int r2 __asm__ ("r2");
417  r0 = fh;
418  r1 = (int)ptr;
419  r2 = len;
420  __asm__ ("swi %a4"
421       : "=r" (r0)
422       : "0"(r0), "r"(r1), "r"(r2), "i"(SWI_Write));
423  return checkerror (r0);
424#endif
425}
426
427/* fd, is a user file descriptor. */
428int
429gdbarmsim_write (int    fd,
430                 char * ptr,
431                 int    len)
432{
433  int res;
434  struct fdent *pfd;
435
436  pfd = findslot (fd);
437  if (pfd == NULL)
438    {
439      errno = EBADF;
440      return -1;
441    }
442
443  res = gdbarmsim_swiwrite (pfd->handle, ptr,len);
444
445  /* Clearly an error. */
446  if (res < 0)
447    return -1;
448
449  pfd->pos += len - res;
450
451  /* We wrote 0 bytes?
452     Retrieve errno just in case. */
453  if ((len - res) == 0)
454    return error (0);
455
456  return (len - res);
457}
458
459int
460gdbarmsim_swiopen (const char * path, int flags)
461{
462  int aflags = 0, fh;
463#ifdef ARM_RDI_MONITOR
464  int block[3];
465#endif
466
467  int fd = newslot ();
468
469  if (fd == -1)
470    {
471      errno = EMFILE;
472      return -1;
473    }
474
475  /* It is an error to open a file that already exists. */
476  if ((flags & O_CREAT)
477      && (flags & O_EXCL))
478    {
479      struct stat st;
480      int res;
481      res = gdbarmsim_stat (path, &st);
482      if (res != -1)
483        {
484          errno = EEXIST;
485          return -1;
486        }
487    }
488
489  /* The flags are Unix-style, so we need to convert them. */
490#ifdef O_BINARY
491  if (flags & O_BINARY)
492    aflags |= 1;
493#endif
494
495  /* In O_RDONLY we expect aflags == 0. */
496
497  if (flags & O_RDWR)
498    aflags |= 2;
499
500  if ((flags & O_CREAT)
501      || (flags & O_TRUNC)
502      || (flags & O_WRONLY))
503    aflags |= 4;
504
505  if (flags & O_APPEND)
506    {
507      /* Can't ask for w AND a; means just 'a'.  */
508      aflags &= ~4;
509      aflags |= 8;
510    }
511
512#ifdef ARM_RDI_MONITOR
513  block[0] = (int) path;
514  block[2] = strlen (path);
515  block[1] = aflags;
516
517  fh = do_AngelSWI (AngelSWI_Reason_Open, block);
518
519#else
520  __asm__ ("mov r0,%2; mov r1, %3; swi %a1; mov %0, r0"
521       : "=r"(fh)
522       : "i" (SWI_Open),"r"(path),"r"(aflags)
523       : "r0","r1");
524#endif
525
526  /* Return a user file descriptor or an error. */
527  if (fh >= 0)
528    {
529      openfiles[fd].handle = fh;
530      openfiles[fd].pos = 0;
531      return fd;
532    }
533  else
534    return error (fh);
535}
536
537int
538gdbarmsim_open (const char * path, int flags, ...)
539{
540  return gdbarmsim_swiopen (path, flags);
541}
542
543/* fh, is a valid internal file handle. */
544int
545gdbarmsim_swiclose (int fh)
546{
547#ifdef ARM_RDI_MONITOR
548  return checkerror (do_AngelSWI (AngelSWI_Reason_Close, &fh));
549#else
550  register int r0 __asm__ ("r0");
551  r0 = fh;
552  __asm__ ("swi %a2"
553       : "=r"(r0)
554       : "0"(r0), "i" (SWI_Close));
555  return checkerror (r0);
556#endif
557}
558
559/* fd, is a user file descriptor. */
560int
561gdbarmsim_close (int fd)
562{
563  int res;
564  struct fdent *pfd;
565
566  pfd = findslot (fd);
567  if (pfd == NULL)
568    {
569      errno = EBADF;
570      return -1;
571    }
572
573  /* Handle stderr == stdout. */
574  if ((fd == 1 || fd == 2)
575      && (openfiles[1].handle == openfiles[2].handle))
576    {
577      pfd->handle = -1;
578      return 0;
579    }
580
581  /* Attempt to close the handle. */
582  res = gdbarmsim_swiclose (pfd->handle);
583
584  /* Reclaim handle? */
585  if (res == 0)
586    pfd->handle = -1;
587
588  return res;
589}
590
591int
592gdbarmsim_swistat (int fd, struct stat * st)
593{
594  struct fdent *pfd;
595  int res;
596
597  pfd = findslot (fd);
598  if (pfd == NULL)
599    {
600      errno = EBADF;
601      return -1;
602    }
603
604  /* Always assume a character device,
605     with 1024 byte blocks. */
606  st->st_mode |= S_IFCHR;
607  st->st_blksize = 1024;
608#ifdef ARM_RDI_MONITOR
609  res = checkerror (do_AngelSWI (AngelSWI_Reason_FLen, &pfd->handle));
610#else
611  __asm__ ("mov r0, %2; swi %a1; mov %0, r0"
612       : "=r" (res)
613       : "i" (SWI_Flen), "r" (pfd->handle)
614       : "r0");
615  checkerror (res);
616#endif
617  if (res == -1)
618    return -1;
619  /* Return the file size. */
620  st->st_size = res;
621  return 0;
622}
623
624int
625gdbarmsim_fstat (int fd, struct stat * st)
626{
627  memset (st, 0, sizeof (* st));
628  return gdbarmsim_swistat (fd, st);
629}
630
631int
632gdbarmsim_stat (const char *fname, struct stat *st)
633{
634  int fd, res;
635  memset (st, 0, sizeof (* st));
636  /* The best we can do is try to open the file readonly.
637     If it exists, then we can guess a few things about it. */
638  if ((fd = gdbarmsim_open (fname, O_RDONLY)) == -1)
639    return -1;
640  st->st_mode |= S_IFREG | S_IREAD;
641  res = gdbarmsim_swistat (fd, st);
642  /* Not interested in the error. */
643  gdbarmsim_close (fd);
644  return res;
645}
646
647int
648gdbarmsim_unlink (const char *path)
649{
650  int res;
651#ifdef ARM_RDI_MONITOR
652  int block[2];
653  block[0] = (int)path;
654  block[1] = strlen(path);
655  res = do_AngelSWI (AngelSWI_Reason_Remove, block);
656#else
657  register int r0 __asm__ ("r0");
658  r0 = (int)path;
659  __asm__ ("swi %a2"
660       : "=r"(r0)
661       : "0"(r0), "i" (SWI_Remove));
662  res = r0;
663#endif
664  if (res == -1)
665    return error (res);
666  return 0;
667}
668
669/* Return a clock that ticks at 100Hz.  */
670clock_t
671gdbarmsim_clock (void)
672{
673  clock_t timeval;
674
675#ifdef ARM_RDI_MONITOR
676  timeval = do_AngelSWI (AngelSWI_Reason_Clock,NULL);
677#else
678  __asm__ ("swi %a1; mov %0, r0" : "=r" (timeval): "i" (SWI_Clock) : "r0");
679#endif
680  return timeval;
681}
682
683int
684gdbarmsim__isatty (int fd)
685{
686  struct fdent *pfd;
687
688  pfd = findslot (fd);
689  if (pfd == NULL)
690    {
691      errno = EBADF;
692      return -1;
693    }
694
695#ifdef ARM_RDI_MONITOR
696  return checkerror (do_AngelSWI (AngelSWI_Reason_IsTTY, &pfd->handle));
697#else
698  register int r0 __asm__ ("r0");
699  r0 = pfd->handle;
700  __asm__ ("swi %a2"
701       : "=r" (r0)
702       : "0"(r0), "i" (SWI_IsTTY));
703  return checkerror (r0);
704#endif
705}
706
707int
708gdbarmsim_system (const char *s)
709{
710#ifdef ARM_RDI_MONITOR
711  int block[2];
712  int e;
713
714  /* Hmmm.  The ARM debug interface specification doesn't say whether
715     SYS_SYSTEM does the right thing with a null argument, or assign any
716     meaning to its return value.  Try to do something reasonable....  */
717  if (!s)
718    return 1;  /* maybe there is a shell available? we can hope. :-P */
719  block[0] = (int)s;
720  block[1] = strlen (s);
721  e = checkerror (do_AngelSWI (AngelSWI_Reason_System, block));
722  if ((e >= 0) && (e < 256))
723    {
724      /* We have to convert e, an exit status to the encoded status of
725         the command.  To avoid hard coding the exit status, we simply
726         loop until we find the right position.  */
727      int exit_code;
728
729      for (exit_code = e; e && WEXITSTATUS (e) != exit_code; e <<= 1)
730        continue;
731    }
732  return e;
733#else
734  register int r0 __asm__ ("r0");
735  r0 = (int)s;
736  __asm__ ("swi %a2"
737       : "=r" (r0)
738       : "0"(r0), "i" (SWI_CLI));
739  return checkerror (r0);
740#endif
741}
742
743int
744gdbarmsim_rename (const char * oldpath, const char * newpath)
745{
746#ifdef ARM_RDI_MONITOR
747  int block[4];
748  block[0] = (int)oldpath;
749  block[1] = strlen(oldpath);
750  block[2] = (int)newpath;
751  block[3] = strlen(newpath);
752  return checkerror (do_AngelSWI (AngelSWI_Reason_Rename, block)) ? -1 : 0;
753#else
754  register int r0 __asm__ ("r0");
755  register int r1 __asm__ ("r1");
756  r0 = (int)oldpath;
757  r1 = (int)newpath;
758  __asm__ ("swi %a3"
759       : "=r" (r0)
760       : "0" (r0), "r" (r1), "i" (SWI_Rename));
761  return checkerror (r0);
762#endif
763}
Note: See TracBrowser for help on using the repository browser.