libc

my libc
git clone git://git.evenfri.duckdns.org/libc.git
Log | Files | Refs | README

commit 8e72d1ebba101811cbea4da918f2f9912749a250
parent dc97c0baccb63e6adf9c185a093735d3de9c5d3f
Author: evenfri <evenfri256@gmail.com>
Date:   Sun,  9 Aug 2026 01:30:12 +0800

feat: errno, syscall wrapper

Diffstat:
Mchdir.c | 7+++++--
Mclose.c | 7++++++-
Aerrno.c | 8++++++++
Mexecve.c | 6++++--
Mfork.c | 9+++++++--
Mgetcwd.c | 9+++++++--
Mgetdents.c | 2+-
Mlibc.h | 54+++++++++++++++---------------------------------------
Mmalloc.c | 12++++++------
Mmkfile | 2++
Mmmap.c | 22++++++----------------
Mmount.c | 27++++++++++++---------------
Mmunmap.c | 7++++++-
Mopen.c | 7++++++-
Mread.c | 7++++++-
Mstrchr.c | 16+++++++++-------
Mstrtok.c | 14+++++++-------
Asyscall.c | 37+++++++++++++++++++++++++++++++++++++
Mwaitpid.c | 17+++++------------
Mwrite.c | 7++++++-
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; }