From 847e89f8e1f05115b9f719a319f7f7405f246e9b Mon Sep 17 00:00:00 2001 From: Jeff Johnston Date: Fri, 10 Aug 2007 19:36:46 +0000 Subject: [PATCH] 2007-08-10 Carlos O'Donell 2007-07-12 Daniel Jacobowitz * arm/syscalls.c (_stat): Use _close * arm/syscalls.c (struct poslog): Rename to... (struct fdent): ... this. (FILE_HANDLE_OFFSET): Remove. (findslot): Return a struct fdent* if fd is valid, otherwise return NULL. (newslot): New function. (remap_handle): Remove. (initialise_monitor_handles): Use stdout as fallback for stderr. (wrap): Rename to... (checkerror): ... this. (_swiread): Use checkerror() for the return of SWI calls. Correct the use of r0. (_read): Use findslot(). Return EBADF on bad handle. (_swilseek): Call findslot(). Check for valid whence. Check for negative offset when using SEEK_CUR, and check for overflow. Use checkerror(). Check *_Flen calls for errors. (_swiwrite): Correct the use of r0. (_write): Call findslot(). (_swiopen): Call findslot(). Check for valid flags. Use checkerror(). Call newslot(). Handle O_TRUNC, and O_WRONLY. Return index into openfiles[] for fd. (_swiclose): Correct the use of r0. (_close): Handle stderr == stdout case. Only reclaim handle if _swiclose succeeded. (_getpid): Use __attribute__((unused)). (_sbrk): Fix formatting. (_swistat): New function. (_stat): Call _swistat(). (_fstat): Call _swistat(). (_unlink): Correct the use of r0. (isatty): Call finslot(). Correct the use of r0. (_system): Call checkerror(). Correct the use of r0. (_rename): Correct the use of r0. --- libgloss/ChangeLog | 41 ++- libgloss/arm/syscalls.c | 535 +++++++++++++++++++++++++++------------- 2 files changed, 406 insertions(+), 170 deletions(-) diff --git a/libgloss/ChangeLog b/libgloss/ChangeLog index 3fce80858..e1aa5c35d 100644 --- a/libgloss/ChangeLog +++ b/libgloss/ChangeLog @@ -1,8 +1,43 @@ -2007-07-13 Kevin Buettner +2007-08-10 Carlos O'Donell - * mep/fmax.ld, mep/gmap_default.ld, mep/min.ld, mep/simple.ld - (.gcc_except_table): Add pattern for .gcc_except_table.*. + 2007-07-12 Daniel Jacobowitz + * arm/syscalls.c (_stat): Use _close + + * arm/syscalls.c (struct poslog): Rename to... + (struct fdent): ... this. + (FILE_HANDLE_OFFSET): Remove. + (findslot): Return a struct fdent* if fd is valid, otherwise return NULL. + (newslot): New function. + (remap_handle): Remove. + (initialise_monitor_handles): Use stdout as fallback for stderr. + (wrap): Rename to... + (checkerror): ... this. + (_swiread): Use checkerror() for the return of SWI calls. Correct the use of r0. + (_read): Use findslot(). Return EBADF on bad handle. + (_swilseek): Call findslot(). Check for valid whence. Check for negative offset when using + SEEK_CUR, and check for overflow. Use checkerror(). Check *_Flen calls for errors. + (_swiwrite): Correct the use of r0. + (_write): Call findslot(). + (_swiopen): Call findslot(). Check for valid flags. Use checkerror(). Call newslot(). + Handle O_TRUNC, and O_WRONLY. Return index into openfiles[] for fd. + (_swiclose): Correct the use of r0. + (_close): Handle stderr == stdout case. Only reclaim handle if _swiclose succeeded. + (_getpid): Use __attribute__((unused)). + (_sbrk): Fix formatting. + (_swistat): New function. + (_stat): Call _swistat(). + (_fstat): Call _swistat(). + (_unlink): Correct the use of r0. + (isatty): Call finslot(). Correct the use of r0. + (_system): Call checkerror(). Correct the use of r0. + (_rename): Correct the use of r0. + +2007-07-13 Kevin Buettner + + * mep/fmax.ld, mep/gmap_default.ld, mep/min.ld, mep/simple.ld (.gcc_except_table): Add pattern + for .gcc_except_table.*. + 2007-07-06 Jeff Johnston * arm/syscalls.c (gettimeofday): Change to POSIX signature diff --git a/libgloss/arm/syscalls.c b/libgloss/arm/syscalls.c index 1ab383073..0e0a5dae0 100644 --- a/libgloss/arm/syscalls.c +++ b/libgloss/arm/syscalls.c @@ -27,6 +27,7 @@ int _unlink _PARAMS ((const char *)); int _link _PARAMS ((void)); int _stat _PARAMS ((const char *, struct stat *)); int _fstat _PARAMS ((int, struct stat *)); +int _swistat _PARAMS ((int fd, struct stat * st)); caddr_t _sbrk _PARAMS ((int)); int _getpid _PARAMS ((int)); int _close _PARAMS ((int)); @@ -42,11 +43,39 @@ int _read _PARAMS ((int, char *, int)); int _swiread _PARAMS ((int, char *, int)); void initialise_monitor_handles _PARAMS ((void)); -static int wrap _PARAMS ((int)); +static int checkerror _PARAMS ((int)); static int error _PARAMS ((int)); static int get_errno _PARAMS ((void)); -static int remap_handle _PARAMS ((int)); -static int findslot _PARAMS ((int)); + +/* Struct used to keep track of the file position, just so we + can implement fseek(fh,x,SEEK_CUR). */ +struct fdent +{ + int handle; + int pos; +}; + +#define MAX_OPEN_FILES 20 + +/* User file descriptors (fd) are integer indexes into + the openfiles[] array. Error checking is done by using + findslot(). + + This openfiles array is manipulated directly by only + these 5 functions: + + findslot() - Translate entry. + newslot() - Find empty entry. + initilise_monitor_handles() - Initialize entries. + _swiopen() - Initialize entry. + _close() - Handle stdout == stderr case. + + Every other function must use findslot(). */ + +static struct fdent openfiles [MAX_OPEN_FILES]; + +static struct fdent* findslot _PARAMS ((int)); +static int newslot _PARAMS ((void)); /* Register name faking - works in collusion with the linker. */ register char * stack_ptr asm ("sp"); @@ -62,49 +91,44 @@ extern void _EXFUN(__sinit,(struct _reent *)); } \ while (0) -/* Adjust our internal handles to stay away from std* handles. */ -#define FILE_HANDLE_OFFSET (0x20) - static int monitor_stdin; static int monitor_stdout; static int monitor_stderr; -/* Struct used to keep track of the file position, just so we - can implement fseek(fh,x,SEEK_CUR). */ -typedef struct -{ - int handle; - int pos; -} -poslog; - -#define MAX_OPEN_FILES 20 -static poslog openfiles [MAX_OPEN_FILES]; - -static int -findslot (int fh) -{ - int i; - for (i = 0; i < MAX_OPEN_FILES; i ++) - if (openfiles[i].handle == fh) - break; - return i; -} - -/* Function to convert std(in|out|err) handles to internal versions. */ -static int -remap_handle (int fh) +/* Return a pointer to the structure associated with + the user file descriptor fd. */ +static struct fdent* +findslot (int fd) { CHECK_INIT(_REENT); - if (fh == STDIN_FILENO) - return monitor_stdin; - if (fh == STDOUT_FILENO) - return monitor_stdout; - if (fh == STDERR_FILENO) - return monitor_stderr; + /* User file descriptor is out of range. */ + if ((unsigned int)fd >= MAX_OPEN_FILES) + return NULL; - return fh - FILE_HANDLE_OFFSET; + /* User file descriptor is open? */ + if (openfiles[fd].handle == -1) + return NULL; + + /* Valid. */ + return &openfiles[fd]; +} + +/* Return the next lowest numbered free file + structure, or -1 if we can't find one. */ +static int +newslot (void) +{ + int i; + + for (i = 0; i < MAX_OPEN_FILES; i++) + if (openfiles[i].handle == -1) + break; + + if (i == MAX_OPEN_FILES) + return -1; + + return i; } void @@ -165,6 +189,10 @@ initialise_monitor_handles (void) monitor_stderr = fh; #endif + /* If we failed to open stderr, redirect to stdout. */ + if (monitor_stderr == -1) + monitor_stderr = monitor_stdout; + for (i = 0; i < MAX_OPEN_FILES; i ++) openfiles[i].handle = -1; @@ -188,6 +216,7 @@ get_errno (void) #endif } +/* Set errno and return result. */ static int error (int result) { @@ -195,21 +224,24 @@ error (int result) return result; } +/* Check the return and set errno appropriately. */ static int -wrap (int result) +checkerror (int result) { if (result == -1) return error (-1); return result; } -/* Returns # chars not! written. */ +/* fh, is a valid internal file handle. + ptr, is a null terminated string. + len, is the length in bytes to read. + Returns the number of bytes *not* written. */ int -_swiread (int file, +_swiread (int fh, char * ptr, int len) { - int fh = remap_handle (file); #ifdef ARM_RDI_MONITOR int block[3]; @@ -217,104 +249,152 @@ _swiread (int file, block[1] = (int) ptr; block[2] = len; - return do_AngelSWI (AngelSWI_Reason_Read, block); + return checkerror (do_AngelSWI (AngelSWI_Reason_Read, block)); #else - asm ("mov r0, %1; mov r1, %2;mov r2, %3; swi %a0" - : /* No outputs */ - : "i"(SWI_Read), "r"(fh), "r"(ptr), "r"(len) - : "r0","r1","r2"); + register r0 asm("r0"); + register r1 asm("r1"); + register r2 asm("r2"); + r0 = fh; + r1 = (int)ptr; + r2 = len; + asm ("swi %a4" + : "=r" (r0) + : "0"(r0), "r"(r1), "r"(r2), "i"(SWI_Read)); + return checkerror (r0); #endif } +/* fd, is a valid user file handle. + Translates the return of _swiread into + bytes read. */ int -_read (int file, +_read (int fd, char * ptr, int len) { - int slot = findslot (remap_handle (file)); - int x = _swiread (file, ptr, len); + int res; + struct fdent *pfd; - if (x < 0) - return error (-1); + pfd = findslot (fd); + if (pfd == NULL) + { + errno = EBADF; + return -1; + } - if (slot != MAX_OPEN_FILES) - openfiles [slot].pos += len - x; + res = _swiread (pfd->handle, ptr, len); - /* x == len is not an error, at least if we want feof() to work. */ - return len - x; + if (res == -1) + return res; + + pfd->pos += len - res; + + /* res == len is not an error, + at least if we want feof() to work. */ + return len - res; } +/* fd, is a user file descriptor. */ int -_swilseek (int file, - int ptr, - int dir) +_swilseek (int fd, + int ptr, + int dir) { int res; - int fh = remap_handle (file); - int slot = findslot (fh); -#ifdef ARM_RDI_MONITOR - int block[2]; -#endif + struct fdent *pfd; + /* Valid file descriptor? */ + pfd = findslot (fd); + if (pfd == NULL) + { + errno = EBADF; + return -1; + } + + /* Valid whence? */ + if ((dir != SEEK_CUR) + && (dir != SEEK_SET) + && (dir != SEEK_END)) + { + errno = EINVAL; + return -1; + } + + /* Convert SEEK_CUR to SEEK_SET */ if (dir == SEEK_CUR) { - if (slot == MAX_OPEN_FILES) - return -1; - ptr = openfiles[slot].pos + ptr; + ptr = pfd->pos + ptr; + /* The resulting file offset would be negative. */ + if (ptr < 0) + { + errno = EINVAL; + if ((pfd->pos > 0) && (ptr > 0)) + errno = EOVERFLOW; + return -1; + } dir = SEEK_SET; } - + #ifdef ARM_RDI_MONITOR + int block[2]; if (dir == SEEK_END) { - block[0] = fh; - ptr += do_AngelSWI (AngelSWI_Reason_FLen, block); + block[0] = pfd->handle; + res = checkerror (do_AngelSWI (AngelSWI_Reason_FLen, block)); + if (res == -1) + return -1; + ptr += res; } /* This code only does absolute seeks. */ - block[0] = remap_handle (file); + block[0] = pfd->handle; block[1] = ptr; - res = do_AngelSWI (AngelSWI_Reason_Seek, block); + res = checkerror (do_AngelSWI (AngelSWI_Reason_Seek, block)); #else if (dir == SEEK_END) { asm ("mov r0, %2; swi %a1; mov %0, r0" : "=r" (res) - : "i" (SWI_Flen), "r" (fh) + : "i" (SWI_Flen), "r" (pfd->handle) : "r0"); + checkerror (res); + if (res == -1) + return -1; ptr += res; } /* This code only does absolute seeks. */ asm ("mov r0, %2; mov r1, %3; swi %a1; mov %0, r0" : "=r" (res) - : "i" (SWI_Seek), "r" (fh), "r" (ptr) + : "i" (SWI_Seek), "r" (pfd->handle), "r" (ptr) : "r0", "r1"); + checkerror (res); #endif - - if (slot != MAX_OPEN_FILES && res == 0) - openfiles[slot].pos = ptr; - - /* This is expected to return the position in the file. */ - return res == 0 ? ptr : -1; + /* At this point ptr is the current file position. */ + if (res >= 0) + { + pfd->pos = ptr; + return ptr; + } + else + return -1; } -int -_lseek (int file, +_lseek (int fd, int ptr, int dir) { - return wrap (_swilseek (file, ptr, dir)); + return _swilseek (fd, ptr, dir); } -/* Returns #chars not! written. */ +/* fh, is a valid internal file handle. + Returns the number of bytes *not* written. */ int _swiwrite ( - int file, + int fh, char * ptr, int len) { - int fh = remap_handle (file); #ifdef ARM_RDI_MONITOR int block[3]; @@ -322,64 +402,103 @@ _swiwrite ( block[1] = (int) ptr; block[2] = len; - return do_AngelSWI (AngelSWI_Reason_Write, block); + return checkerror (do_AngelSWI (AngelSWI_Reason_Write, block)); #else - asm ("mov r0, %1; mov r1, %2;mov r2, %3; swi %a0" - : /* No outputs */ - : "i"(SWI_Write), "r"(fh), "r"(ptr), "r"(len) - : "r0","r1","r2"); + register r0 asm("r0"); + register r1 asm("r1"); + register r2 asm("r2"); + r0 = fh; + r1 = (int)ptr; + r2 = len; + asm ("swi %a4" + : "=r" (r0) + : "0"(r0), "r"(r1), "r"(r2), "i"(SWI_Write)); + return checkerror (r0); #endif } +/* fd, is a user file descriptor. */ int -_write (int file, +_write (int fd, char * ptr, int len) { - int slot = findslot (remap_handle (file)); - int x = _swiwrite (file, ptr,len); + int res; + struct fdent *pfd; - if (x == -1 || x == len) - return error (-1); + pfd = findslot (fd); + if (pfd == NULL) + { + errno = EBADF; + return -1; + } + + res = _swiwrite (pfd->handle, ptr,len); + + /* Clearly an error. */ + if (res < 0) + return -1; + + pfd->pos += len - res; + + /* We wrote 0 bytes? + Retrieve errno just in case. */ + if ((len - res) == 0) + return error (0); - if (slot != MAX_OPEN_FILES) - openfiles[slot].pos += len - x; - - return len - x; + return (len - res); } int -_swiopen (const char * path, - int flags) +_swiopen (const char * path, int flags) { int aflags = 0, fh; #ifdef ARM_RDI_MONITOR int block[3]; #endif - int i = findslot (-1); - - if (i == MAX_OPEN_FILES) - return -1; + int fd = newslot (); - /* The flags are Unix-style, so we need to convert them. */ + if (fd == -1) + { + errno = EMFILE; + return -1; + } + + /* It is an error to open a file that already exists. */ + if ((flags & O_CREAT) + && (flags & O_EXCL)) + { + struct stat st; + int res; + res = _stat (path, &st); + if (res != -1) + { + errno = EEXIST; + return -1; + } + } + + /* The flags are Unix-style, so we need to convert them. */ #ifdef O_BINARY if (flags & O_BINARY) aflags |= 1; #endif + + /* In O_RDONLY we expect aflags == 0. */ - if (flags & O_RDWR) + if (flags & O_RDWR) aflags |= 2; - if (flags & O_CREAT) - aflags |= 4; - - if (flags & O_TRUNC) + if ((flags & O_CREAT) + || (flags & O_TRUNC) + || (flags & O_WRONLY)) aflags |= 4; if (flags & O_APPEND) { - aflags &= ~4; /* Can't ask for w AND a; means just 'a'. */ + /* Can't ask for w AND a; means just 'a'. */ + aflags &= ~4; aflags |= 8; } @@ -397,58 +516,83 @@ _swiopen (const char * path, : "r0","r1"); #endif + /* Return a user file descriptor or an error. */ if (fh >= 0) { - openfiles[i].handle = fh; - openfiles[i].pos = 0; + openfiles[fd].handle = fh; + openfiles[fd].pos = 0; + return fd; } - - return fh >= 0 ? fh + FILE_HANDLE_OFFSET : error (fh); + else + return error (fh); } int -_open (const char * path, - int flags, - ...) +_open (const char * path, int flags, ...) { - return wrap (_swiopen (path, flags)); + return _swiopen (path, flags); } +/* fh, is a valid internal file handle. */ int -_swiclose (int file) +_swiclose (int fh) { - int myhan = remap_handle (file); - int slot = findslot (myhan); - - if (slot != MAX_OPEN_FILES) - openfiles[slot].handle = -1; - #ifdef ARM_RDI_MONITOR - return do_AngelSWI (AngelSWI_Reason_Close, & myhan); + return checkerror (do_AngelSWI (AngelSWI_Reason_Close, &fh)); #else - asm ("mov r0, %1; swi %a0" :: "i" (SWI_Close),"r"(myhan):"r0"); + register r0 asm("r0"); + r0 = fh; + asm ("swi %a2" + : "=r"(r0) + : "0"(r0), "i" (SWI_Close)); + return checkerror (r0); #endif } +/* fd, is a user file descriptor. */ int -_close (int file) +_close (int fd) { - return wrap (_swiclose (file)); + int res; + struct fdent *pfd; + + pfd = findslot (fd); + if (pfd == NULL) + { + errno = EBADF; + return -1; + } + + /* Handle stderr == stdout. */ + if ((fd == 1 || fd == 2) + && (openfiles[1].handle == openfiles[2].handle)) + { + pfd->handle = -1; + return 0; + } + + /* Attempt to close the handle. */ + res = _swiclose (pfd->handle); + + /* Reclaim handle? */ + if (res == 0) + pfd->handle = -1; + + return res; } int __attribute__((weak)) -_getpid (int n) +_getpid (int n __attribute__ ((unused))) { return 1; - n = n; } caddr_t _sbrk (int incr) { - extern char end asm ("end"); /* Defined by the linker. */ + extern char end asm ("end"); /* Defined by the linker. */ static char * heap_end; - char * prev_heap_end; + char * prev_heap_end; if (heap_end == NULL) heap_end = & end; @@ -476,31 +620,60 @@ _sbrk (int incr) return (caddr_t) prev_heap_end; } +int +_swistat (int fd, struct stat * st) +{ + struct fdent *pfd; + int res; + + pfd = findslot (fd); + if (pfd == NULL) + { + errno = EBADF; + return -1; + } + + /* Always assume a character device, + with 1024 byte blocks. */ + st->st_mode |= S_IFCHR; + st->st_blksize = 1024; +#ifdef ARM_RDI_MONITOR + res = checkerror (do_AngelSWI (AngelSWI_Reason_FLen, &pfd->handle)); +#else + asm ("mov r0, %2; swi %a1; mov %0, r0" + : "=r" (res) + : "i" (SWI_Flen), "r" (pfd->handle) + : "r0"); + checkerror (res); +#endif + if (res == -1) + return -1; + /* Return the file size. */ + st->st_size = res; + return 0; +} + int __attribute__((weak)) -_fstat (int file, struct stat * st) +_fstat (int fd, struct stat * st) { memset (st, 0, sizeof (* st)); - st->st_mode = S_IFCHR; - st->st_blksize = 1024; - return 0; - file = file; + return _swistat (fd, st); } int __attribute__((weak)) _stat (const char *fname, struct stat *st) { - int file; - - /* The best we can do is try to open the file readonly. If it exists, - then we can guess a few things about it. */ - if ((file = _open (fname, O_RDONLY)) < 0) - return -1; - + int fd, res; memset (st, 0, sizeof (* st)); - st->st_mode = S_IFREG | S_IREAD; - st->st_blksize = 1024; - _swiclose (file); /* Not interested in the error. */ - return 0; + /* The best we can do is try to open the file readonly. + If it exists, then we can guess a few things about it. */ + if ((fd = _open (fname, O_RDONLY)) == -1) + return -1; + st->st_mode |= S_IFREG | S_IREAD; + res = _swistat (fd, st); + /* Not interested in the error. */ + _close (fd); + return res; } int __attribute__((weak)) @@ -513,15 +686,23 @@ _link (void) int _unlink (const char *path) { + int res; #ifdef ARM_RDI_MONITOR int block[2]; block[0] = (int)path; block[1] = strlen(path); - return wrap (do_AngelSWI (AngelSWI_Reason_Remove, block)) ? -1 : 0; + res = do_AngelSWI (AngelSWI_Reason_Remove, block); #else - (void)path; - asm ("swi %a0" :: "i" (SWI_Remove)); + register r0 asm("r0"); + r0 = (int)path; + asm ("swi %a2" + : "=r"(r0) + : "0"(r0), "i" (SWI_Remove)); + res = r0; #endif + if (res == -1) + return error (res); + return 0; } int @@ -588,14 +769,24 @@ _times (struct tms * tp) int _isatty (int fd) { - int fh = remap_handle (fd); + struct fdent *pfd; + + pfd = findslot (fd); + if (pfd == NULL) + { + errno = EBADF; + return -1; + } + #ifdef ARM_RDI_MONITOR - return wrap (do_AngelSWI (AngelSWI_Reason_IsTTY, &fh)); + return checkerror (do_AngelSWI (AngelSWI_Reason_IsTTY, &pfd->handle)); #else - asm ("mov r0, %1; swi %a0" - : /* No outputs */ - : "i" (SWI_IsTTY), "r"(fh) - : "r0"); + register r0 asm("r0"); + r0 = pfd->handle; + asm ("swi %a2" + : "=r" (r0) + : "0"(r0), "i" (SWI_IsTTY)); + return checkerror (r0); #endif } @@ -613,7 +804,7 @@ _system (const char *s) return 1; /* maybe there is a shell available? we can hope. :-P */ block[0] = (int)s; block[1] = strlen (s); - e = wrap (do_AngelSWI (AngelSWI_Reason_System, block)); + e = checkerror (do_AngelSWI (AngelSWI_Reason_System, block)); if ((e >= 0) && (e < 256)) { /* We have to convert e, an exit status to the encoded status of @@ -626,8 +817,12 @@ _system (const char *s) } return e; #else - (void)s; - asm ("swi %a0" :: "i" (SWI_CLI)); + register r0 asm("r0"); + r0 = (int)s; + asm ("swi %a2" + : "=r" (r0) + : "0"(r0), "i" (SWI_CLI)); + return checkerror (r0); #endif } @@ -640,9 +835,15 @@ _rename (const char * oldpath, const char * newpath) block[1] = strlen(oldpath); block[2] = (int)newpath; block[3] = strlen(newpath); - return wrap (do_AngelSWI (AngelSWI_Reason_Rename, block)) ? -1 : 0; + return checkerror (do_AngelSWI (AngelSWI_Reason_Rename, block)) ? -1 : 0; #else - (void)oldpath; (void)newpath; - asm ("swi %a0" :: "i" (SWI_Rename)); + register r0 asm("r0"); + register r1 asm("r1"); + r0 = (int)oldpath; + r1 = (int)newpath; + asm ("swi %a3" + : "=r" (r0) + : "0" (r0), "r" (r1), "i" (SWI_Rename)); + return checkerror (r0); #endif }