diff --git a/src/console.asm b/src/console.asm index a7c5164..b1d9102 100644 --- a/src/console.asm +++ b/src/console.asm @@ -112,9 +112,10 @@ eprintf: ; See printf description above, + ; 1) Return value can be amount of printed characters or -errno (eg if bad FD was passed, -EBADF is returned) ; 2) FD has to be passed via RAX (this is clearly an INTERNAL function so passed arguments are slightly different, that is, RAX required for FD) -; 3) FOR DEVS: When writing an I/O function that calls this wrapper, make sure that: +; 3) When writing a function(/wrapper) that calls this function, make sure that: ; - That function has function prologue (ie push rbp + mov rbp, rsp) ; - __INTERNAL_fmt is called via CALL and not a simple JMP like in printf +; - Arguments from function/wrapper are all shifted ; This is because in such I/O functions, first argument should be file descriptor, and following SYS V ABI, that first argument is passed to RDI ; However since __INTERNAL_fmt expects FD via RAX, all arguments have to be shifted. Due to this, argument in R9 becomes a stack argument ; Because of that, __INTERNAL_fmt has to load from stack with a different offset; +24 bytes extra (extra +8 for function call, extra +8 for function prologue and extra +8 to account for possible R9 arg becoming a stack arg) @@ -126,8 +127,8 @@ __INTERNAL_fmt: jmp %%continue %%fromStack: cmp r15, FD_stderr - jle %%stackNoShift ;simple jle (for test r15,2); entry of this wrapper quits early if passed FD is less than 1, so this simple check is safe enough - mov %1, [rbp + (RBP_OFFSET_CALLER*2 + SIZE_QWORD) + ((r14-5) * SIZE_QWORD)] ;non-printf functions calling __INTERNAL_fmt require RDI to be FD, all args shifted and rbp+RBP_OFFSET_CALLER to r9. Also requires function prologue and a CALL to __INTERNAL_fmt (not a JMP like in printf); hence the RBP_OFFSET_CALLER*2 + jle %%stackNoShift + mov %1, [rbp + (RBP_OFFSET_CALLER*2 + SIZE_QWORD) + ((r14-5) * SIZE_QWORD)] jmp %%continue %%stackNoShift: mov %1, [rbp + RBP_OFFSET_CALLER + ((r14-5) * SIZE_QWORD)] diff --git a/src/constants.asm b/src/constants.asm index e40e4d8..79ae552 100644 --- a/src/constants.asm +++ b/src/constants.asm @@ -1,186 +1,5 @@ -section .rodata - ; syscall - NR_read equ 0 - NR_write equ 1 - NR_open equ 2 - NR_close equ 3 - NR_stat equ 4 - NR_fstat equ 5 - NR_lstat equ 6 - NR_exit equ 60 - NR_creat equ 85 - NR_umask equ 95 - - ; file descriptors - FD_stdin equ 0 - FD_stdout equ 1 - FD_stderr equ 2 - - ; ASCII - EOS equ 0 - TAB equ 9 - NL equ 10 - DQUO equ 34 - - ; Sizes - RBP_OFFSET_CALLER equ 16 - SIZE_QWORD equ 8 - SIZE_DWORD equ 4 - SIZE_WORD equ 2 - SIZE_BYTE equ 1 - - MIN_UINT64 equ 0 - MIN_UINT32 equ 0 - MIN_UINT16 equ 0 - MIN_UINT8 equ 0 - - MAX_UINT64 equ 0xFFFFFFFFFFFFFFFF - MAX_UINT32 equ 0xFFFFFFFF - MAX_UINT16 equ 0xFFFF - MAX_UINT8 equ 0xFF - - MIN_INT64 equ ~0x7FFFFFFFFFFFFFFF - MIN_INT32 equ ~0x7FFFFFFF - MIN_INT16 equ ~0x7FFF - MIN_INT8 equ ~0x7F - - MAX_INT64 equ 0x7FFFFFFFFFFFFFFF - MAX_INT32 equ 0x7FFFFFFF - MAX_INT16 equ 0x7FFF - MAX_INT8 equ 0x7F - - ; System error codes - ENONE equ 0 - EPERM equ 1 - ENOENT equ 2 - ESRCH equ 3 - EINTR equ 4 - EIO equ 5 - ENXIO equ 6 - E2BIG equ 7 - ENOEXEC equ 8 - EBADF equ 9 - ECHILD equ 10 - EAGAIN equ 11 - ENOMEM equ 12 - EACCES equ 13 - EFAULT equ 14 - ENOTBLK equ 15 - EBUSY equ 16 - EEXIST equ 17 - EXDEV equ 18 - ENODEV equ 19 - ENOTDIR equ 20 - EISDIR equ 21 - EINVAL equ 22 - ENFILE equ 23 - EMFILE equ 24 - ENOTTY equ 25 - ETXTBSY equ 26 - EFBIG equ 27 - ENOSPC equ 28 - ESPIPE equ 29 - EROFS equ 30 - EMLINK equ 31 - EPIPE equ 32 - EDOM equ 33 - ERANGE equ 34 - EDEADLK equ 35 - ENAMETOOLONG equ 36 - ENOLCK equ 37 - ENOSYS equ 38 - ENOTEMPTY equ 39 - ELOOP equ 40 - EWOULDBLOCK equ EAGAIN - ENOMSG equ 42 - EIDRM equ 43 - ECHRNG equ 44 - EL2NSYNC equ 45 - EL3HLT equ 46 - EL3RST equ 47 - ELNRNG equ 48 - EUNATCH equ 49 - ENOCSI equ 50 - EL2HLT equ 51 - EBADE equ 52 - EBADR equ 53 - EXFULL equ 54 - ENOANO equ 55 - EBADRQC equ 56 - EBADSLT equ 57 - EDEADLOCK equ EDEADLK - EBFONT equ 59 - ENOSTR equ 60 - ENODATA equ 61 - ETIME equ 62 - ENOSR equ 63 - ENONET equ 64 - ENOPKG equ 65 - EREMOTE equ 66 - ENOLINK equ 67 - EADV equ 68 - ESRMNT equ 69 - ECOMM equ 70 - EPROTO equ 71 - EMULTIHOP equ 72 - EDOTDOT equ 73 - EBADMSG equ 74 - EOVERFLOW equ 75 - ENOTUNIQ equ 76 - EBADFD equ 77 - EREMCHG equ 78 - ELIBACC equ 79 - ELIBBAD equ 80 - ELIBSCN equ 81 - ELIBMAX equ 82 - ELIBEXEC equ 83 - EILSEQ equ 84 - ERESTART equ 85 - ESTRPIPE equ 86 - EUSERS equ 87 - ENOTSOCK equ 88 - EDESTADDRREQ equ 89 - EMSGSIZE equ 90 - EPROTOTYPE equ 91 - ENOPROTOOPT equ 92 - EPROTONOSUPPORT equ 93 - ESOCKTNOSUPPORT equ 94 - EOPNOTSUPP equ 95 - EPFNOSUPPORT equ 96 - EAFNOSUPPORT equ 97 - EADDRINUSE equ 98 - EADDRNOTAVAIL equ 99 - ENETDOWN equ 100 - ENETUNREACH equ 101 - ENETRESET equ 102 - ECONNABORTED equ 103 - ECONNRESET equ 104 - ENOBUFS equ 105 - EISCONN equ 106 - ENOTCONN equ 107 - ESHUTDOWN equ 108 - ETOOMANYREFS equ 109 - ETIMEDOUT equ 110 - ECONNREFUSED equ 111 - EHOSTDOWN equ 112 - EHOSTUNREACH equ 113 - EALREADY equ 114 - EINPROGRESS equ 115 - ESTALE equ 116 - EUCLEAN equ 117 - ENOTNAM equ 118 - ENAVAIL equ 119 - EISNAM equ 120 - EREMOTEIO equ 121 - EDQUOT equ 122 - ENOMEDIUM equ 123 - EMEDIUMTYPE equ 124 - ECANCELED equ 125 - ENOKEY equ 126 - EKEYEXPIRED equ 127 - EKEYREVOKED equ 128 - EKEYREJECTED equ 129 - EOWNERDEAD equ 130 - ENOTRECOVERABLE equ 131 - ERFKILL equ 132 - EHWPOISON equ 133 +%include "src/constants/common.asm" +%include "src/constants/syscalls.asm" +%include "src/constants/errors.asm" +%include "src/constants/sizes.asm" +%include "src/constants/file.asm" diff --git a/src/constants/common.asm b/src/constants/common.asm new file mode 100644 index 0000000..51a70ac --- /dev/null +++ b/src/constants/common.asm @@ -0,0 +1,11 @@ +section .rodata + ; file descriptors + FD_stdin equ 0 + FD_stdout equ 1 + FD_stderr equ 2 + + ; ASCII + EOS equ 0 + TAB equ 9 + NL equ 10 + DQUO equ 34 diff --git a/src/constants/errors.asm b/src/constants/errors.asm new file mode 100644 index 0000000..919dde4 --- /dev/null +++ b/src/constants/errors.asm @@ -0,0 +1,135 @@ +section .rodata + ENONE equ 0 + EPERM equ 1 + ENOENT equ 2 + ESRCH equ 3 + EINTR equ 4 + EIO equ 5 + ENXIO equ 6 + E2BIG equ 7 + ENOEXEC equ 8 + EBADF equ 9 + ECHILD equ 10 + EAGAIN equ 11 + ENOMEM equ 12 + EACCES equ 13 + EFAULT equ 14 + ENOTBLK equ 15 + EBUSY equ 16 + EEXIST equ 17 + EXDEV equ 18 + ENODEV equ 19 + ENOTDIR equ 20 + EISDIR equ 21 + EINVAL equ 22 + ENFILE equ 23 + EMFILE equ 24 + ENOTTY equ 25 + ETXTBSY equ 26 + EFBIG equ 27 + ENOSPC equ 28 + ESPIPE equ 29 + EROFS equ 30 + EMLINK equ 31 + EPIPE equ 32 + EDOM equ 33 + ERANGE equ 34 + EDEADLK equ 35 + ENAMETOOLONG equ 36 + ENOLCK equ 37 + ENOSYS equ 38 + ENOTEMPTY equ 39 + ELOOP equ 40 + EWOULDBLOCK equ EAGAIN + ENOMSG equ 42 + EIDRM equ 43 + ECHRNG equ 44 + EL2NSYNC equ 45 + EL3HLT equ 46 + EL3RST equ 47 + ELNRNG equ 48 + EUNATCH equ 49 + ENOCSI equ 50 + EL2HLT equ 51 + EBADE equ 52 + EBADR equ 53 + EXFULL equ 54 + ENOANO equ 55 + EBADRQC equ 56 + EBADSLT equ 57 + EDEADLOCK equ EDEADLK + EBFONT equ 59 + ENOSTR equ 60 + ENODATA equ 61 + ETIME equ 62 + ENOSR equ 63 + ENONET equ 64 + ENOPKG equ 65 + EREMOTE equ 66 + ENOLINK equ 67 + EADV equ 68 + ESRMNT equ 69 + ECOMM equ 70 + EPROTO equ 71 + EMULTIHOP equ 72 + EDOTDOT equ 73 + EBADMSG equ 74 + EOVERFLOW equ 75 + ENOTUNIQ equ 76 + EBADFD equ 77 + EREMCHG equ 78 + ELIBACC equ 79 + ELIBBAD equ 80 + ELIBSCN equ 81 + ELIBMAX equ 82 + ELIBEXEC equ 83 + EILSEQ equ 84 + ERESTART equ 85 + ESTRPIPE equ 86 + EUSERS equ 87 + ENOTSOCK equ 88 + EDESTADDRREQ equ 89 + EMSGSIZE equ 90 + EPROTOTYPE equ 91 + ENOPROTOOPT equ 92 + EPROTONOSUPPORT equ 93 + ESOCKTNOSUPPORT equ 94 + EOPNOTSUPP equ 95 + EPFNOSUPPORT equ 96 + EAFNOSUPPORT equ 97 + EADDRINUSE equ 98 + EADDRNOTAVAIL equ 99 + ENETDOWN equ 100 + ENETUNREACH equ 101 + ENETRESET equ 102 + ECONNABORTED equ 103 + ECONNRESET equ 104 + ENOBUFS equ 105 + EISCONN equ 106 + ENOTCONN equ 107 + ESHUTDOWN equ 108 + ETOOMANYREFS equ 109 + ETIMEDOUT equ 110 + ECONNREFUSED equ 111 + EHOSTDOWN equ 112 + EHOSTUNREACH equ 113 + EALREADY equ 114 + EINPROGRESS equ 115 + ESTALE equ 116 + EUCLEAN equ 117 + ENOTNAM equ 118 + ENAVAIL equ 119 + EISNAM equ 120 + EREMOTEIO equ 121 + EDQUOT equ 122 + ENOMEDIUM equ 123 + EMEDIUMTYPE equ 124 + ECANCELED equ 125 + ENOKEY equ 126 + EKEYEXPIRED equ 127 + EKEYREVOKED equ 128 + EKEYREJECTED equ 129 + EOWNERDEAD equ 130 + ENOTRECOVERABLE equ 131 + ERFKILL equ 132 + EHWPOISON equ 133 diff --git a/src/constants/file.asm b/src/constants/file.asm new file mode 100644 index 0000000..55c72f6 --- /dev/null +++ b/src/constants/file.asm @@ -0,0 +1,73 @@ +section .rodata + ; Open flags + O_ACCMODE equ 00000003q + O_RDONLY equ 00000000q + O_WRONLY equ 00000001q + O_RDWR equ 00000002q + O_CREAT equ 00000100q ;create if not exist + O_EXCL equ 00000200q ;fail if file exists and O_EXCL+O_CREAT set + O_NOCTTY equ 00000400q + O_TRUNC equ 00001000q + O_APPEND equ 00002000q + O_NONBLOCK equ 00004000q + O_DSYNC equ 00010000q + FASYNC equ 00020000q + O_DIRECT equ 00040000q + O_LARGEFILE equ 00100000q + O_DIRECTORY equ 00200000q + O_NOFOLLOW equ 00400000q + O_NOATIME equ 01000000q + O_CLOEXEC equ 02000000q + __O_SYNC equ 04000000q + O_SYNC equ (__O_SYNC | O_DSYNC) + O_PATH equ 01000000q + __O_TMPFILE equ 02000000q + O_TMPFILE equ (__O_TMPFILE | O_DIRECTORY) + O_NDELAY equ O_NONBLOCK + ; Permission flags + S_IXOTH equ 00001q ;o=x + S_IWOTH equ 00002q ;o=w + S_IROTH equ 00004q ;o=r + S_IRWXO equ 00007q ;o=rwx + S_IXGRP equ 00010q ;g=x + S_IWGRP equ 00020q ;g=w + S_IRGRP equ 00040q ;g=r + S_IRWXG equ 00070q ;g=rwx + S_IXUSR equ 00100q ;u=x + S_IWUSR equ 00200q ;u=w + S_IRUSR equ 00400q ;u=r + S_IRWXU equ 00700q ;u=rwx + S_ISVTX equ 0001000q ;sticky bit + S_ISGID equ 0002000q ;set-group-ID bit + S_ISUID equ 0004000q ;set-user-ID bit + ; Stat buffer fields + ST_DEV equ 0 ; Device + ST_INO equ 8 ; File serial number + ST_NLINK equ 16 + ST_MODE equ 24 ; File mode + ST_UID equ 28 ; User ID of the file's owner + ST_GID equ 32 ; Group ID of the file's group + ST__PAD0 equ 36 + ST_RDEV equ 40 ; Device number, if device + ST_SIZE equ 48 ; Size of file, in bytes + ST_BLKSIZE equ 56 ; Optimal block size for I/O + ST_BLOCKS equ 64 ; Number 512-byte blocks allocated + ST_ATIME equ 72 ; Time of last access + ST_ATIME_NSEC equ 80 + ST_MTIME equ 88 ; Time of last modification + ST_MTIME_NSEC equ 96 + ST_CTIME equ 104 ; Time of last status change + ST_CTIME_NSEC equ 112 + ST__UNUSED equ 120 + ST__END equ 128 ; End of stat buffer + STATBUFF_SIZE equ ST__END + + AT_FDCWD equ -100 + ; File types + S_IFDIR equ 0040000q ; Directory + S_IFCHR equ 0020000q ; Character device + S_IFBLK equ 0060000q ; Block device + S_IFREG equ 0100000q ; Regular file + S_IFIFO equ 0010000q ; FIFO + S_IFLNK equ 0120000q ; Symbolic link + S_IFSOCK equ 0140000q ; Socket diff --git a/src/constants/sizes.asm b/src/constants/sizes.asm new file mode 100644 index 0000000..3d6c901 --- /dev/null +++ b/src/constants/sizes.asm @@ -0,0 +1,26 @@ +section .rodata + RBP_OFFSET_CALLER equ 16 + SIZE_QWORD equ 8 + SIZE_DWORD equ 4 + SIZE_WORD equ 2 + SIZE_BYTE equ 1 + + MIN_UINT64 equ 0 + MIN_UINT32 equ 0 + MIN_UINT16 equ 0 + MIN_UINT8 equ 0 + + MAX_UINT64 equ 0xFFFFFFFFFFFFFFFF + MAX_UINT32 equ 0xFFFFFFFF + MAX_UINT16 equ 0xFFFF + MAX_UINT8 equ 0xFF + + MIN_INT64 equ ~0x7FFFFFFFFFFFFFFF + MIN_INT32 equ ~0x7FFFFFFF + MIN_INT16 equ ~0x7FFF + MIN_INT8 equ ~0x7F + + MAX_INT64 equ 0x7FFFFFFFFFFFFFFF + MAX_INT32 equ 0x7FFFFFFF + MAX_INT16 equ 0x7FFF + MAX_INT8 equ 0x7F diff --git a/src/constants/syscalls.asm b/src/constants/syscalls.asm new file mode 100644 index 0000000..f63212c --- /dev/null +++ b/src/constants/syscalls.asm @@ -0,0 +1,12 @@ +section .rodata + NR_read equ 0 + NR_write equ 1 + NR_open equ 2 + NR_close equ 3 + ;NR_stat equ 4 + NR_fstat equ 5 + NR_lstat equ 6 + NR_exit equ 60 + NR_creat equ 85 + NR_umask equ 95 + NR_newfstatat equ 262 diff --git a/src/file.asm b/src/file.asm index db953d2..e66551a 100644 --- a/src/file.asm +++ b/src/file.asm @@ -5,57 +5,66 @@ extern __INTERNAL_fmt extern strlen extern umask_get -section .rodata - ; Open flags - O_ACCMODE equ 00000003q - O_RDONLY equ 00000000q - O_WRONLY equ 00000001q - O_RDWR equ 00000002q - O_CREAT equ 00000100q ;create if not exist - O_EXCL equ 00000200q ;fail if file exists and O_EXCL+O_CREAT set - O_NOCTTY equ 00000400q - O_TRUNC equ 00001000q - O_APPEND equ 00002000q - O_NONBLOCK equ 00004000q - O_DSYNC equ 00010000q - FASYNC equ 00020000q - O_DIRECT equ 00040000q - O_LARGEFILE equ 00100000q - O_DIRECTORY equ 00200000q - O_NOFOLLOW equ 00400000q - O_NOATIME equ 01000000q - O_CLOEXEC equ 02000000q - __O_SYNC equ 04000000q - O_SYNC equ (__O_SYNC | O_DSYNC) - O_PATH equ 01000000q - __O_TMPFILE equ 02000000q - O_TMPFILE equ (__O_TMPFILE | O_DIRECTORY) - O_NDELAY equ O_NONBLOCK - ; Permission flags - S_IXOTH equ 00001q ;o=x - S_IWOTH equ 00002q ;o=w - S_IROTH equ 00004q ;o=r - S_IRWXO equ 00007q ;o=rwx - S_IXGRP equ 00010q ;g=x - S_IWGRP equ 00020q ;g=w - S_IRGRP equ 00040q ;g=r - S_IRWXG equ 00070q ;g=rwx - S_IXUSR equ 00100q ;u=x - S_IWUSR equ 00200q ;u=w - S_IRUSR equ 00400q ;u=r - S_IRWXU equ 00700q ;u=rwx - S_ISVIX equ 0001000q ;sticky bit - S_ISGID equ 0002000q ;set-group-ID bit - S_ISUID equ 0004000q ;set-user-ID bit - -section .bss - section .text + global fstatat + global fgetmod global fopen global fclose global fexist global fwrite +;----- fstatat(*file[], *statBuffer[]) -----; +; Gets information from a file, stores it into statBuffer[] +; Return value: 0 if stats received, -errno otherwise +; Used registers: +; rax* (ret) +; rdi* (arg) Pointer to file +; rsi* (arg) Pointer to statBuffer +; rdx* arg for syscall NR_newfstatat +; r10* arg(flag) for syscall NR_newfstatat +fstatat: + sub rsp, SIZE_QWORD + mov rax, NR_newfstatat + mov rdx, rsi + mov rsi, rdi + mov rdi, AT_FDCWD + xor r10, r10 + syscall + add rsp, SIZE_QWORD + ret + +;----- fgettype(*statBuffer[]) -----; +; Gets file type from stat buffer +; Return value: Permissions of given file or -EINVAL if statBuffer is invalid (first bit is 0) +; Used registers: +; rax* (ret) +; rdi (arg) Pointer to statBuffer[] +fgettype: + cmp byte [rdi], 0 + jne .buffok + mov rax, -EINVAL + ret + .buffok: + mov rax, [rdi + ST_MODE] + and rax, 0xF000 + ret + +;----- fgetmod(*statBuffer[]) -----; +; Gets file mode bits (file permissions) from stat buffer +; Return value: Permissions of given file or -EINVAL if statBuffer is invalid (first bit is 0) +; Used registers: +; rax* (ret) +; rdi (arg) Pointer to stat buffer +fgetmod: + cmp byte [rdi], 0 + jne .buffok + mov rax, -EINVAL + ret + .buffok: + mov rax, [rdi + ST_MODE] + and rax, 0x0FFF + ret + ;----- fopen(*file[], char mode) -----; ; Opens a file ; Return value: Pointer to opened file pointer, -errno otherwise