diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/include/syscall.h | 27 | ||||
-rw-r--r-- | lib/include/syscalls.h | 25 | ||||
-rw-r--r-- | lib/src/syscalls.c | 48 |
3 files changed, 88 insertions, 12 deletions
diff --git a/lib/include/syscall.h b/lib/include/syscall.h index c9314d2..10dc545 100644 --- a/lib/include/syscall.h +++ b/lib/include/syscall.h @@ -19,6 +19,7 @@ // // Machine specific constraints (x86_64): // a | a register (eg rax) +// c | c register (eg rcx) // d | d register (eg rdx) // D | di register (eg rdi) // S | si register (eg rsi) @@ -54,10 +55,12 @@ // Reference: // https://www.felixcloutier.com/x86/syscall -#define argcast(A) ((long)(A)) -#define syscall1(n, a1) _syscall1(n, argcast(a1)) -#define syscall2(n, a1, a2) _syscall2(n, argcast(a1), argcast(a2)) -#define syscall3(n, a1, a2, a3) _syscall3(n, argcast(a1), argcast(a2), argcast(a3)) +#define argcast(A) ((long)(A)) +#define syscall1(n, a1) _syscall1(n, argcast(a1)) +#define syscall2(n, a1, a2) _syscall2(n, argcast(a1), argcast(a2)) +#define syscall3(n, a1, a2, a3) _syscall3(n, argcast(a1), argcast(a2), argcast(a3)) +#define syscall4(n, a1, a2, a3, a4) _syscall4(n, argcast(a1), argcast(a2), argcast(a3), argcast(a4)) +#define syscall6(n, a1, a2, a3, a4, a5, a6) _syscall6(n, argcast(a1), argcast(a2), argcast(a3), argcast(a4), argcast(a5), argcast(a6)) static inline long _syscall1(long n, long a1) { long ret; @@ -76,3 +79,19 @@ static inline long _syscall3(long n, long a1, long a2, long a3) { asm volatile("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2), "d"(a3) : "rcx", "r11", "memory"); return ret; } + +static inline long _syscall4(long n, long a1, long a2, long a3, long a4) { + long ret; + register long r10 asm("r10") = a4; + asm volatile("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2), "d"(a3), "r"(r10) : "rcx", "r11", "memory"); + return ret; +} + +static inline long _syscall6(long n, long a1, long a2, long a3, long a4, long a5, long a6) { + long ret; + register long r10 asm("r10") = a4; + register long r8 asm("r8") = a5; + register long r9 asm("r9") = a6; + asm volatile("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2), "d"(a3), "r"(r10), "r"(r8), "r"(r9) : "rcx", "r11", "memory"); + return ret; +} diff --git a/lib/include/syscalls.h b/lib/include/syscalls.h index 34b6b37..7808e98 100644 --- a/lib/include/syscalls.h +++ b/lib/include/syscalls.h @@ -5,6 +5,8 @@ #include <stddef.h> // size_t #include <sys/types.h> // ssize_t, off_t, ... +extern int dynld_errno; + // Syscall definitions taken from corresponding man pages, eg // open(2) // read(2) @@ -12,12 +14,27 @@ #define O_RDONLY 00 int open(const char* path, int flags); +int close(int fd); + +#define F_OK 0 +#define R_OK 4 +int access(const char* path, int mode); +ssize_t write(int fd, const void* buf, size_t count); ssize_t read(int fd, void* buf, size_t count); +ssize_t pread(int fd, void* buf, size_t count, off_t offset); -#define SEEK_SET 0 -#define SEEK_CUR 1 -#define SEEK_END 2 -off_t lseek(int fd, off_t offset, int whence); +// mmap - prot: +#define PROT_READ 0x1 +#define PROT_WRITE 0x2 +#define PROT_EXEC 0x4 +// mmap - flags: +#define MAP_PRIVATE 0x2 +#define MAP_ANONYMOUS 0x20 +#define MAP_FIXED 0x10 +// mmap - ret: +#define MAP_FAILED ((void*)-1) +void* mmap(void* addr, size_t length, int prot, int flags, int fd, off_t offset); +int munmap(void* addr, size_t length); void _exit(int status); diff --git a/lib/src/syscalls.c b/lib/src/syscalls.c index d6ac1a5..074fced 100644 --- a/lib/src/syscalls.c +++ b/lib/src/syscalls.c @@ -4,16 +4,56 @@ #include <syscall.h> #include <syscalls.h> +// Storage for `dynld_errno`. +int dynld_errno; + +// Convert return value to errno/ret. +static long syscall_ret(unsigned long ret) { + if (ret > (unsigned long)-4096ul) { + dynld_errno = -ret; + return -1; + } + return ret; +} + int open(const char* path, int flags) { - return syscall2(__NR_open, path, flags); + long ret = syscall2(__NR_open, path, flags); + return syscall_ret(ret); +} + +int close(int fd) { + long ret = syscall1(__NR_close, fd); + return syscall_ret(ret); +} + +int access(const char* path, int mode) { + long ret = syscall2(__NR_access, path, mode); + return syscall_ret(ret); +} + +ssize_t write(int fd, const void* buf, size_t count) { + long ret = syscall3(__NR_write, fd, buf, count); + return syscall_ret(ret); } ssize_t read(int fd, void* buf, size_t count) { - return syscall3(__NR_read, fd, buf, count); + long ret = syscall3(__NR_read, fd, buf, count); + return syscall_ret(ret); +} + +ssize_t pread(int fd, void* buf, size_t count, off_t offset) { + long ret = syscall4(__NR_read, fd, buf, count, offset); + return syscall_ret(ret); +} + +void* mmap(void* addr, size_t length, int prot, int flags, int fd, off_t offset) { + long ret = syscall6(__NR_mmap, addr, length, prot, flags, fd, offset); + return (void*)syscall_ret(ret); } -off_t lseek(int fd, off_t offset, int whence) { - return syscall3(__NR_lseek, fd, offset, whence); +int munmap(void* addr, size_t length) { + long ret = syscall2(__NR_munmap, addr, length); + return syscall_ret(ret); } void _exit(int status) { |