[arm] Fix syscalls.c for newlib embedded syscalls builds

Newlib has a build configuration where syscalls can be directly
embedded in the newlib library rather than relying on libgloss.

This configuration was broken recently by an update to the libgloss
support for Arm that was not propagated to the syscalls interface in
newlib itself.  This patch restores the build.  It's essentially a
copy of https://sourceware.org/ml/newlib/2018/msg00128.html but there
are some other minor cleanups and changes that I've made at the same
time.  None of those cleanups affect functionality.

The prototypes of the following functions have been updated: _link,
_sbrk, _getpid, _write, _swiwrite, _lseek, _swilseek, _read and
_swiread.

Signed-off-by: Richard Earnshaw <Richard.Earnshaw@arm.com>
This commit is contained in:
Richard Earnshaw 2018-03-15 09:55:11 +00:00
parent 829820af6e
commit 0bb8697333
1 changed files with 126 additions and 119 deletions

View File

@ -18,37 +18,37 @@
#include "swi.h" #include "swi.h"
/* Forward prototypes. */ /* Forward prototypes. */
int _system (const char *); int _system (const char *);
int _rename (const char *, const char *); int _rename (const char *, const char *);
int _isatty (int); int _isatty (int);
clock_t _times (struct tms *); clock_t _times (struct tms *);
int _gettimeofday (struct timeval *, void *); int _gettimeofday (struct timeval *, void *);
void _raise (void); void _raise (void);
int _unlink (const char *); int _unlink (const char *);
int _link (void); int _link (const char *, const char *);
int _stat (const char *, struct stat *); int _stat (const char *, struct stat *);
int _fstat (int, struct stat *); int _fstat (int, struct stat *);
caddr_t _sbrk (int); void * _sbrk (ptrdiff_t);
int _getpid (int); pid_t _getpid (void);
int _kill (int, int); int _kill (int, int);
void _exit (int); void _exit (int);
int _close (int); int _close (int);
int _swiclose (int); int _swiclose (int);
int _open (const char *, int, ...); int _open (const char *, int, ...);
int _swiopen (const char *, int); int _swiopen (const char *, int);
int _write (int, char *, int); int _write (int, const void *, size_t);
int _swiwrite (int, char *, int); int _swiwrite (int, const void *, size_t);
int _lseek (int, int, int); _off_t _lseek (int, _off_t, int);
int _swilseek (int, int, int); _off_t _swilseek (int, _off_t, int);
int _read (int, char *, int); int _read (int, void *, size_t);
int _swiread (int, char *, int); int _swiread (int, void *, size_t);
void initialise_monitor_handles (void); void initialise_monitor_handles (void);
static int wrap (int); static int wrap (int);
static int error (int); static int error (int);
static int get_errno (void); static int get_errno (void);
static int remap_handle (int); static int remap_handle (int);
static int findslot (int); static int findslot (int);
/* Register name faking - works in collusion with the linker. */ /* Register name faking - works in collusion with the linker. */
register char * stack_ptr asm ("sp"); register char * stack_ptr asm ("sp");
@ -113,10 +113,10 @@ void
initialise_monitor_handles (void) initialise_monitor_handles (void)
{ {
int i; int i;
#ifdef ARM_RDI_MONITOR #ifdef ARM_RDI_MONITOR
int volatile block[3]; int volatile block[3];
block[0] = (int) ":tt"; block[0] = (int) ":tt";
block[2] = 3; /* length of filename */ block[2] = 3; /* length of filename */
block[1] = 0; /* mode "r" */ block[1] = 0; /* mode "r" */
@ -125,7 +125,8 @@ initialise_monitor_handles (void)
block[0] = (int) ":tt"; block[0] = (int) ":tt";
block[2] = 3; /* length of filename */ block[2] = 3; /* length of filename */
block[1] = 4; /* mode "w" */ block[1] = 4; /* mode "w" */
monitor_stdout = monitor_stderr = do_AngelSWI (AngelSWI_Reason_Open, (void *) block); monitor_stdout = monitor_stderr
= do_AngelSWI (AngelSWI_Reason_Open, (void *) block);
#else #else
int fh; int fh;
const char * name; const char * name;
@ -160,7 +161,9 @@ get_errno (void)
#ifdef ARM_RDI_MONITOR #ifdef ARM_RDI_MONITOR
return do_AngelSWI (AngelSWI_Reason_Errno, NULL); return do_AngelSWI (AngelSWI_Reason_Errno, NULL);
#else #else
asm ("swi %a0" :: "i" (SWI_GetErrno)); register int r0 asm("r0");
asm ("swi %a1" : "=r"(r0): "i" (SWI_GetErrno));
return r0;
#endif #endif
} }
@ -181,31 +184,30 @@ wrap (int result)
/* Returns # chars not! written. */ /* Returns # chars not! written. */
int int
_swiread (int file, _swiread (int file, void * ptr, size_t len)
char * ptr,
int len)
{ {
int fh = remap_handle (file); int fh = remap_handle (file);
#ifdef ARM_RDI_MONITOR #ifdef ARM_RDI_MONITOR
int block[3]; int block[3];
block[0] = fh; block[0] = fh;
block[1] = (int) ptr; block[1] = (int) ptr;
block[2] = len; block[2] = (int) len;
return do_AngelSWI (AngelSWI_Reason_Read, block); return do_AngelSWI (AngelSWI_Reason_Read, block);
#else #else
asm ("mov r0, %1; mov r1, %2;mov r2, %3; swi %a0" register int r0 asm("r0") = fh;
: /* No outputs */ register int r1 asm("r1") = (int) ptr;
: "i"(SWI_Read), "r"(fh), "r"(ptr), "r"(len) register int r2 asm("r2") = (int) len;
: "r0","r1","r2"); asm ("swi %a4"
: "=r" (r0)
: "0"(r0), "r"(r1), "r"(r2), "i"(SWI_Read));
return r0;
#endif #endif
} }
int __attribute__((weak)) int __attribute__((weak))
_read (int file, _read (int file, void * ptr, size_t len)
char * ptr,
int len)
{ {
int slot = findslot (remap_handle (file)); int slot = findslot (remap_handle (file));
int x = _swiread (file, ptr, len); int x = _swiread (file, ptr, len);
@ -220,12 +222,10 @@ _read (int file,
return len - x; return len - x;
} }
int off_t
_swilseek (int file, _swilseek (int file, off_t ptr, int dir)
int ptr,
int dir)
{ {
int res; _off_t res;
int fh = remap_handle (file); int fh = remap_handle (file);
int slot = findslot (fh); int slot = findslot (fh);
#ifdef ARM_RDI_MONITOR #ifdef ARM_RDI_MONITOR
@ -239,33 +239,38 @@ _swilseek (int file,
ptr = openfiles[slot].pos + ptr; ptr = openfiles[slot].pos + ptr;
dir = SEEK_SET; dir = SEEK_SET;
} }
#ifdef ARM_RDI_MONITOR #ifdef ARM_RDI_MONITOR
if (dir == SEEK_END) if (dir == SEEK_END)
{ {
block[0] = fh; block[0] = fh;
ptr += do_AngelSWI (AngelSWI_Reason_FLen, block); ptr += do_AngelSWI (AngelSWI_Reason_FLen, block);
} }
/* This code only does absolute seeks. */ /* This code only does absolute seeks. */
block[0] = remap_handle (file); block[0] = remap_handle (file);
block[1] = ptr; block[1] = ptr;
res = do_AngelSWI (AngelSWI_Reason_Seek, block); res = do_AngelSWI (AngelSWI_Reason_Seek, block);
#else #else
register int r0 asm("r0");
register int r1 asm("r1");
if (dir == SEEK_END) if (dir == SEEK_END)
{ {
asm ("mov r0, %2; swi %a1; mov %0, r0" r0 = (int) fh;
: "=r" (res) asm ("swi %a2"
: "i" (SWI_Flen), "r" (fh) : "=r" (r0)
: "r0"); : "0"(r0), "i" (SWI_Flen));
res = r0;
ptr += res; ptr += res;
} }
/* This code only does absolute seeks. */ /* This code only does absolute seeks. */
asm ("mov r0, %2; mov r1, %3; swi %a1; mov %0, r0" r0 = (int) fh;
: "=r" (res) r1 = (int) ptr;
: "i" (SWI_Seek), "r" (fh), "r" (ptr) asm ("swi %a3"
: "r0", "r1"); : "=r" (r0)
: "0"(r0), "r"(r1), "i" (SWI_Seek));
res = r0;
#endif #endif
if (slot != MAX_OPEN_FILES && res == 0) if (slot != MAX_OPEN_FILES && res == 0)
@ -275,68 +280,64 @@ _swilseek (int file,
return res == 0 ? ptr : -1; return res == 0 ? ptr : -1;
} }
int off_t
_lseek (int file, _lseek (int file, off_t ptr, int dir)
int ptr,
int dir)
{ {
return wrap (_swilseek (file, ptr, dir)); return wrap (_swilseek (file, ptr, dir));
} }
/* Returns #chars not! written. */ /* Returns #chars not! written. */
int int
_swiwrite ( _swiwrite (int file, const void * ptr, size_t len)
int file,
char * ptr,
int len)
{ {
int fh = remap_handle (file); int fh = remap_handle (file);
#ifdef ARM_RDI_MONITOR #ifdef ARM_RDI_MONITOR
int block[3]; int block[3];
block[0] = fh; block[0] = fh;
block[1] = (int) ptr; block[1] = (int) ptr;
block[2] = len; block[2] = (int) len;
return do_AngelSWI (AngelSWI_Reason_Write, block); return do_AngelSWI (AngelSWI_Reason_Write, block);
#else #else
asm ("mov r0, %1; mov r1, %2;mov r2, %3; swi %a0" register int r0 asm("r0") = fh;
: /* No outputs */ register int r1 asm("r1") = (int) ptr;
: "i"(SWI_Write), "r"(fh), "r"(ptr), "r"(len) register int r2 asm("r2") = (int) len;
: "r0","r1","r2");
asm ("swi %a4"
: "=r" (r0)
: "0"(fh), "r"(r1), "r"(r2), "i"(SWI_Write));
return r0;
#endif #endif
} }
int __attribute__((weak)) int __attribute__((weak))
_write (int file, _write (int file, const void * ptr, size_t len)
char * ptr,
int len)
{ {
int slot = findslot (remap_handle (file)); int slot = findslot (remap_handle (file));
int x = _swiwrite (file, ptr,len); int x = _swiwrite (file, ptr, len);
if (x == -1 || x == len) if (x == -1 || x == len)
return error (-1); return error (-1);
if (slot != MAX_OPEN_FILES) if (slot != MAX_OPEN_FILES)
openfiles[slot].pos += len - x; openfiles[slot].pos += len - x;
return len - x; return len - x;
} }
extern int strlen (const char *); extern int strlen (const char *);
int int
_swiopen (const char * path, _swiopen (const char * path, int flags)
int flags)
{ {
int aflags = 0, fh; int aflags = 0, fh;
#ifdef ARM_RDI_MONITOR #ifdef ARM_RDI_MONITOR
int block[3]; int block[3];
#endif #endif
int i = findslot (-1); int i = findslot (-1);
if (i == MAX_OPEN_FILES) if (i == MAX_OPEN_FILES)
return -1; return -1;
@ -360,21 +361,23 @@ _swiopen (const char * path,
aflags &= ~4; /* Can't ask for w AND a; means just 'a'. */ aflags &= ~4; /* Can't ask for w AND a; means just 'a'. */
aflags |= 8; aflags |= 8;
} }
#ifdef ARM_RDI_MONITOR #ifdef ARM_RDI_MONITOR
block[0] = (int) path; block[0] = (int) path;
block[2] = strlen (path); block[2] = strlen (path);
block[1] = aflags; block[1] = aflags;
fh = do_AngelSWI (AngelSWI_Reason_Open, block); fh = do_AngelSWI (AngelSWI_Reason_Open, block);
#else #else
asm ("mov r0,%2; mov r1, %3; swi %a1; mov %0, r0" register int r0 asm("r0") = (int) path;
: "=r"(fh) register int r1 asm("r1") = (int) aflags;;
: "i" (SWI_Open),"r"(path),"r"(aflags) asm ("swi %a3"
: "r0","r1"); : "=r"(r0)
: "0"(r0), "r"(r1), "i" (SWI_Open));
fh = r0;
#endif #endif
if (fh >= 0) if (fh >= 0)
{ {
openfiles[i].handle = fh; openfiles[i].handle = fh;
@ -385,9 +388,7 @@ _swiopen (const char * path,
} }
int int
_open (const char * path, _open (const char * path, int flags, ...)
int flags,
...)
{ {
return wrap (_swiopen (path, flags)); return wrap (_swiopen (path, flags));
} }
@ -397,14 +398,16 @@ _swiclose (int file)
{ {
int myhan = remap_handle (file); int myhan = remap_handle (file);
int slot = findslot (myhan); int slot = findslot (myhan);
if (slot != MAX_OPEN_FILES) if (slot != MAX_OPEN_FILES)
openfiles[slot].handle = -1; openfiles[slot].handle = -1;
#ifdef ARM_RDI_MONITOR #ifdef ARM_RDI_MONITOR
return do_AngelSWI (AngelSWI_Reason_Close, & myhan); return do_AngelSWI (AngelSWI_Reason_Close, & myhan);
#else #else
asm ("mov r0, %1; swi %a0" :: "i" (SWI_Close),"r"(myhan):"r0"); register int r0 asm("r0") = myhan;
asm ("swi %a2" : "=r"(r0): "0"(r0), "i" (SWI_Close));
return r0;
#endif #endif
} }
@ -444,15 +447,14 @@ _exit (int status)
_kill(status, -1); _kill(status, -1);
} }
int pid_t
_getpid (int n) _getpid (void)
{ {
return 1; return (pid_t)1;
n = n;
} }
caddr_t __attribute__((weak)) void * __attribute__((weak))
_sbrk (int incr) _sbrk (ptrdiff_t incr)
{ {
extern char end asm ("end"); /* Defined by the linker. */ extern char end asm ("end"); /* Defined by the linker. */
static char * heap_end; static char * heap_end;
@ -460,9 +462,9 @@ _sbrk (int incr)
if (heap_end == NULL) if (heap_end == NULL)
heap_end = & end; heap_end = & end;
prev_heap_end = heap_end; prev_heap_end = heap_end;
if (heap_end + incr > stack_ptr) if (heap_end + incr > stack_ptr)
{ {
/* Some of the libstdc++-v3 tests rely upon detecting /* Some of the libstdc++-v3 tests rely upon detecting
@ -471,17 +473,17 @@ _sbrk (int incr)
extern void abort (void); extern void abort (void);
_write (1, "_sbrk: Heap and stack collision\n", 32); _write (1, "_sbrk: Heap and stack collision\n", 32);
abort (); abort ();
#else #else
errno = ENOMEM; errno = ENOMEM;
return (caddr_t) -1; return (void *) -1;
#endif #endif
} }
heap_end += incr; heap_end += incr;
return (caddr_t) prev_heap_end; return (void *) prev_heap_end;
} }
extern void memset (struct stat *, int, unsigned int); extern void memset (struct stat *, int, unsigned int);
@ -513,20 +515,23 @@ int _stat (const char *fname, struct stat *st)
} }
int int
_link (void) _link (const char *__path1 __attribute__ ((unused)),
const char *__path2 __attribute__ ((unused)))
{ {
errno = ENOSYS;
return -1; return -1;
} }
int int
_unlink (const char *path) _unlink (const char *path __attribute__ ((unused)))
{ {
#ifdef ARM_RDI_MONITOR #ifdef ARM_RDI_MONITOR
int block[2]; int block[2];
block[0] = path; block[0] = path;
block[1] = strlen(path); block[1] = strlen(path);
return wrap (do_AngelSWI (AngelSWI_Reason_Remove, block)) ? -1 : 0; return wrap (do_AngelSWI (AngelSWI_Reason_Remove, block)) ? -1 : 0;
#else #else
errno = ENOSYS;
return -1; return -1;
#endif #endif
} }
@ -548,9 +553,9 @@ _gettimeofday (struct timeval * tp, void * tzvp)
tp->tv_sec = do_AngelSWI (AngelSWI_Reason_Time,NULL); tp->tv_sec = do_AngelSWI (AngelSWI_Reason_Time,NULL);
#else #else
{ {
int value; register int r0 asm("r0");
asm ("swi %a1; mov %0, r0" : "=r" (value): "i" (SWI_Time) : "r0"); asm ("swi %a1" : "=r" (r0): "i" (SWI_Time));
tp->tv_sec = value; tp->tv_sec = r0;
} }
#endif #endif
tp->tv_usec = 0; tp->tv_usec = 0;
@ -567,15 +572,17 @@ _gettimeofday (struct timeval * tp, void * tzvp)
} }
/* Return a clock that ticks at 100Hz. */ /* Return a clock that ticks at 100Hz. */
clock_t clock_t
_times (struct tms * tp) _times (struct tms * tp)
{ {
clock_t timeval; clock_t timeval;
#ifdef ARM_RDI_MONITOR #ifdef ARM_RDI_MONITOR
timeval = do_AngelSWI (AngelSWI_Reason_Clock,NULL); timeval = do_AngelSWI (AngelSWI_Reason_Clock, NULL);
#else #else
asm ("swi %a1; mov %0, r0" : "=r" (timeval): "i" (SWI_Clock) : "r0"); register int r0 asm("r0");
asm ("swi %a1" : "=r" (r0): "i" (SWI_Clock));
timeval = (clock_t) r0;
#endif #endif
if (tp) if (tp)
@ -585,7 +592,7 @@ _times (struct tms * tp)
tp->tms_cutime = 0; /* user time, children */ tp->tms_cutime = 0; /* user time, children */
tp->tms_cstime = 0; /* system time, children */ tp->tms_cstime = 0; /* system time, children */
} }
return timeval; return timeval;
}; };
@ -619,7 +626,7 @@ _system (const char *s)
if ((e >= 0) && (e < 256)) if ((e >= 0) && (e < 256))
{ {
/* We have to convert e, an exit status to the encoded status of /* We have to convert e, an exit status to the encoded status of
the command. To avoid hard coding the exit status, we simply the command. To avoid hard coding the exit status, we simply
loop until we find the right position. */ loop until we find the right position. */
int exit_code; int exit_code;
@ -645,7 +652,7 @@ _rename (const char * oldpath, const char * newpath)
block[2] = newpath; block[2] = newpath;
block[3] = strlen(newpath); block[3] = strlen(newpath);
return wrap (do_AngelSWI (AngelSWI_Reason_Rename, block)) ? -1 : 0; return wrap (do_AngelSWI (AngelSWI_Reason_Rename, block)) ? -1 : 0;
#else #else
errno = ENOSYS; errno = ENOSYS;
return -1; return -1;
#endif #endif