diff --git a/arch/aarch64.c b/arch/aarch64.c index 9ff9deb..8c4ef02 100644 --- a/arch/aarch64.c +++ b/arch/aarch64.c @@ -81,6 +81,50 @@ uint32_t fork(){ return (uint32_t)rtn; } +// SYS_EXECVE 221 +int32_t execve(const char* filename, const char* argv[], const char* envp[]){ + long int rtn; + asm volatile( + // Assembly Instructions + "mov x0, %0\n" // Set x0 to value of filename + "mov x1, %1\n" // Set x1 to value of argv + "mov x2, %2\n" // Set x2 to value of envp + "mov x8, #221\n" // Syscall number + "svc #0\n" // Make syscall + // Output operands + : "=r"(rtn) + // Input operands + : "r"(filename), "r" (argv), "r"(envp) + // Clobbered registers + : "x0", "x1", "x2", "x8", "memory" + ); + return (int32_t)rtn; +} + +uint32_t wait4(uint32_t pid, int* wstatus, int options, void* rusage) { + uint64_t rtn; + asm volatile ( + // Assembly Instructions + "mov x8, #260\n" // Syscall number for 'listen' is 201 in AArch64 + "mov x0, %1\n" // pid + "mov x1, %2\n" // wstatus + "mov x2, %3\n" // options + "mov x3, %4\n" // rusage + "svc #0\n" // Make the syscall + "mov %0, x0\n" // save return value + // Output operands + : "=r" (rtn) + // Input operand + : "r" ((uint64_t)pid), "r"(wstatus), "r"((int64_t)options), "r"(rusage) + // Clobbered registers + : "x0", "x1", "x8", "memory" + ); + return (uint32_t)rtn; +} +uint32_t waitpid(uint32_t pid, int* wstatus, int options) { + return wait4(pid, wstatus, options, 0); +} + int32_t openat(int32_t fd, const char* filename, uint32_t flags, uint32_t mode) { long int rtn; asm volatile ( diff --git a/arch/mips.c b/arch/mips.c index 46cb7c4..f83c91f 100644 --- a/arch/mips.c +++ b/arch/mips.c @@ -1,5 +1,19 @@ #if defined(__mips__) #include "../int.h" +#include "../sys.h" + +/* +#ifndef _START_DEFINED +#define _START_DEFINED +extern int main(int c, char** v); +void __start() { + void* fp = __builtin_frame_address(0); + register int argc asm("a0") = *(uintptr_t*)(fp+32); + register char** argv asm("a1") = fp+36; + exit(main(argc, argv)); +} + +#endif */ /* ifndef _START_DEFINED */ #include "generic.h" @@ -59,6 +73,37 @@ uint32_t fork(){ return (uint32_t)rtn; } +uint32_t waitpid(uint32_t pid, int* wstatus, int options) { + int child_pid = 0; + asm volatile ( + "move $a0, %1\n" + "move $a1, %2\n" + "move $a2, %3\n" + "li $v0, 4007\n" + "syscall\n" + "move %0, $v0\n" + : "=r"(child_pid) + : "r"(pid), "r"(wstatus), "r"(options) + : "a0", "a1", "a2", "v0", "memory" + ); + return child_pid; +} + +int32_t execve(const char* filename, const char* argv[], const char* envp[]){ + int rtn; + asm volatile ( + "move $a0, %0\n" + "move $a1, %1\n" + "move $a2, %2\n" + "li $v0, 4011\n" + "syscall\n" + : "=r"(rtn) + : "r"(filename), "r"(argv), "r"(envp) + : "a0", "a1", "a2", "a3", "v0" + ); + return (int32_t)rtn; +} + int32_t openat(int32_t fd, const char* filename, uint32_t flags, uint32_t mode) { int32_t file = 0; asm volatile ( diff --git a/arch/x86_64.c b/arch/x86_64.c index 1b7c43b..10e5dae 100644 --- a/arch/x86_64.c +++ b/arch/x86_64.c @@ -5,16 +5,16 @@ // Start code #ifndef _START_DEFINED #define _START_DEFINED -extern int main(int argc, char** argv); +extern int main(int argc, char **argv); void _start() { - void* fp = __builtin_frame_address(0); - register int argc asm("rdi") = *(uint64_t*)(fp+8); - register char** argv asm("rsi") = fp+16; + void *fp = __builtin_frame_address(0); + register int argc asm("rdi") = *(uint64_t *)(fp + 8); + register char **argv asm("rsi") = fp + 16; exit(main(argc, argv)); } #endif /* ifndef _START_DEFINED */ -//include other generic functions +// include other generic functions #include "generic.h" // @@ -22,254 +22,245 @@ void _start() { #define SYS_EXIT 60 void exit(int8_t status) { - asm volatile( - "syscall" - : - : "a"(SYS_EXIT), "D"(status) - : - ); - for(;;); + asm volatile("syscall" : : "a"(SYS_EXIT), "D"(status) :); + for (;;) + ; } #define SYS_WRITE 1 -intptr_t write(int32_t fd, const void* buf, intptr_t size) { +intptr_t write(int32_t fd, const void *buf, intptr_t size) { intptr_t n_written = 0; - asm volatile ( - "syscall\n" - "movq %0, %%rax\n" - : "=r"(n_written) - : "a"(SYS_WRITE), "D"(fd), "S"(buf), "d"(size) // RDI, RSI, RDX are used in x86-64 for write args - : "rcx", "r11" - ); + asm volatile("syscall\n" + "movq %0, %%rax\n" + : "=r"(n_written) + : "a"(SYS_WRITE), "D"(fd), "S"(buf), + "d"(size) // RDI, RSI, RDX are used in x86-64 for write args + : "rcx", "r11"); return n_written; } #define SYS_READ 0 -intptr_t read(int32_t fd, const void* buf, intptr_t size) { +intptr_t read(int32_t fd, const void *buf, intptr_t size) { intptr_t n_read = 0; - asm volatile ( - "syscall\n" - "movq %0, %%rax\n" - : "=r"(n_read) - : "a"(SYS_READ), "D"(fd), "S"(buf), "d"(size) // RDI, RSI, RDX are used in x86-64 for write args - : "rcx", "r11", "memory" - ); + asm volatile("syscall\n" + "movq %0, %%rax\n" + : "=r"(n_read) + : "a"(SYS_READ), "D"(fd), "S"(buf), + "d"(size) // RDI, RSI, RDX are used in x86-64 for write args + : "rcx", "r11", "memory"); return n_read; } #define SYS_FORK 57 uint32_t fork() { uint64_t rtn; - asm volatile( - "syscall\n" // syscall - "movq %0, %%rax\n" // save return value - : "=r"(rtn) - : "a"(SYS_FORK) - : - ); + asm volatile("syscall\n" // syscall + "movq %0, %%rax\n" // save return value + : "=r"(rtn) + : "a"(SYS_FORK) + :); return (uint32_t)rtn; } +#define SYS_EXECVE 59 +int32_t execve(const char *filename, const char *argv[], const char *envp[]) { + int64_t rtn; + asm volatile("syscall\n" + : "=r"(rtn) + : "a"(SYS_EXECVE), "D"(filename), "S"(argv), "d"(envp) + : "rcx", "r11"); + return (int32_t)rtn; +} + +#define SYS_WAIT4 61 +uint32_t wait4(uint32_t pid, int *wstatus, int options, void *rusage) { + uint32_t child_pid; + asm volatile("mov %5, %%r10\n" + "syscall\n" + : "=a"(child_pid) + : "a"(SYS_WAIT4), "D"(pid), "S"(wstatus), "d"(options), + "r"(rusage) + : "rcx", "r10", "r11", "memory"); + return child_pid; +} +uint32_t waitpid(uint32_t pid, int *wstatus, int options) { + return wait4(pid, wstatus, options, 0); +} + #define SYS_OPENAT 257 -int32_t openat(int32_t fd, const char* filename, uint32_t flags, uint32_t mode) { +int32_t openat(int32_t fd, const char *filename, uint32_t flags, + uint32_t mode) { int32_t file; - asm volatile ( + asm volatile( "mov %5, %%r10\n" "syscall\n" : "=a"(file) - : "a"(SYS_OPENAT), "D"(fd), "S"(filename), "d"(flags), "r"((uint64_t)mode) // RDI, RSI, RDX are used in x86-64 for write args - : "rcx", "r10", "r11" - ); + : "a"(SYS_OPENAT), "D"(fd), "S"(filename), "d"(flags), + "r"((uint64_t)mode) // RDI, RSI, RDX are used in x86-64 for write args + : "rcx", "r10", "r11"); return file; } #define SYS_CLOSE 3 int close(unsigned int fd) { int rtn; - asm volatile( - "syscall" - : "=a"(rtn) - : "a"(SYS_CLOSE), "D"(fd) - : "rcx", "r11" - ); + asm volatile("syscall" : "=a"(rtn) : "a"(SYS_CLOSE), "D"(fd) : "rcx", "r11"); return rtn; } #define SYS_FSYNC 74 int fsync(unsigned int fd) { int rtn; - asm volatile( - "syscall" - : "=a"(rtn) - : "a"(SYS_FSYNC), "D"(fd) - : "rcx", "r11" - ); + asm volatile("syscall" : "=a"(rtn) : "a"(SYS_FSYNC), "D"(fd) : "rcx", "r11"); return rtn; } #define SYS_SOCKET 41 int socket(int domain, int type, int protocol) { int32_t fd; - asm volatile ( - "syscall\n" - : "=a"(fd) - : "a"(SYS_SOCKET), "D"(domain), "S"(type), "d"(protocol) - : "rcx", "r11" - ); + asm volatile("syscall\n" + : "=a"(fd) + : "a"(SYS_SOCKET), "D"(domain), "S"(type), "d"(protocol) + : "rcx", "r11"); return fd; } #define SYS_SETSOCKOPT 54 -int setsockopt(int fd, int level, int optname, const void* optval, socklen_t optlen) { +int setsockopt(int fd, int level, int optname, const void *optval, + socklen_t optlen) { int rtn; - asm volatile( - "mov %5, %%r10\n" - "mov %6, %%r8\n" - "syscall\n" - : "=a"(rtn) - : "a"(SYS_SETSOCKOPT), "D"(fd), "S"(level), "d"(optname), "r"(optval), "r"((uint64_t)optlen) - : "rcx", "r11" - ); + asm volatile("mov %5, %%r10\n" + "mov %6, %%r8\n" + "syscall\n" + : "=a"(rtn) + : "a"(SYS_SETSOCKOPT), "D"(fd), "S"(level), "d"(optname), + "r"(optval), "r"((uint64_t)optlen) + : "rcx", "r11"); return rtn; } #define SYS_BIND 49 -int bind(int fd, const void* sockaddr, socklen_t addrlen) { +int bind(int fd, const void *sockaddr, socklen_t addrlen) { int rtn; - asm volatile( - "syscall\n" - : "=a"(rtn) - : "a"(SYS_BIND), "D"(fd), "S"(sockaddr), "d"(addrlen) - : "rcx", "r11" - ); + asm volatile("syscall\n" + : "=a"(rtn) + : "a"(SYS_BIND), "D"(fd), "S"(sockaddr), "d"(addrlen) + : "rcx", "r11"); return rtn; } #define SYS_LISTEN 50 int listen(int fd, int backlog) { int rtn; - asm volatile( - "syscall\n" - : "=a"(rtn) - : "a"(SYS_LISTEN), "D"(fd), "S"(backlog) - : "rcx", "r11" - ); + asm volatile("syscall\n" + : "=a"(rtn) + : "a"(SYS_LISTEN), "D"(fd), "S"(backlog) + : "rcx", "r11"); return rtn; } #define SYS_ACCEPT 43 -int accept(int fd, void* addr, socklen_t* addrlen) { +int accept(int fd, void *addr, socklen_t *addrlen) { int rtn; - asm volatile( - "syscall\n" - : "=a"(rtn) - : "a"(SYS_ACCEPT), "D"(fd), "S"(addr), "d"(addrlen) - : "rcx", "r11", "memory" - ); + asm volatile("syscall\n" + : "=a"(rtn) + : "a"(SYS_ACCEPT), "D"(fd), "S"(addr), "d"(addrlen) + : "rcx", "r11", "memory"); return rtn; } #define SYS_CONNECT 42 -int connect(int fd, void* addr, socklen_t addrlen) { +int connect(int fd, void *addr, socklen_t addrlen) { int rtn; - asm volatile( - "syscall\n" - : "=a"(rtn) - : "a"(SYS_CONNECT), "D"(fd), "S"(addr), "d"(addrlen) - : "rcx", "r11" - ); + asm volatile("syscall\n" + : "=a"(rtn) + : "a"(SYS_CONNECT), "D"(fd), "S"(addr), "d"(addrlen) + : "rcx", "r11"); return rtn; } #define SYS_SENDTO 44 -ssize_t sendto(int fd, const void* buf, size_t size, int flags, const void* sockaddr, socklen_t addrlen) { +ssize_t sendto(int fd, const void *buf, size_t size, int flags, + const void *sockaddr, socklen_t addrlen) { ssize_t nsent; - asm volatile( - "mov %5, %%r10\n" - "mov %6, %%r8\n" - "mov %7, %%r9\n" - "syscall\n" - : "=a"(nsent) - : "a"(SYS_SENDTO), "D"(fd), "S"(buf), "d"(size), "r"((int64_t)flags), "r"(sockaddr), "r"((uint64_t)addrlen) - : "rcx", "r11" - ); + asm volatile("mov %5, %%r10\n" + "mov %6, %%r8\n" + "mov %7, %%r9\n" + "syscall\n" + : "=a"(nsent) + : "a"(SYS_SENDTO), "D"(fd), "S"(buf), "d"(size), + "r"((int64_t)flags), "r"(sockaddr), "r"((uint64_t)addrlen) + : "rcx", "r11"); return nsent; } #define SYS_RECVFROM 45 -ssize_t recvfrom(int fd, const void* buf, size_t size, int flags, const void* sockaddr, socklen_t addrlen) { +ssize_t recvfrom(int fd, const void *buf, size_t size, int flags, + const void *sockaddr, socklen_t addrlen) { ssize_t nrecv; - asm volatile( - "mov %5, %%r10\n" - "mov %6, %%r8\n" - "mov %7, %%r9\n" - "syscall\n" - : "=a"(nrecv) - : "a"(SYS_RECVFROM), "D"(fd), "S"(buf), "d"(size), "r"((int64_t)flags), "r"(sockaddr), "r"((int64_t)addrlen) - : "rcx", "r11", "memory" - ); + asm volatile("mov %5, %%r10\n" + "mov %6, %%r8\n" + "mov %7, %%r9\n" + "syscall\n" + : "=a"(nrecv) + : "a"(SYS_RECVFROM), "D"(fd), "S"(buf), "d"(size), + "r"((int64_t)flags), "r"(sockaddr), "r"((int64_t)addrlen) + : "rcx", "r11", "memory"); return nrecv; } #define SYS_CLOCK_SETTIME 227 int clock_settime(clockid_t clockid, const struct timespec *tp) { int rtn; - asm volatile( - "syscall\n" - : "=a"(rtn) - : "a"(SYS_CLOCK_SETTIME), "D"(clockid), "S"(tp) - : "rcx", "r11" - ); + asm volatile("syscall\n" + : "=a"(rtn) + : "a"(SYS_CLOCK_SETTIME), "D"(clockid), "S"(tp) + : "rcx", "r11"); return rtn; } #define SYS_CLOCK_GETTIME 228 int clock_gettime(clockid_t clockid, struct timespec *tp) { int rtn; - asm volatile( - "syscall\n" - : "=a"(rtn) - : "a"(SYS_CLOCK_GETTIME), "D"(clockid), "S"(tp) - : "rcx", "r11", "memory" - ); + asm volatile("syscall\n" + : "=a"(rtn) + : "a"(SYS_CLOCK_GETTIME), "D"(clockid), "S"(tp) + : "rcx", "r11", "memory"); return rtn; } #define SYS_CLOCK_GETRES 229 -int clock_getres(clockid_t clockid, struct timespec *res){ +int clock_getres(clockid_t clockid, struct timespec *res) { int rtn; - asm volatile( - "syscall\n" - : "=a"(rtn) - : "a"(SYS_CLOCK_GETRES), "D"(clockid), "S"(res) - : "rcx", "r11", "memory" - ); + asm volatile("syscall\n" + : "=a"(rtn) + : "a"(SYS_CLOCK_GETRES), "D"(clockid), "S"(res) + : "rcx", "r11", "memory"); return rtn; } #define SYS_CLOCK_NANOSLEEP 230 -int clock_nanosleep(clockid_t clockid, int flags, const struct timespec *t, struct timespec* remain){ +int clock_nanosleep(clockid_t clockid, int flags, const struct timespec *t, + struct timespec *remain) { int rtn; - asm volatile( - "mov %5, %%r10\n" - "syscall\n" - : "=a"(rtn) - : "a"(SYS_CLOCK_NANOSLEEP), "D"(clockid), "S"(flags), "d"(t), "r"(remain) - : "rcx", "r11", "memory" - ); + asm volatile("mov %5, %%r10\n" + "syscall\n" + : "=a"(rtn) + : "a"(SYS_CLOCK_NANOSLEEP), "D"(clockid), "S"(flags), "d"(t), + "r"(remain) + : "rcx", "r11", "memory"); return rtn; } #define SYS_RT_SIGACTION 13 -int rt_sigaction(int signum, const void* act, void* oldact, size_t sigset_len) { +int rt_sigaction(int signum, const void *act, void *oldact, size_t sigset_len) { int rtn; - asm volatile( - "mov %5, %%r10\n" - "syscall\n" - : "=a"(rtn) - : "a"(SYS_RT_SIGACTION), "D"(signum), "S"(act), "d"(oldact), "r"(sigset_len) - : "rcx", "r11", "memory" - ); + asm volatile("mov %5, %%r10\n" + "syscall\n" + : "=a"(rtn) + : "a"(SYS_RT_SIGACTION), "D"(signum), "S"(act), "d"(oldact), + "r"(sigset_len) + : "rcx", "r11", "memory"); return rtn; } diff --git a/buildtest.c b/buildtest.c index 97ad897..24598f4 100644 --- a/buildtest.c +++ b/buildtest.c @@ -34,10 +34,24 @@ int main(int argc, char* argv[]) { uint64_t pid = fork(); // Print the pid in hex printhex(pid); - - // Child process exits - if(pid == 0) return 0; - //TODO: wait on child to remove zombie process + // Child process + if (pid == 0) { + const char *progname = "/bin/sh"; + const char *argv[4] = { + progname, + "-c", + "echo hi from sh", + 0, + }; + const char **envp = {0}; + int32_t err = execve(progname, argv, envp); + // return with error code if execve fails + return err; + } + int status; // Note: this is not JUST the exit code of the child + waitpid(pid, &status, 0); + print("Child wstatus: "); + printhex((uint64_t)status); // Test the read syscall #define INPUT_BUFFER_LEN 4096 diff --git a/sys.h b/sys.h index 791acbf..f3036b9 100644 --- a/sys.h +++ b/sys.h @@ -141,6 +141,8 @@ int clock_nanosleep(clockid_t clockid, int flags, const struct timespec *t, stru #define nanosleep(t, remain) clock_nanosleep(CLOCK_MONOTONIC, 0, t, remain) uint32_t fork(); +int32_t execve(const char* filename, const char* argv[], const char* envp[]); +uint32_t waitpid(uint32_t pid, int* wstatus, int options); void *memset(void* s, int c, unsigned long n); int strlen(char* s);