commit 8e72d1ebba101811cbea4da918f2f9912749a250
parent dc97c0baccb63e6adf9c185a093735d3de9c5d3f
Author: evenfri <evenfri256@gmail.com>
Date: Sun, 9 Aug 2026 01:30:12 +0800
feat: errno, syscall wrapper
Diffstat:
20 files changed, 161 insertions(+), 116 deletions(-)
diff --git a/chdir.c b/chdir.c
@@ -6,9 +6,12 @@
#include "libc.h"
int chdir(const char *path) {
- long ret = syscall(sys_chdir, path);
+ int ret = syscall(sys_chdir, path);
+
if (ret < 0) {
+ errno = -ret;
return -1;
}
- return 0;
+
+ return ret;
}
diff --git a/close.c b/close.c
@@ -6,7 +6,12 @@
#include "libc.h"
int close(int fd) {
- long ret = syscall(sys_close, fd);
+ int ret = syscall(sys_close, fd);
+
+ if (ret < 0) {
+ errno = -ret;
+ return -1;
+ }
return ret;
}
diff --git a/errno.c b/errno.c
@@ -0,0 +1,8 @@
+/*
+ * errno.c - define 'int errno;'
+ * Copyright (C) 2026. All rights reserved.
+ */
+
+#include "libc.h"
+
+int errno;
diff --git a/execve.c b/execve.c
@@ -6,10 +6,12 @@
#include "libc.h"
int execve(const char *path, char *const argv[], char *const envp[]) {
- long ret = syscall3(sys_execve, path, argv, envp);
+ int ret = syscall(sys_execve, path, argv, envp);
if (ret < 0) {
+ errno = -ret;
return -1;
}
- return 0;
+
+ return ret;
}
diff --git a/fork.c b/fork.c
@@ -8,7 +8,12 @@
#define sigchld 17
int fork(void) {
- long ret = syscall2(sys_clone, (long)sigchld, 0L);
+ int ret = syscall(sys_clone, (long)sigchld, 0L);
- return (int)ret;
+ if (ret < 0) {
+ errno = -ret;
+ return -1;
+ }
+
+ return ret;
}
diff --git a/getcwd.c b/getcwd.c
@@ -6,7 +6,12 @@
#include "libc.h"
char *getcwd(char *buf, size_t size) {
- long ret = syscall2(sys_getcwd, buf, size);
- if (ret < 0) return NULL;
+ int ret = syscall(sys_getcwd, buf, size);
+
+ if (ret < 0) {
+ errno = -ret;
+ return NULL;
+ }
+
return buf;
}
diff --git a/getdents.c b/getdents.c
@@ -6,5 +6,5 @@
#include "libc.h"
int getdents64(int fd, struct linux_dirent64 *dirp, unsigned int count) {
- return (int)syscall3(sys_getdents64, fd, (long)dirp, count);
+ return (int)syscall(sys_getdents64, fd, (long)dirp, count);
}
diff --git a/libc.h b/libc.h
@@ -27,40 +27,6 @@ struct linux_dirent64 {
char d_name[];
};
-/* macros */
-#define syscall(n, d) ({ \
- long ret; \
- asm volatile ( \
- "syscall" \
- : "=a"(ret) \
- : "a"(n), "D"(d) \
- : "rcx", "r11", "memory" \
- ); \
- ret; \
- })
-
-#define syscall2(n, arg1, arg2) ({ \
- long ret; \
- asm volatile ( \
- "syscall" \
- : "=a"(ret) \
- : "a"(n), "D"(arg1), "S"(arg2) \
- : "rcx", "r11", "memory" \
- ); \
- ret; \
- })
-
-#define syscall3(n, arg1, arg2, arg3) ({ \
- long ret; \
- asm volatile ( \
- "syscall" \
- : "=a"(ret) \
- : "a"(n), "D"(arg1), "S"(arg2), "d"(arg3) \
- : "rcx", "r11", "memory" \
- ); \
- ret; \
- })
-
/* open flags */
#define o_rdonly 00
#define o_wronly 01
@@ -95,17 +61,24 @@ struct linux_dirent64 {
/* variables */
extern char **environ;
-/* function prototypes */
+/* syscall function */
+long syscall(long num, ...);
+
+/* io */
ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);
int open(const char *filename, int flags, int mode);
int close(int fd);
+
+/* proc */
void _exit(int status);
void exit(int status);
int execve(const char *path, char *const argv[], char *const envp[]);
int execvp(const char *file, char *const argv[]);
int fork(void);
int waitpid(int pid, int *status, int options);
+
+/* fs */
int mount(const char *source,
const char *target,
const char *filesystemtype,
@@ -115,22 +88,25 @@ int chdir(const char *path);
char *getcwd(char *buf, size_t size);
int getdents64(int fd, struct linux_dirent64 *dirp, unsigned int count);
-/* memory prototypes */
+/* memory */
void* mmap(void *addr, size_t length, int prot, int flags, int fd, long offset);
int munmap(void *addr, size_t length);
void* memset(void *s, int c, size_t n);
void* memcpy(void *dest, const void *src, size_t n);
-/* alloc prototypes */
+/* alloc */
void* malloc(size_t size);
void free(void *ptr);
void* calloc(size_t nmemb, size_t size);
void* realloc(void *ptr, size_t size);
-/* string functions prototypes */
+/* string functions */
size_t strlen(const char *str);
-int strchr(const char *s, int c);
+char *strchr(const char *str, int c);
int strcmp(const char *s1, const char *s2);
char* strtok(char *str, const char *delim);
+/* errno */
+extern int errno;
+
#endif /* libc_h */
diff --git a/malloc.c b/malloc.c
@@ -16,7 +16,7 @@ struct block_header {
typedef struct block_header block_header_t;
-static block_header_t *glb_free_list = NULL;
+static block_header_t *free_list = NULL;
static size_t align(size_t n) {
return (n + align_mask) & ~align_mask;
@@ -28,7 +28,7 @@ void* malloc(size_t size) {
}
size_t total_size = align(size + sizeof(block_header_t));
- block_header_t *curr = glb_free_list;
+ block_header_t *curr = free_list;
block_header_t *prev = NULL;
while (curr != NULL) {
@@ -42,9 +42,9 @@ void* malloc(size_t size) {
size_t alloc_size = total_size < 4096 ? 4096 : total_size;
block_header_t *block = mmap(NULL, alloc_size,
- prot_read | prot_write,
- map_private | map_anonymous,
- -1, 0);
+ prot_read | prot_write,
+ map_private | map_anonymous,
+ -1, 0);
if (block == map_failed) {
return NULL;
@@ -57,7 +57,7 @@ void* malloc(size_t size) {
if (prev != NULL) {
prev->next = block;
} else {
- glb_free_list = block;
+ free_list = block;
}
return (void*)(block + 1);
diff --git a/mkfile b/mkfile
@@ -7,6 +7,7 @@ ld = ld
lib = libc.a
ofiles = start.$o \
+ syscall.$o \
_exit.$o \
exit.$o \
read.$o \
@@ -26,6 +27,7 @@ ofiles = start.$o \
getcwd.$o \
chdir.$o \
getdents.$o \
+ errno.$o \
strlen.$o \
strchr.$o \
strcmp.$o \
diff --git a/mmap.c b/mmap.c
@@ -6,23 +6,13 @@
#include "libc.h"
void* mmap(void *addr, size_t length, int prot, int flags, int fd, long offset) {
- long ret;
- register long r10 asm("r10") = (long)flags;
- register long r8 asm("r8") = (long)fd;
- register long r9 asm("r9") = offset;
+ long ret = syscall(sys_mmap, addr, length, prot, (long)flags, (long)fd,
+ offset);
- asm volatile (
- "syscall"
- : "=a"(ret)
- : "a"(sys_mmap),
- "D"(addr),
- "S"(length),
- "d"(prot),
- "r"(r10),
- "r"(r8),
- "r"(r9)
- : "rcx", "r11", "memory"
- );
+ if (ret < 0) {
+ errno = -ret;
+ return (void*)-1;
+ }
return (void*)ret;
}
diff --git a/mount.c b/mount.c
@@ -10,21 +10,18 @@ int mount(const char *source,
const char *filesystemtype,
ulong_t mountflags,
const void *data) {
- long ret;
- register long r10 asm("r10") = (long)mountflags;
- register long r8 asm("r8") = (long)data;
- asm volatile (
- "syscall"
- : "=a"(ret)
- : "a"(sys_mount),
- "D"(source),
- "S"(target),
- "d"(filesystemtype),
- "r"(r10),
- "r"(r8)
- : "rcx", "r11", "memory"
- );
+ int ret = syscall(sys_mount,
+ source,
+ target,
+ filesystemtype,
+ mountflags,
+ data);
- return (int)ret;
+ if (ret < 0) {
+ errno = -ret;
+ return -1;
+ }
+
+ return ret;
}
diff --git a/munmap.c b/munmap.c
@@ -6,7 +6,12 @@
#include "libc.h"
int munmap(void *addr, size_t length) {
- long ret = syscall2(sys_munmap, addr, length);
+ long ret = syscall(sys_munmap, addr, length);
+
+ if (ret < 0) {
+ errno = -ret;
+ return -1;
+ }
return (int)ret;
}
diff --git a/open.c b/open.c
@@ -6,7 +6,12 @@
#include "libc.h"
int open(const char *filename, int flags, int mode) {
- long ret = syscall3(sys_open, filename, flags, mode);
+ int ret = syscall(sys_open, filename, flags, mode);
+
+ if (ret < 0) {
+ errno = -ret;
+ return -1;
+ }
return ret;
}
diff --git a/read.c b/read.c
@@ -6,7 +6,12 @@
#include "libc.h"
ssize_t read(int fd, void *buf, size_t count) {
- long ret = syscall3(sys_read, fd, buf, count);
+ int ret = syscall(sys_read, fd, buf, count);
+
+ if (ret < 0) {
+ errno = -ret;
+ return -1;
+ }
return ret;
}
diff --git a/strchr.c b/strchr.c
@@ -4,13 +4,15 @@
*/
#include "libc.h"
+char *strchr(const char *str, int c) {
+ char chr = (char)c;
+ int i = 0;
-int strchr(const char *s, int c) {
- while (*s) {
- if (*s == (char)c) {
- return 1;
- }
- s++;
+ while (str[i] != 0) {
+ if (str[i] == chr)
+ return (char*)str + i;
+ i++;
}
- return 0;
+
+ return NULL;
}
diff --git a/strtok.c b/strtok.c
@@ -6,23 +6,23 @@
#include "libc.h"
char* strtok(char *str, const char *delim) {
- static char *glb_next_token = NULL;
+ static char *next_token = NULL;
if (str != NULL) {
- glb_next_token = str;
+ next_token = str;
}
- if (glb_next_token == NULL || *glb_next_token == '\0') {
+ if ( next_token == NULL || * next_token == '\0') {
return NULL;
}
- char *token_start = glb_next_token;
+ char *token_start = next_token;
while (*token_start && strchr(delim, *token_start)) {
token_start++;
}
if (*token_start == '\0') {
- glb_next_token = NULL;
+ next_token = NULL;
return NULL;
}
@@ -33,9 +33,9 @@ char* strtok(char *str, const char *delim) {
if (*token_end != '\0') {
*token_end = '\0';
- glb_next_token = token_end + 1;
+ next_token = token_end + 1;
} else {
- glb_next_token = NULL;
+ next_token = NULL;
}
return token_start;
diff --git a/syscall.c b/syscall.c
@@ -0,0 +1,37 @@
+/*
+ * syscall.c - syscalls wrapper
+ * Copyright (C) 2026. All rights reserved.
+ */
+
+#include <stdarg.h>
+#include "libc.h"
+
+static inline long call(long n, long a1, long a2, long a3, long a4, long a5, long a6)
+{
+ unsigned 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;
+}
+
+long syscall(long num, ...) {
+ va_list valist;
+ long a, b, c, d, e, f;
+
+ va_start(valist, num);
+ a = va_arg(valist, long);
+ b = va_arg(valist, long);
+ c = va_arg(valist, long);
+ d = va_arg(valist, long);
+ e = va_arg(valist, long);
+ f = va_arg(valist, long);
+ va_end(valist);
+
+ return call(num, a, b, c, d, e, f);
+}
diff --git a/waitpid.c b/waitpid.c
@@ -6,19 +6,12 @@
#include "libc.h"
int waitpid(int pid, int *status, int options) {
- long ret;
- register long r10 asm("r10") = 0;
+ int ret = syscall(sys_waitpid, pid, status, options);
- asm volatile (
- "syscall"
- : "=a"(ret)
- : "a"(sys_waitpid),
- "D"((long)pid),
- "S"(status),
- "d"((long)options),
- "r"(r10)
- : "rcx", "r11", "memory"
- );
+ if (ret < 0) {
+ errno = -ret;
+ return -1;
+ }
return (int)ret;
}
diff --git a/write.c b/write.c
@@ -6,7 +6,12 @@
#include "libc.h"
ssize_t write(int fd, const void *buf, size_t count) {
- long ret = syscall3(sys_write, fd, buf, count);
+ int ret = syscall(sys_write, fd, buf, count);
+
+ if (ret < 0) {
+ errno = -ret;
+ return -1;
+ }
return ret;
}