diff --git a/build/build.sh b/build.sh similarity index 75% rename from build/build.sh rename to build.sh index b1db3fb..75edf63 100644 --- a/build/build.sh +++ b/build.sh @@ -1,3 +1,4 @@ +#!/usr/bin/env bash set -e nasm -f elf64 ./src/assembly/syscalls.asm -o ./build/syscalls.o diff --git a/build/main b/build/main new file mode 100644 index 0000000..ff6b6e2 Binary files /dev/null and b/build/main differ diff --git a/build/syscalls.o b/build/syscalls.o new file mode 100644 index 0000000..5ce8c9c Binary files /dev/null and b/build/syscalls.o differ diff --git "a/build/syscalls.o\r" "b/build/syscalls.o\r" new file mode 100644 index 0000000..f9314ab Binary files /dev/null and "b/build/syscalls.o\r" differ diff --git a/main.c b/main.c deleted file mode 100644 index 7e2442f..0000000 --- a/main.c +++ /dev/null @@ -1,8 +0,0 @@ -#include "headers/nstdo.h" -extern long sys_write(int fd, const void *buf, size_t count); - -int main(void) { - const char msg[] = "Hello, World!\n"; - sys_write(1, msg, sizeof(msg)-1); - return 0; -} diff --git a/src/assembly/syscalls.asm b/src/assembly/syscalls.asm new file mode 100644 index 0000000..144aaa2 --- /dev/null +++ b/src/assembly/syscalls.asm @@ -0,0 +1,45 @@ +global _start +global sys_read +global sys_write +global sys_fork +global sys_execve +global sys_wait4 +global sys_exit +extern main + +section .text + +sys_read: + mov rax, 0 + syscall + ret + +sys_write: + mov rax, 1 + syscall + ret + +sys_fork: + mov rax, 57 + syscall + ret + +sys_execve: + mov rax, 59 + syscall + ret + +sys_wait4: + mov rax, 61 + syscall + ret + +sys_exit: + mov rax, 60 + syscall + +_start: + call main + mov rdi, rax + mov rax, 60 + syscall diff --git a/nstdo.h b/src/headers/nstdo.h similarity index 94% rename from nstdo.h rename to src/headers/nstdo.h index 919274e..3cd7aab 100644 --- a/nstdo.h +++ b/src/headers/nstdo.h @@ -1,52 +1,53 @@ -#ifndef MINI_STDIO_H -#define MINI_STDIO_H - -#ifdef __cplusplus -extern "C" { -#endif - -typedef unsigned long size_t; -typedef long off_t; - -#define O_RDONLY 0 -#define O_WRONLY 1 -#define O_RDWR 2 -#define O_CREAT 64 -#define O_TRUNC 512 -#define O_APPEND 1024 -#define O_CLOEXEC 02000000 - -typedef __builtin_va_list va_list; -#define va_start(ap,last) __builtin_va_start(ap,last) -#define va_arg(ap,type) __builtin_va_arg(ap,type) -#define va_end(ap) __builtin_va_end(ap) - -#define SYS_READ 0 -#define SYS_WRITE 1 -#define SYS_OPEN 2 -#define SYS_CLOSE 3 -#define SYS_LSEEK 8 - -static inline long _syscall3(long nr,long a1,long a2,long a3){long ret;asm volatile("syscall":"=a"(ret):"a"(nr),"D"(a1),"S"(a2),"d"(a3):"rcx","r11","memory");return ret;} - -#ifndef MY_BUFSIZ -#define MY_BUFSIZ 4096 -#endif - -typedef struct{int fd;char buf[MY_BUFSIZ];size_t pos;size_t len;int mode;}MY_FILE; - -MY_FILE* my_fopen(const char* path,int flags,int mode); -int my_fclose(MY_FILE* f); -size_t my_fread(void* ptr,size_t size,size_t nmemb,MY_FILE* f); -size_t my_fwrite(const void* ptr,size_t size,size_t nmemb,MY_FILE* f); -int my_putc(int c,MY_FILE* f); -int my_puts(const char* s,MY_FILE* f); -off_t my_seek(MY_FILE* f,off_t offset,int whence); -int my_printf(MY_FILE* f,const char* fmt,...); -int my_vprintf(MY_FILE* f,const char* fmt,va_list ap); - -#ifdef __cplusplus -} -#endif - -#endif +#ifndef MINI_STDIO_H +#define MINI_STDIO_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef unsigned long size_t; +typedef long off_t; +#define NULL ((void*)0) + +#define O_RDONLY 0 +#define O_WRONLY 1 +#define O_RDWR 2 +#define O_CREAT 64 +#define O_TRUNC 512 +#define O_APPEND 1024 +#define O_CLOEXEC 02000000 + +typedef __builtin_va_list va_list; +#define va_start(ap,last) __builtin_va_start(ap,last) +#define va_arg(ap,type) __builtin_va_arg(ap,type) +#define va_end(ap) __builtin_va_end(ap) + +#define SYS_READ 0 +#define SYS_WRITE 1 +#define SYS_OPEN 2 +#define SYS_CLOSE 3 +#define SYS_LSEEK 8 + +static inline long _syscall3(long nr,long a1,long a2,long a3){long ret;asm volatile("syscall":"=a"(ret):"a"(nr),"D"(a1),"S"(a2),"d"(a3):"rcx","r11","memory");return ret;} + +#ifndef MY_BUFSIZ +#define MY_BUFSIZ 4096 +#endif + +typedef struct{int fd;char buf[MY_BUFSIZ];size_t pos;size_t len;int mode;}MY_FILE; + +MY_FILE* my_fopen(const char* path,int flags,int mode); +int my_fclose(MY_FILE* f); +size_t my_fread(void* ptr,size_t size,size_t nmemb,MY_FILE* f); +size_t my_fwrite(const void* ptr,size_t size,size_t nmemb,MY_FILE* f); +int my_putc(int c,MY_FILE* f); +int my_puts(const char* s,MY_FILE* f); +off_t my_seek(MY_FILE* f,off_t offset,int whence); +int my_printf(MY_FILE* f,const char* fmt,...); +int my_vprintf(MY_FILE* f,const char* fmt,va_list ap); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..c01ee8a --- /dev/null +++ b/src/main.c @@ -0,0 +1,52 @@ +#include "headers/nstdo.h" +extern long sys_read(int fd, void *buf, size_t cnt); +extern long sys_write(int fd, const void *buf, size_t cnt); +extern long sys_fork(void); +extern long sys_execve(const char *filename, char *const argv[], char *const envp[]); +extern long sys_wait4(int pid, int *wstatus, int options, void *rusage); +extern void sys_exit(int status); + +static int streq(const char *a, const char *b) { + while (*a && *b) { + if (*a != *b) return 0; + a++; b++; + } + return *a == *b; +} + +static long str_len(const char *s) { + long len = 0; + while (s[len]) len++; + return len; +} + +int main(int argc, char *argv[], char *envp[]) { + (void)argc; (void)argv; + const char prompt[] = "$ "; + char buf[512]; + while (1) { + sys_write(1, prompt, sizeof(prompt)-1); + long n = sys_read(0, buf, sizeof(buf)-1); + if (n <= 0) break; + buf[n-1] = '\0'; + if (streq(buf, "help")) { + const char *h1 = " help - display this help message\n"; + const char *h2 = " exit - exit the shell\n"; + sys_write(1, h1, str_len(h1)); + sys_write(1, h2, str_len(h2)); + continue; + } + if (streq(buf, "exit")) { + break; + } + char *args[] = { buf, NULL }; + long pid = sys_fork(); + if (pid == 0) { + sys_execve(buf, args, envp); + sys_exit(1); + } else { + sys_wait4(pid, 0, 0, 0); + } + } + return 0; +} diff --git a/syscalls.asm b/syscalls.asm deleted file mode 100644 index 1e3e39d..0000000 --- a/syscalls.asm +++ /dev/null @@ -1,16 +0,0 @@ -global _start -global sys_write -extern main - -section .text - -sys_write: - mov rax, 1 - syscall - ret - -_start: - call main - mov rdi, rax - mov rax, 60 - syscall \ No newline at end of file diff --git a/syscalls.txt b/syscalls.txt new file mode 100644 index 0000000..3e2b974 --- /dev/null +++ b/syscalls.txt @@ -0,0 +1,362 @@ +Using x86_64 syscall table: +0 read +1 write +2 open +3 close +4 stat +5 fstat +6 lstat +7 poll +8 lseek +9 mmap +10 mprotect +11 munmap +12 brk +13 rt_sigaction +14 rt_sigprocmask +15 rt_sigreturn +16 ioctl +17 pread +18 pwrite +19 readv +20 writev +21 access +22 pipe +23 select +24 sched_yield +25 mremap +26 msync +27 mincore +28 madvise +29 shmget +30 shmat +31 shmctl +32 dup +33 dup2 +34 pause +35 nanosleep +36 getitimer +37 alarm +38 setitimer +39 getpid +40 sendfile +41 socket +42 connect +43 accept +44 sendto +45 recvfrom +46 sendmsg +47 recvmsg +48 shutdown +49 bind +50 listen +51 getsockname +52 getpeername +53 socketpair +54 setsockopt +55 getsockopt +56 clone +57 fork +58 vfork +59 execve +60 exit +61 wait4 +62 kill +63 uname +64 semget +65 semop +66 semctl +67 shmdt +68 msgget +69 msgsnd +70 msgrcv +71 msgctl +72 fcntl +73 flock +74 fsync +75 fdatasync +76 truncate +77 ftruncate +78 getdents +79 getcwd +80 chdir +81 fchdir +82 rename +83 mkdir +84 rmdir +85 creat +86 link +87 unlink +88 symlink +89 readlink +90 chmod +91 fchmod +92 chown +93 fchown +94 lchown +95 umask +96 gettimeofday +97 getrlimit +98 getrusage +99 sysinfo +100 times +101 ptrace +102 getuid +103 syslog +104 getgid +105 setuid +106 setgid +107 geteuid +108 getegid +109 setpgid +110 getppid +111 getpgrp +112 setsid +113 setreuid +114 setregid +115 getgroups +116 setgroups +117 setresuid +118 getresuid +119 setresgid +120 getresgid +121 getpgid +122 setfsuid +123 setfsgid +124 getsid +125 capget +126 capset +127 rt_sigpending +128 rt_sigtimedwait +129 rt_sigqueueinfo +130 rt_sigsuspend +131 sigaltstack +132 utime +133 mknod +134 uselib +135 personality +136 ustat +137 statfs +138 fstatfs +139 sysfs +140 getpriority +141 setpriority +142 sched_setparam +143 sched_getparam +144 sched_setscheduler +145 sched_getscheduler +146 sched_get_priority_max +147 sched_get_priority_min +148 sched_rr_get_interval +149 mlock +150 munlock +151 mlockall +152 munlockall +153 vhangup +154 modify_ldt +155 pivot_root +156 _sysctl +157 prctl +158 arch_prctl +159 adjtimex +160 setrlimit +161 chroot +162 sync +163 acct +164 settimeofday +165 mount +166 umount2 +167 swapon +168 swapoff +169 reboot +170 sethostname +171 setdomainname +172 iopl +173 ioperm +174 create_module +175 init_module +176 delete_module +177 get_kernel_syms +178 query_module +179 quotactl +180 nfsservctl +181 getpmsg +182 putpmsg +183 afs_syscall +184 tuxcall +185 security +186 gettid +187 readahead +188 setxattr +189 lsetxattr +190 fsetxattr +191 getxattr +192 lgetxattr +193 fgetxattr +194 listxattr +195 llistxattr +196 flistxattr +197 removexattr +198 lremovexattr +199 fremovexattr +200 tkill +201 time +202 futex +203 sched_setaffinity +204 sched_getaffinity +205 set_thread_area +206 io_setup +207 io_destroy +208 io_getevents +209 io_submit +210 io_cancel +211 get_thread_area +212 lookup_dcookie +213 epoll_create +214 epoll_ctl_old +215 epoll_wait_old +216 remap_file_pages +217 getdents64 +218 set_tid_address +219 restart_syscall +220 semtimedop +221 fadvise64 +222 timer_create +223 timer_settime +224 timer_gettime +225 timer_getoverrun +226 timer_delete +227 clock_settime +228 clock_gettime +229 clock_getres +230 clock_nanosleep +231 exit_group +232 epoll_wait +233 epoll_ctl +234 tgkill +235 utimes +236 vserver +237 mbind +238 set_mempolicy +239 get_mempolicy +240 mq_open +241 mq_unlink +242 mq_timedsend +243 mq_timedreceive +244 mq_notify +245 mq_getsetattr +246 kexec_load +247 waitid +248 add_key +249 request_key +250 keyctl +251 ioprio_set +252 ioprio_get +253 inotify_init +254 inotify_add_watch +255 inotify_rm_watch +256 migrate_pages +257 openat +258 mkdirat +259 mknodat +260 fchownat +261 futimesat +262 newfstatat +263 unlinkat +264 renameat +265 linkat +266 symlinkat +267 readlinkat +268 fchmodat +269 faccessat +270 pselect6 +271 ppoll +272 unshare +273 set_robust_list +274 get_robust_list +275 splice +276 tee +277 sync_file_range +278 vmsplice +279 move_pages +280 utimensat +281 epoll_pwait +282 signalfd +283 timerfd_create +284 eventfd +285 fallocate +286 timerfd_settime +287 timerfd_gettime +288 accept4 +289 signalfd4 +290 eventfd2 +291 epoll_create1 +292 dup3 +293 pipe2 +294 inotify_init1 +295 preadv +296 pwritev +297 rt_tgsigqueueinfo +298 perf_event_open +299 recvmmsg +300 fanotify_init +301 fanotify_mark +302 prlimit64 +303 name_to_handle_at +304 open_by_handle_at +305 clock_adjtime +306 syncfs +307 sendmmsg +308 setns +309 getcpu +310 process_vm_readv +311 process_vm_writev +312 kcmp +313 finit_module +314 sched_setattr +315 sched_getattr +316 renameat2 +317 seccomp +318 getrandom +319 memfd_create +320 kexec_file_load +321 bpf +322 execveat +323 userfaultfd +324 membarrier +325 mlock2 +326 copy_file_range +327 preadv2 +328 pwritev2 +329 pkey_mprotect +330 pkey_alloc +331 pkey_free +332 statx +333 io_pgetevents +334 rseq +424 pidfd_send_signal +425 io_uring_setup +426 io_uring_enter +427 io_uring_register +428 open_tree +429 move_mount +430 fsopen +431 fsconfig +432 fsmount +433 fspick +434 pidfd_open +435 clone3 +436 close_range +437 openat2 +438 pidfd_getfd +439 faccessat2 +440 process_madvise +441 epoll_pwait2 +442 mount_setattr +443 quotactl_fd +444 landlock_create_ruleset +445 landlock_add_rule +446 landlock_restrict_self +447 memfd_secret +448 process_mrelease +449 futex_waitv