liblinux++

Log | Files | Refs

commit b8f04aa6fc6abab81fb8af1f0a0b58994fe2df25
Author: Henry Wilson <henry@henryandlizzy.uk>
Date:   Fri,  6 Dec 2024 16:15:41 +0000

Initial working version in AT&T syntax

Diffstat:
ATupfile | 7+++++++
ATupfile.ini | 0
Acrt0.s | 12++++++++++++
Acrt1.c | 14++++++++++++++
Aecho.c | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
Asyscall.h | 14++++++++++++++
Asyscall.s | 100+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7 files changed, 199 insertions(+), 0 deletions(-)

diff --git a/Tupfile b/Tupfile @@ -0,0 +1,7 @@ +CFLAGS = -Os -fno-asynchronous-unwind-tables +LDFLAGS = -static -nostartfiles -nostdlib -Xlinker --gc-sections + +: foreach *.c *.s |> cc $(CFLAGS) -c -o %o %f |> x86_64/%B.o {objs.x86_64} +: {objs.x86_64} |> cc $(LDFLAGS) -o %o %f |> echo.x86_64 + +.gitignore diff --git a/Tupfile.ini b/Tupfile.ini diff --git a/crt0.s b/crt0.s @@ -0,0 +1,12 @@ +.global _start + +.text + +_start: # _start is the entry point known to the linker + xor %ebp, %ebp # effectively RBP := 0, mark the end of stack frames + mov (%rsp), %edi # get argc from the stack (implicitly zero-extended to 64-bit) + lea 8(%rsp), %rsi # take the address of argv from the stack + lea 16(%rsp,%rdi,8), %rdx # take the address of envp from the stack + xor %eax, %eax # per ABI and compatibility with icc + jmp start # %edi, %rsi, %rdx are the three args (of which first two are C standard) to main + diff --git a/crt1.c b/crt1.c @@ -0,0 +1,14 @@ +#include "syscall.h" + +extern char __bss_start[], _end[]; +extern int main(int, char**, char**); + +__attribute__((noreturn)) +void start(int argc, char* argv[], char* envp[]) +{ + for (char* p = __bss_start; p < _end; ++p) + *p = 0; + + exit(main(argc, argv, envp)); + __builtin_trap(); +} diff --git a/echo.c b/echo.c @@ -0,0 +1,52 @@ +#include "syscall.h" + +static char buf[0x1000]; +static unsigned bufsize; + +static void putflush() +{ + if (bufsize && write(1, buf, bufsize) != bufsize) + exit(1); + bufsize = 0; +} + +static void putch(char c) +{ + buf[bufsize++] = c; + if (c == '\n' || bufsize == sizeof buf) + putflush(); +} + +static void putstr(char const* s) +{ + while(*s) + putch(*s++); +} +/* +static void* sbrk(unsigned size) +{ + static void* end; + + if (!end) + end = brk(NULL); + + end += size; + + if (brk(end) != end) + exit(1); + + return end; +} +*/ +int main(int argc, char* argv[]) +{ +// sbrk(0); + if (argc > 1) + putstr(argv[1]); + for (int i = 2; i < argc; ++i) + { + putch(' '); + putstr(argv[i]); + } + putch('\n'); +} diff --git a/syscall.h b/syscall.h @@ -0,0 +1,14 @@ +#include <stddef.h> + +extern int read(int fd, char* data, size_t count); +extern int write(int fd, char const* data, size_t count); +extern int open(char const* name, int flags, int mode); +extern int close(int fd); +extern void* mmap(void* addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long off); + +extern void* brk(void* new_brk); + +__attribute__((noreturn)) +extern void exit(int error_code); + +extern int ftruncate(int fd, unsigned long length); diff --git a/syscall.s b/syscall.s @@ -0,0 +1,100 @@ +.macro syscall3, num, name +.global \name +.section .text.\name +\name: + push %r11 + push %rcx + mov $\num, %rax + syscall + pop %rcx + pop %r11 + ret +.endm + +.macro syscall6, num, name +.global \name +.section .text.\name +\name: + push %r11 + mov $\num, %rax + mov %rcx, %r10 + syscall + pop %r11 + ret +.endm + +.text +.global exit + +syscall3 0 read +syscall3 1 write +syscall3 2 open +syscall3 3 close +syscall3 4 stat +syscall3 5 fstat +syscall3 6 lstat +syscall3 7 poll +syscall3 8 lseek +syscall6 9 mmap +syscall3 10 mprotect +syscall3 11 munmap +syscall3 12 brk +syscall6 13 rt_sigaction +syscall6 14 rt_sigprocmask +syscall3 15 rt_sigreturn +syscall3 16 ioctl +syscall6 17 pread64 +syscall6 18 pwrite64 +syscall3 19 readv +syscall3 20 writev +syscall3 21 access +syscall3 22 pipe +syscall6 23 select +syscall3 24 yield +syscall6 25 mremap +syscall3 26 msync +syscall3 27 mincore +syscall3 28 madvise +syscall3 29 shmget +syscall3 30 shmat +syscall3 31 shmctl +syscall3 32 dup +syscall3 33 dup2 +syscall3 34 pause +syscall3 35 nanosleep +syscall3 36 getitimer +syscall3 37 alarm +syscall3 38 setitimer +syscall3 39 getpid +syscall6 40 sendfile +syscall3 41 socket +syscall3 42 connect +syscall3 43 accept +syscall6 44 sendto +syscall6 45 recvfrom +syscall3 46 sendmsg +syscall3 47 recvmsg +syscall3 48 shutdown +syscall3 49 bind +syscall3 50 listen +syscall3 51 getsockname +syscall3 52 getpeername +syscall3 53 socketpair +syscall6 54 setsockopt +syscall6 55 getsockopt +syscall3 56 clone +syscall3 57 fork +syscall3 58 vfork +syscall3 59 execve + +.section .text.exit +exit: mov $60, %rax + syscall + +syscall6 61 wait4 +syscall3 62 kill +syscall3 63 uname +syscall3 64 semget +syscall3 65 semop + +syscall3 77 ftruncate