aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjohannst <johannes.stoelp@gmail.com>2021-04-17 23:41:17 +0200
committerjohannst <johannes.stoelp@gmail.com>2021-04-17 23:41:17 +0200
commit26088bf37ef85681cf2158fdff82233b1b0c9bfd (patch)
treef0e9e3ac1f123b3fd5446e1fafe01e491da9ebbb
parent9b4b10a31954c00813a7cbf9411d30bc84eccea8 (diff)
downloaddynld-26088bf37ef85681cf2158fdff82233b1b0c9bfd.tar.gz
dynld-26088bf37ef85681cf2158fdff82233b1b0c9bfd.zip
added close,access,write,pread,mmap,munmap syscalls + syscall ret handler
-rw-r--r--lib/include/syscall.h27
-rw-r--r--lib/include/syscalls.h25
-rw-r--r--lib/src/syscalls.c48
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) {