Compare commits
36 Commits
ff71a50db7
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 73ad441585 | |||
| ea0ec6a818 | |||
| ed7a811736 | |||
| f7109b8743 | |||
| cc557ed1b9 | |||
| 02f308ffbd | |||
| 7c8c2e2dc2 | |||
| 9163857e83 | |||
| d47709b03c | |||
| ab5dd8d9fb | |||
| 74cfa5f949 | |||
| 37bf95704e | |||
| 42268b6cc2 | |||
| f98b95ac4a | |||
| abbace3df4 | |||
| b890d54c8f | |||
| 52a7a909ff | |||
| adfdaa27f7 | |||
| f07d793e6c | |||
| faab7a9622 | |||
| eda1bbca23 | |||
| 39e797f937 | |||
| 0caa6320b1 | |||
| 47d317b977 | |||
| f5722b2c09 | |||
| cbd613e068 | |||
| 0eaae16280 | |||
| 519de693ec | |||
| bd9a3d3b99 | |||
| c8875d39f2 | |||
|
|
6a51f8851b | ||
|
|
8a01908b1c | ||
| a8594606c3 | |||
| 6902b49be2 | |||
| c2d03d048a | |||
| d37d65b500 |
11
.gitignore
vendored
11
.gitignore
vendored
@@ -1,10 +1,3 @@
|
|||||||
print
|
|
||||||
print_aarch64
|
|
||||||
print_mips32
|
|
||||||
print_x64
|
|
||||||
bldtst
|
|
||||||
bldtst_aarch64
|
|
||||||
bldtst_mips32
|
|
||||||
bldtst_x64
|
|
||||||
bldtst_llvm
|
|
||||||
a.out
|
a.out
|
||||||
|
bin
|
||||||
|
tmp
|
||||||
|
|||||||
97
Makefile
97
Makefile
@@ -1,32 +1,85 @@
|
|||||||
all: buildtest
|
bindir ?= ./bin
|
||||||
|
|
||||||
|
CFLAGS := -nostdlib -static -fuse-ld=lld -fno-stack-protector
|
||||||
|
|
||||||
|
CLANG_WNO := -Wno-incompatible-library-redeclaration
|
||||||
|
GCC_WNO := -Wno-builtin-declaration-mismatch
|
||||||
|
|
||||||
|
MIPS_CFLAGS := --target=mips-linux-gnu -fno-pic
|
||||||
|
MIPSEL_CFLAGS := --target=mipsel-linux-gnu -fno-pic
|
||||||
|
X86_64_CFLAGS := --target=x86_64-linux-gnu
|
||||||
|
|
||||||
|
AARCH64_CFLAGS := --target=aarch64-linux-gnu
|
||||||
|
|
||||||
|
all: buildtest socktest stackdump
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
if test -f print; then rm print; fi
|
rm $(bindir)/*
|
||||||
if test -f print_x64; then rm print_x64; fi
|
|
||||||
if test -f print_aarch64; then rm print_aarch64; fi
|
|
||||||
if test -f print_mips32; then rm print_mips32; fi
|
|
||||||
if test -f bldtst; then rm bldtst; fi
|
|
||||||
if test -f bldtst_llvm; then rm bldtst_llvm; fi
|
|
||||||
if test -f bldtst_x64; then rm bldtst_x64; fi
|
|
||||||
if test -f bldtst_aarch64; then rm bldtst_aarch64; fi
|
|
||||||
if test -f bldtst_mips32; then rm bldtst_mips32; fi
|
|
||||||
|
|
||||||
buildtest: bldtst bldtst_llvm bldtst_x64 bldtst_aarch64 bldtst_mips32
|
$(bindir)/:
|
||||||
|
mkdir -p ${bindir}
|
||||||
|
|
||||||
.PHONY: all buildtest clean
|
headers := sys.h int.h
|
||||||
|
buildtest: $(bindir)/bldtst $(bindir)/bldtst_llvm $(bindir)/bldtst_x64 $(bindir)/bldtst_aarch64 $(bindir)/bldtst_mips $(bindir)/bldtst_mipsel
|
||||||
|
socktest: $(bindir)/socktest $(bindir)/socktest_llvm $(bindir)/socktest_x64 $(bindir)/socktest_aarch64 $(bindir)/socktest_mips $(bindir)/socktest_mipsel
|
||||||
|
stackdump: $(bindir)/stackdump $(bindir)/stackdump_llvm $(bindir)/stackdump_x64 $(bindir)/stackdump_aarch64 $(bindir)/stackdump_mips $(bindir)/stackdump_mipsel
|
||||||
|
|
||||||
|
|
||||||
bldtst: buildtest.c arch/*.c
|
.PHONY: all clean buildtest socktest stackdump
|
||||||
gcc -static -nostdlib -Wno-builtin-declaration-mismatch -fno-stack-protector -o bldtst buildtest.c arch/*.c
|
|
||||||
|
|
||||||
bldtst_llvm: buildtest.c arch/*.c
|
|
||||||
clang -nostdlib -Wno-incompatible-library-redeclaration -static -fuse-ld=lld -fno-stack-protector -o bldtst_llvm buildtest.c arch/*.c
|
|
||||||
|
|
||||||
bldtst_x64: buildtest.c arch/x86_64.c
|
${bindir}/bldtst: buildtest.c $(headers) arch/* | $(bindir)/
|
||||||
clang --target=x86_64-linux-gnu -nostdlib -Wno-incompatible-library-redeclaration -static -fuse-ld=lld -fno-stack-protector -o bldtst_x64 buildtest.c arch/x86_64.c
|
gcc $(CFLAGS) $(GCC_WNO) -o $@ buildtest.c arch/*.c
|
||||||
|
|
||||||
bldtst_aarch64: buildtest.c
|
${bindir}/bldtst_llvm: $(headers) buildtest.c arch/* | $(bindir)/
|
||||||
clang --target=aarch64-linux-gnu -nostdlib -Wno-incompatible-library-redeclaration -static -fuse-ld=lld -fno-stack-protector -o bldtst_aarch64 buildtest.c arch/aarch64.c
|
clang $(CFLAGS) $(CLANG_WNO) -o $@ buildtest.c arch/*.c
|
||||||
|
|
||||||
bldtst_mips32: buildtest.c
|
${bindir}/bldtst_x64: $(headers) buildtest.c arch/x86_64.c arch/generic.h | $(bindir)/
|
||||||
clang --target=mips-linux-gnu -nostdlib -Wno-incompatible-library-redeclaration -static -fuse-ld=lld -fno-stack-protector -fno-pic -o bldtst_mips32 buildtest.c arch/mips.c
|
clang $(X86_64_CFLAGS) $(CFLAGS) $(CLANG_WNO) -o $@ buildtest.c arch/x86_64.c
|
||||||
|
|
||||||
|
${bindir}/bldtst_aarch64: $(headers) buildtest.c arch/aarch64.c arch/generic.h | $(bindir)/
|
||||||
|
clang $(AARCH64_CFLAGS) $(CFLAGS) $(CLANG_WNO) -o $@ buildtest.c arch/aarch64.c
|
||||||
|
|
||||||
|
${bindir}/bldtst_mips: $(headers) buildtest.c arch/mips.c arch/generic.h | $(bindir)/
|
||||||
|
clang $(MIPS_CFLAGS) $(CFLAGS) $(CLANG_WNO) -o $@ buildtest.c arch/mips.c
|
||||||
|
|
||||||
|
${bindir}/bldtst_mipsel: $(headers) buildtest.c arch/mips.c arch/generic.h | $(bindir)/
|
||||||
|
clang $(MIPSEL_CFLAGS) $(CFLAGS) $(CLANG_WNO) -o $@ buildtest.c arch/mips.c
|
||||||
|
|
||||||
|
|
||||||
|
${bindir}/socktest: socktest.c $(headers) arch/* | $(bindir)/
|
||||||
|
gcc $(CFLAGS) $(GCC_WNO) -o $@ socktest.c arch/*.c
|
||||||
|
|
||||||
|
${bindir}/socktest_llvm: $(headers) socktest.c arch/* | $(bindir)/
|
||||||
|
clang $(CFLAGS) $(CLANG_WNO) -o $@ socktest.c arch/*.c
|
||||||
|
|
||||||
|
${bindir}/socktest_x64: $(headers) socktest.c arch/x86_64.c arch/generic.h | $(bindir)/
|
||||||
|
clang $(X86_64_CFLAGS) $(CFLAGS) $(CLANG_WNO) -o $@ socktest.c arch/x86_64.c
|
||||||
|
|
||||||
|
${bindir}/socktest_aarch64: $(headers) socktest.c arch/aarch64.c arch/generic.h | $(bindir)/
|
||||||
|
clang $(AARCH64_CFLAGS) $(CFLAGS) $(CLANG_WNO) -o $@ socktest.c arch/aarch64.c
|
||||||
|
|
||||||
|
${bindir}/socktest_mips: $(headers) socktest.c arch/mips.c arch/generic.h | $(bindir)/
|
||||||
|
clang $(MIPS_CFLAGS) $(CFLAGS) $(CLANG_WNO) -o $@ socktest.c arch/mips.c
|
||||||
|
|
||||||
|
${bindir}/socktest_mipsel: $(headers) socktest.c arch/mips.c arch/generic.h | $(bindir)/
|
||||||
|
clang $(MIPSEL_CFLAGS) $(CFLAGS) $(CLANG_WNO) -o $@ socktest.c arch/mips.c
|
||||||
|
|
||||||
|
|
||||||
|
${bindir}/stackdump: stackdump.c $(headers) arch/* | $(bindir)/
|
||||||
|
gcc -D _START_DEFINED $(CFLAGS) $(GCC_WNO) -o $@ stackdump.c arch/*.c
|
||||||
|
|
||||||
|
${bindir}/stackdump_llvm: $(headers) stackdump.c arch/* | $(bindir)/
|
||||||
|
clang -D _START_DEFINED $(CFLAGS) $(CLANG_WNO) -o $@ stackdump.c arch/*.c
|
||||||
|
|
||||||
|
${bindir}/stackdump_x64: $(headers) stackdump.c arch/x86_64.c arch/generic.h | $(bindir)/
|
||||||
|
clang -D _START_DEFINED $(X86_64_CFLAGS) $(CFLAGS) $(CLANG_WNO) -o $@ stackdump.c arch/x86_64.c
|
||||||
|
|
||||||
|
${bindir}/stackdump_aarch64: $(headers) stackdump.c arch/aarch64.c arch/generic.h | $(bindir)/
|
||||||
|
clang -D _START_DEFINED $(AARCH64_CFLAGS) $(CFLAGS) $(CLANG_WNO) -o $@ stackdump.c arch/aarch64.c
|
||||||
|
|
||||||
|
${bindir}/stackdump_mips: $(headers) stackdump.c arch/mips.c arch/generic.h | $(bindir)/
|
||||||
|
clang -D _START_DEFINED $(MIPS_CFLAGS) $(CFLAGS) $(CLANG_WNO) -o $@ stackdump.c arch/mips.c
|
||||||
|
|
||||||
|
${bindir}/stackdump_mipsel: $(headers) stackdump.c arch/mips.c arch/generic.h | $(bindir)/
|
||||||
|
clang -D _START_DEFINED $(MIPSEL_CFLAGS) $(CFLAGS) $(CLANG_WNO) -o $@ stackdump.c arch/mips.c
|
||||||
|
|||||||
387
arch/aarch64.c
387
arch/aarch64.c
@@ -1,5 +1,7 @@
|
|||||||
#if defined(__aarch64__)
|
#if defined(__aarch64__)
|
||||||
#include <stdint.h>
|
#include "../int.h"
|
||||||
|
|
||||||
|
#include "generic.h"
|
||||||
|
|
||||||
void exit(int8_t status){
|
void exit(int8_t status){
|
||||||
asm ( "mov x0, %0\n" // Move the exit status into register x0
|
asm ( "mov x0, %0\n" // Move the exit status into register x0
|
||||||
@@ -14,24 +16,51 @@ void exit(int8_t status){
|
|||||||
|
|
||||||
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;
|
intptr_t n_written = 0;
|
||||||
|
//register int32_t fd_w asm("w0") = fd;
|
||||||
asm volatile(
|
asm volatile(
|
||||||
"mov x0, %2\n"
|
// Assembly Instructions
|
||||||
"mov x1, %0\n"
|
"mov x0, %1\n" // Set x0 to value of fd
|
||||||
"mov x2, %1\n"
|
"mov x1, %2\n" // Set x1 to value of buf
|
||||||
"mov x8, #64\n"
|
"mov x2, %3\n" // Set x2 to value of size
|
||||||
"svc #0\n"
|
"mov x8, #64\n" // Syscall number for 'write' is 64 in AArch64
|
||||||
: //TODO: n_written
|
"svc #0\n" // Make syscall
|
||||||
: "r" (buf), "r"(size), "r"(fd)
|
"mov %0, x0\n" // Store return value in n_written
|
||||||
: "x0", "x8" // Clobbered registers
|
// Output operands
|
||||||
|
: "=r"(n_written)
|
||||||
|
// Input operands
|
||||||
|
: "r"((int64_t)fd), "r" (buf), "r"(size)
|
||||||
|
// Clobbered registers
|
||||||
|
: "x0", "x1", "x2", "x8"
|
||||||
);
|
);
|
||||||
return n_written;
|
return n_written;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
intptr_t read(int32_t fd, const void* buf, intptr_t size){
|
||||||
|
intptr_t n_read = 0;
|
||||||
|
asm volatile(
|
||||||
|
// Assembly Instructions
|
||||||
|
"mov x0, %1\n" // Set x0 to value of fd
|
||||||
|
"mov x1, %2\n" // Set x1 to value of buf
|
||||||
|
"mov x2, %3\n" // Set x2 to value of size
|
||||||
|
"mov x8, #63\n" // Syscall number for 'read' is 63 in AArch64
|
||||||
|
"svc #0\n" // Make syscall
|
||||||
|
"mov %0, x0\n" // Store return value in n_read
|
||||||
|
// Output operands
|
||||||
|
: "=r"(n_read)
|
||||||
|
// Input operands
|
||||||
|
: "r"((int64_t)fd), "r" (buf), "r"(size)
|
||||||
|
// Clobbered registers
|
||||||
|
: "x0", "x1", "x2", "x8", "memory"
|
||||||
|
);
|
||||||
|
return n_read;
|
||||||
|
}
|
||||||
|
|
||||||
#define CLONE_CHILD_SETTID 0x1000000
|
#define CLONE_CHILD_SETTID 0x1000000
|
||||||
#define CLONE_CHILD_CLEARTID 0x200000
|
#define CLONE_CHILD_CLEARTID 0x200000
|
||||||
|
#define SIGCHLD 0x11
|
||||||
uint32_t fork(){
|
uint32_t fork(){
|
||||||
long int rtn;
|
long int rtn;
|
||||||
long int flags = CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID;
|
long int flags = CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID | SIGCHLD;
|
||||||
asm volatile (
|
asm volatile (
|
||||||
// Assembly Instructions
|
// Assembly Instructions
|
||||||
"mov x8, #220\n" // Syscall number for 'clone' is 220 in AArch64
|
"mov x8, #220\n" // Syscall number for 'clone' is 220 in AArch64
|
||||||
@@ -52,4 +81,342 @@ uint32_t fork(){
|
|||||||
return (uint32_t)rtn;
|
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 (
|
||||||
|
// Assembly Instructions
|
||||||
|
"mov x8, #56\n" // Syscall number for 'openat' is 56 in AArch64
|
||||||
|
"mov x0, %1\n" // dir fd
|
||||||
|
"mov x1, %2\n" // file path
|
||||||
|
"mov x2, %3\n" // flags
|
||||||
|
"mov x3, %4\n" // mode
|
||||||
|
"svc #0\n" // Make the syscall
|
||||||
|
"mov %0, x0\n" // save return value
|
||||||
|
// Output operands
|
||||||
|
: "=r" (rtn)
|
||||||
|
// Input operand
|
||||||
|
: "r" ((int64_t)fd), "r"(filename), "r"((int64_t)flags), "r"((int64_t)mode)
|
||||||
|
// Clobbered registers
|
||||||
|
: "x0", "x1", "x2", "x3", "x8"
|
||||||
|
);
|
||||||
|
return (int32_t)rtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
int close(unsigned int fd){
|
||||||
|
long int rtn;
|
||||||
|
asm (
|
||||||
|
"mov x0, %1\n"
|
||||||
|
"mov x8, #57\n"
|
||||||
|
"svc #0\n"
|
||||||
|
"mov %0, x0\n"
|
||||||
|
: "=r"(rtn)
|
||||||
|
: "r" ((long)fd)
|
||||||
|
: "x0", "x8"
|
||||||
|
);
|
||||||
|
return (int)rtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fsync(unsigned int fd){
|
||||||
|
long int rtn;
|
||||||
|
asm (
|
||||||
|
"mov x0, %1\n"
|
||||||
|
"mov x8, #82\n"
|
||||||
|
"svc #0\n"
|
||||||
|
"mov %0, x0\n"
|
||||||
|
: "=r"(rtn)
|
||||||
|
: "r" ((long)fd)
|
||||||
|
: "x0", "x8"
|
||||||
|
);
|
||||||
|
return (int)rtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
int socket(int domain, int type, int protocol) {
|
||||||
|
long int rtn;
|
||||||
|
asm volatile (
|
||||||
|
// Assembly Instructions
|
||||||
|
"mov x8, #198\n" // Syscall number for 'socket' is 198 in AArch64
|
||||||
|
"mov x0, %1\n" // domain
|
||||||
|
"mov x1, %2\n" // type
|
||||||
|
"mov x2, %3\n" // protocol
|
||||||
|
"svc #0\n" // Make the syscall
|
||||||
|
"mov %0, x0\n" // save return value
|
||||||
|
// Output operands
|
||||||
|
: "=r" (rtn)
|
||||||
|
// Input operand
|
||||||
|
: "r" ((int64_t)domain), "r"((int64_t)type), "r"((int64_t)protocol)
|
||||||
|
// Clobbered registers
|
||||||
|
: "x0", "x1", "x2", "x8"
|
||||||
|
);
|
||||||
|
return (int32_t)rtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
int setsockopt(int sockfd, int level, int optname, const void* optval, socklen_t optlen) {
|
||||||
|
long int rtn;
|
||||||
|
asm volatile (
|
||||||
|
// Assembly Instructions
|
||||||
|
"mov x8, #208\n" // Syscall number for 'setsockopt' is 208 in AArch64
|
||||||
|
"mov x0, %1\n" // sockfd
|
||||||
|
"mov x1, %2\n" // level
|
||||||
|
"mov x2, %3\n" // optname
|
||||||
|
"mov x3, %4\n" // optval
|
||||||
|
"mov x4, %5\n" // optlen
|
||||||
|
"svc #0\n" // Make the syscall
|
||||||
|
"mov %0, x0\n" // save return value
|
||||||
|
// Output operands
|
||||||
|
: "=r" (rtn)
|
||||||
|
// Input operand
|
||||||
|
: "r" ((int64_t)sockfd), "r"((int64_t)level), "r"((int64_t)optname), "r"(optval), "r"((uint64_t)optlen)
|
||||||
|
// Clobbered registers
|
||||||
|
: "x0", "x1", "x2", "x3", "x4", "x8"
|
||||||
|
);
|
||||||
|
return (int32_t)rtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bind(int sockfd, const void* sockaddr, socklen_t addrlen) {
|
||||||
|
long int rtn;
|
||||||
|
asm volatile (
|
||||||
|
// Assembly Instructions
|
||||||
|
"mov x8, #200\n" // Syscall number for 'bind' is 200 in AArch64
|
||||||
|
"mov x0, %1\n" // sockfd
|
||||||
|
"mov x1, %2\n" // sockaddr
|
||||||
|
"mov x2, %3\n" // addrlen
|
||||||
|
"svc #0\n" // Make the syscall
|
||||||
|
"mov %0, x0\n" // save return value
|
||||||
|
// Output operands
|
||||||
|
: "=r" (rtn)
|
||||||
|
// Input operand
|
||||||
|
: "r" ((int64_t)sockfd), "r"(sockaddr), "r"((uint64_t)addrlen)
|
||||||
|
// Clobbered registers
|
||||||
|
: "x0", "x1", "x2", "x8"
|
||||||
|
);
|
||||||
|
return (int32_t)rtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
int listen(int fd, int backlog) {
|
||||||
|
long int rtn;
|
||||||
|
asm volatile (
|
||||||
|
// Assembly Instructions
|
||||||
|
"mov x8, #201\n" // Syscall number for 'listen' is 201 in AArch64
|
||||||
|
"mov x0, %1\n" // fd
|
||||||
|
"mov x1, %2\n" // backlog
|
||||||
|
"svc #0\n" // Make the syscall
|
||||||
|
"mov %0, x0\n" // save return value
|
||||||
|
// Output operands
|
||||||
|
: "=r" (rtn)
|
||||||
|
// Input operand
|
||||||
|
: "r" ((int64_t)fd), "r"((int64_t)backlog)
|
||||||
|
// Clobbered registers
|
||||||
|
: "x0", "x1", "x8"
|
||||||
|
);
|
||||||
|
return (int32_t)rtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
int accept(int sockfd, void* addr, socklen_t* addrlen) {
|
||||||
|
long int rtn;
|
||||||
|
asm volatile (
|
||||||
|
// Assembly Instructions
|
||||||
|
"mov x8, #202\n" // Syscall number for 'accept' is 202 in AArch64
|
||||||
|
"mov x0, %1\n" // sockfd
|
||||||
|
"mov x1, %2\n" // addr
|
||||||
|
"mov x2, %3\n" // addrlen
|
||||||
|
"svc #0\n" // Make the syscall
|
||||||
|
"mov %0, x0\n" // save return value
|
||||||
|
// Output operands
|
||||||
|
: "=r" (rtn)
|
||||||
|
// Input operand
|
||||||
|
: "r" ((int64_t)sockfd), "r"(addr), "r"(addrlen)
|
||||||
|
// Clobbered registers
|
||||||
|
: "x0", "x1", "x2", "x8", "memory"
|
||||||
|
);
|
||||||
|
return (int32_t)rtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
int connect(int sockfd, void* addr, socklen_t addrlen) {
|
||||||
|
long int rtn;
|
||||||
|
asm volatile (
|
||||||
|
// Assembly Instructions
|
||||||
|
"mov x8, #203\n" // Syscall number for 'connect' is 203 in AArch64
|
||||||
|
"mov x0, %1\n" // sockfd
|
||||||
|
"mov x1, %2\n" // addr
|
||||||
|
"mov x2, %3\n" // addrlen
|
||||||
|
"svc #0\n" // Make the syscall
|
||||||
|
"mov %0, x0\n" // save return value
|
||||||
|
// Output operands
|
||||||
|
: "=r" (rtn)
|
||||||
|
// Input operand
|
||||||
|
: "r" ((int64_t)sockfd), "r"(addr), "r"((uint64_t)addrlen)
|
||||||
|
// Clobbered registers
|
||||||
|
: "x0", "x1", "x2", "x8"
|
||||||
|
);
|
||||||
|
return (int32_t)rtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t sendto(int sockfd, const void* buf, size_t size, int flags, const void* sockaddr, socklen_t addrlen) {
|
||||||
|
ssize_t rtn;
|
||||||
|
asm volatile (
|
||||||
|
// Assembly Instructions
|
||||||
|
"mov x8, #206\n" // Syscall number for 'sendto' is 206 in AArch64
|
||||||
|
"mov x0, %1\n" //
|
||||||
|
"mov x1, %2\n" //
|
||||||
|
"mov x2, %3\n" //
|
||||||
|
"mov x3, %4\n" //
|
||||||
|
"mov x4, %5\n"
|
||||||
|
"mov x5, %6\n"
|
||||||
|
"svc #0\n" // Make the syscall
|
||||||
|
"mov %0, x0\n" // save return value
|
||||||
|
// Output operands
|
||||||
|
: "=r" (rtn)
|
||||||
|
// Input operand
|
||||||
|
: "r" ((int64_t)sockfd), "r"(buf), "r"(size), "r"((int64_t)flags), "r"(sockaddr), "r"((uint64_t)addrlen)
|
||||||
|
// Clobbered registers
|
||||||
|
: "x0", "x1", "x2", "x3", "x4", "x5", "x8"
|
||||||
|
);
|
||||||
|
return rtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t recvfrom(int sockfd, const void* buf, size_t size, int flags, const void* sockaddr, socklen_t addrlen) {
|
||||||
|
ssize_t rtn;
|
||||||
|
asm volatile (
|
||||||
|
// Assembly Instructions
|
||||||
|
"mov x8, #207\n" // Syscall number for 'recvfrom' is 207 in AArch64
|
||||||
|
"mov x0, %1\n" //
|
||||||
|
"mov x1, %2\n" //
|
||||||
|
"mov x2, %3\n" //
|
||||||
|
"mov x3, %4\n" //
|
||||||
|
"mov x4, %5\n"
|
||||||
|
"mov x5, %6\n"
|
||||||
|
"svc #0\n" // Make the syscall
|
||||||
|
"mov %0, x0\n" // save return value
|
||||||
|
// Output operands
|
||||||
|
: "=r" (rtn)
|
||||||
|
// Input operand
|
||||||
|
: "r" ((int64_t)sockfd), "r"(buf), "r"(size), "r"((int64_t)flags), "r"(sockaddr), "r"((uint64_t)addrlen)
|
||||||
|
// Clobbered registers
|
||||||
|
: "x0", "x1", "x2", "x3", "x4", "x5", "x8", "memory"
|
||||||
|
);
|
||||||
|
return rtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int clock_settime(clockid_t clockid, const struct timespec *tp) {
|
||||||
|
long int rtn;
|
||||||
|
asm volatile (
|
||||||
|
// Assembly Instructions
|
||||||
|
"mov x8, #112\n" // Syscall number for 'listen' is 201 in AArch64
|
||||||
|
"mov x0, %1\n" // fd
|
||||||
|
"mov x1, %2\n" // backlog
|
||||||
|
"svc #0\n" // Make the syscall
|
||||||
|
"mov %0, x0\n" // save return value
|
||||||
|
// Output operands
|
||||||
|
: "=r" (rtn)
|
||||||
|
// Input operand
|
||||||
|
: "r" ((int64_t)clockid), "r"(tp)
|
||||||
|
// Clobbered registers
|
||||||
|
: "x0", "x1", "x8"
|
||||||
|
);
|
||||||
|
return (int32_t)rtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
int clock_gettime(clockid_t clockid, struct timespec *tp) {
|
||||||
|
long int rtn;
|
||||||
|
asm volatile (
|
||||||
|
// Assembly Instructions
|
||||||
|
"mov x8, #113\n" // Syscall number for 'listen' is 201 in AArch64
|
||||||
|
"mov x0, %1\n" // fd
|
||||||
|
"mov x1, %2\n" // backlog
|
||||||
|
"svc #0\n" // Make the syscall
|
||||||
|
"mov %0, x0\n" // save return value
|
||||||
|
// Output operands
|
||||||
|
: "=r" (rtn)
|
||||||
|
// Input operand
|
||||||
|
: "r" ((int64_t)clockid), "r"(tp)
|
||||||
|
// Clobbered registers
|
||||||
|
: "x0", "x1", "x8", "memory"
|
||||||
|
);
|
||||||
|
return (int32_t)rtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
int clock_getres(clockid_t clockid, struct timespec *res) {
|
||||||
|
long int rtn;
|
||||||
|
asm volatile (
|
||||||
|
// Assembly Instructions
|
||||||
|
"mov x8, #114\n" // Syscall number for 'listen' is 201 in AArch64
|
||||||
|
"mov x0, %1\n" // fd
|
||||||
|
"mov x1, %2\n" // backlog
|
||||||
|
"svc #0\n" // Make the syscall
|
||||||
|
"mov %0, x0\n" // save return value
|
||||||
|
// Output operands
|
||||||
|
: "=r" (rtn)
|
||||||
|
// Input operand
|
||||||
|
: "r" ((int64_t)clockid), "r"(res)
|
||||||
|
// Clobbered registers
|
||||||
|
: "x0", "x1", "x8", "memory"
|
||||||
|
);
|
||||||
|
return (int32_t)rtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
int clock_nanosleep(clockid_t clockid, int flags, const struct timespec *t, struct timespec* remain) {
|
||||||
|
long int rtn;
|
||||||
|
asm volatile (
|
||||||
|
// Assembly Instructions
|
||||||
|
"mov x8, #115\n" // Syscall number for 'listen' is 201 in AArch64
|
||||||
|
"mov x0, %1\n" // fd
|
||||||
|
"mov x1, %2\n" // backlog
|
||||||
|
"mov x2, %3\n" // backlog
|
||||||
|
"svc #0\n" // Make the syscall
|
||||||
|
"mov %0, x0\n" // save return value
|
||||||
|
// Output operands
|
||||||
|
: "=r" (rtn)
|
||||||
|
// Input operand
|
||||||
|
: "r" ((int64_t)clockid), "r"((int64_t)flags), "r"(t), "r"(remain)
|
||||||
|
// Clobbered registers
|
||||||
|
: "x0", "x1", "x8", "memory"
|
||||||
|
);
|
||||||
|
return (int32_t)rtn;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
40
arch/generic.h
Normal file
40
arch/generic.h
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* This file is not meant to be included by user applications
|
||||||
|
* It contains generic arch agnostic implementations of helper functions
|
||||||
|
* and start code that can be included in <arch>.c when an architecture
|
||||||
|
* specific version is not nessisary.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2025 Lucas Schumacher. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MEMSET_DEFINED
|
||||||
|
#define MEMSET_DEFINED
|
||||||
|
// Generic memset implementation
|
||||||
|
void *memset(void* s, int c, unsigned long n) {
|
||||||
|
int8_t* mem = s;
|
||||||
|
for(long int i = 0; i < n; ++i) mem[i] = c;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
#endif // !MEMSET_DEFINED
|
||||||
|
|
||||||
|
#ifndef _STRLEN_DEFINED
|
||||||
|
#define _STRLEN_DEFINED
|
||||||
|
int strlen(char* s) {
|
||||||
|
int len = 0;
|
||||||
|
for(;s[len] != 0; ++len);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
#endif // !_STRLEN_DEFINED
|
||||||
|
|
||||||
|
#ifndef _START_DEFINED
|
||||||
|
#define _START_DEFINED
|
||||||
|
// Generic _start implementation. Can't access any args
|
||||||
|
extern void exit(int8_t status);
|
||||||
|
extern int main(int argc, char** argv);
|
||||||
|
void _start() {
|
||||||
|
exit(main(0, 0));
|
||||||
|
}
|
||||||
|
void __start() {
|
||||||
|
exit(main(0, 0));
|
||||||
|
}
|
||||||
|
#endif // !_START_DEFINED
|
||||||
323
arch/mips.c
323
arch/mips.c
@@ -1,5 +1,21 @@
|
|||||||
#if defined(__mips__)
|
#if defined(__mips__)
|
||||||
#include <stdint.h>
|
#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"
|
||||||
|
|
||||||
void exit(int8_t status){
|
void exit(int8_t status){
|
||||||
asm (
|
asm (
|
||||||
@@ -15,19 +31,34 @@ void exit(int8_t status){
|
|||||||
|
|
||||||
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;
|
intptr_t n_written = 0;
|
||||||
asm (
|
asm volatile (
|
||||||
"move $a0, %2\n"
|
"move $a0, %1\n"
|
||||||
"move $a1, %0\n"
|
"move $a1, %2\n"
|
||||||
"move $a2, %1\n"
|
"move $a2, %3\n"
|
||||||
"li $v0, 4004\n"
|
"li $v0, 4004\n"
|
||||||
"syscall\n"
|
"syscall\n"
|
||||||
: //TODO: n_written
|
"move %0, $v0\n"
|
||||||
: "r"(buf), "r"(size), "r"(fd)
|
: "=r"(n_written)
|
||||||
|
: "r"(fd), "r"(buf), "r"(size)
|
||||||
: "a0", "a1", "a2", "v0" //TODO: temp registers clobbered by syscall should probably also be listed but this fn returns right away so it should be fine?
|
: "a0", "a1", "a2", "v0" //TODO: temp registers clobbered by syscall should probably also be listed but this fn returns right away so it should be fine?
|
||||||
);
|
);
|
||||||
return n_written;
|
return n_written;
|
||||||
}
|
}
|
||||||
//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 (
|
||||||
|
"move $a0, %1\n"
|
||||||
|
"move $a1, %2\n"
|
||||||
|
"move $a2, %3\n"
|
||||||
|
"li $v0, 4003\n"
|
||||||
|
"syscall\n"
|
||||||
|
"move %0, $v0\n"
|
||||||
|
: "=r"(n_read)
|
||||||
|
: "r"(fd), "r"(buf), "r"(size)
|
||||||
|
: "a0", "a1", "a2", "v0", "memory" //TODO: temp registers clobbered by syscall should probably also be listed but this fn returns right away so it should be fine?
|
||||||
|
);
|
||||||
|
return n_read;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t fork(){
|
uint32_t fork(){
|
||||||
int rtn;
|
int rtn;
|
||||||
@@ -41,4 +72,280 @@ uint32_t fork(){
|
|||||||
);
|
);
|
||||||
return (uint32_t)rtn;
|
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 (
|
||||||
|
"move $a0, %1\n"
|
||||||
|
"move $a1, %2\n"
|
||||||
|
"move $a2, %3\n"
|
||||||
|
"move $a3, %4\n"
|
||||||
|
"li $v0, 4288\n"
|
||||||
|
"syscall\n"
|
||||||
|
"move %0, $v0\n"
|
||||||
|
: "=r"(file)
|
||||||
|
: "r"(fd), "r"(filename), "r"(flags), "r"(mode)
|
||||||
|
: "a0", "a1", "a2", "a3", "v0"
|
||||||
|
);
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
int close(unsigned int fd){
|
||||||
|
int rtn = 0;
|
||||||
|
asm (
|
||||||
|
"move $a0, %1\n"
|
||||||
|
"li $v0, 4006\n"
|
||||||
|
"syscall\n"
|
||||||
|
"move %0, $v0\n"
|
||||||
|
: "=r"(rtn)
|
||||||
|
: "r" (fd)
|
||||||
|
: "a0", "v0"
|
||||||
|
);
|
||||||
|
return rtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fsync(unsigned int fd){
|
||||||
|
int rtn = 0;
|
||||||
|
asm (
|
||||||
|
"move $a0, %1\n"
|
||||||
|
"li $v0, 4118\n"
|
||||||
|
"syscall\n"
|
||||||
|
"move %0, $v0\n"
|
||||||
|
: "=r"(rtn)
|
||||||
|
: "r" (fd)
|
||||||
|
: "a0", "v0"
|
||||||
|
);
|
||||||
|
return rtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
int socket(int domain, int type, int protocol){
|
||||||
|
int sockfd = 0;
|
||||||
|
asm volatile (
|
||||||
|
"move $a0, %1\n"
|
||||||
|
"move $a1, %2\n"
|
||||||
|
"move $a2, %3\n"
|
||||||
|
"li $v0, 4183\n"
|
||||||
|
"syscall\n"
|
||||||
|
"move %0, $v0\n"
|
||||||
|
: "=r"(sockfd)
|
||||||
|
: "r"(domain), "r"(type), "r"(protocol)
|
||||||
|
: "a0", "a1", "a2", "v0", "memory"
|
||||||
|
);
|
||||||
|
return sockfd;
|
||||||
|
}
|
||||||
|
|
||||||
|
int setsockopt(int sockfd, int level, int optname, const void* optval, socklen_t optlen){
|
||||||
|
int rtn = 0;
|
||||||
|
asm volatile (
|
||||||
|
"li $v0, 4181\n"
|
||||||
|
"move $a0, %1\n"
|
||||||
|
"move $a1, %2\n"
|
||||||
|
"move $a2, %3\n"
|
||||||
|
"move $a3, %4\n"
|
||||||
|
"addiu $sp, $sp, -32\n"
|
||||||
|
"sw %5, 16($sp)\n"
|
||||||
|
"syscall\n"
|
||||||
|
"addiu $sp, $sp, 32\n"
|
||||||
|
"move %0, $v0\n"
|
||||||
|
: "=r"(rtn)
|
||||||
|
: "r"(sockfd), "r"(level), "r"(optname), "r"(optval), "r"(optlen)
|
||||||
|
: "a0", "a1", "a2", "a3", "t0", "v0"
|
||||||
|
);
|
||||||
|
return rtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bind(int sockfd, const void* sockaddr, socklen_t addrlen) {
|
||||||
|
int rtn = 0;
|
||||||
|
asm volatile (
|
||||||
|
"move $a0, %1\n"
|
||||||
|
"move $a1, %2\n"
|
||||||
|
"move $a2, %3\n"
|
||||||
|
"li $v0, 4169\n"
|
||||||
|
"syscall\n"
|
||||||
|
"move %0, $v0\n"
|
||||||
|
: "=r"(rtn)
|
||||||
|
: "r"(sockfd), "r"(sockaddr), "r"(addrlen)
|
||||||
|
: "a0", "a1", "a2", "v0"
|
||||||
|
);
|
||||||
|
return rtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
int listen(int fd, int backlog) {
|
||||||
|
int rtn = 0;
|
||||||
|
asm volatile (
|
||||||
|
"move $a0, %1\n"
|
||||||
|
"move $a1, %2\n"
|
||||||
|
"li $v0, 4174\n"
|
||||||
|
"syscall\n"
|
||||||
|
"move %0, $v0\n"
|
||||||
|
: "=r"(rtn)
|
||||||
|
: "r"(fd), "r"(backlog)
|
||||||
|
: "a0", "a1", "v0"
|
||||||
|
);
|
||||||
|
return rtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
int accept(int sockfd, void* addr, socklen_t* addrlen) {
|
||||||
|
int connfd = 0;
|
||||||
|
asm volatile (
|
||||||
|
"move $a0, %1\n"
|
||||||
|
"move $a1, %2\n"
|
||||||
|
"move $a2, %3\n"
|
||||||
|
"li $v0, 4168\n"
|
||||||
|
"syscall\n"
|
||||||
|
"move %0, $v0\n"
|
||||||
|
: "=r"(connfd)
|
||||||
|
: "r"(sockfd), "r"(addr), "r"(addrlen)
|
||||||
|
: "a0", "a1", "a2", "v0", "memory"
|
||||||
|
);
|
||||||
|
return connfd;
|
||||||
|
}
|
||||||
|
|
||||||
|
int connect(int sockfd, void* addr, socklen_t addrlen) {
|
||||||
|
int connfd = 0;
|
||||||
|
asm volatile (
|
||||||
|
"move $a0, %1\n"
|
||||||
|
"move $a1, %2\n"
|
||||||
|
"move $a2, %3\n"
|
||||||
|
"li $v0, 4170\n"
|
||||||
|
"syscall\n"
|
||||||
|
"move %0, $v0\n"
|
||||||
|
: "=r"(connfd)
|
||||||
|
: "r"(sockfd), "r"(addr), "r"(addrlen)
|
||||||
|
: "a0", "a1", "a2", "v0"
|
||||||
|
);
|
||||||
|
return connfd;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t sendto(int sockfd, const void* buf, size_t size, int flags, const void* sockaddr, socklen_t addrlen){
|
||||||
|
ssize_t rtn = 0;
|
||||||
|
asm volatile (
|
||||||
|
"li $v0, 4180\n"
|
||||||
|
"move $a0, %1\n"
|
||||||
|
"move $a1, %2\n"
|
||||||
|
"move $a2, %3\n"
|
||||||
|
"move $a3, %4\n"
|
||||||
|
"addiu $sp, $sp, -32\n"
|
||||||
|
"sw %5, 16($sp)\n"
|
||||||
|
"sw %6, 20($sp)\n"
|
||||||
|
"syscall\n"
|
||||||
|
"addiu $sp, $sp, 32\n"
|
||||||
|
"move %0, $v0\n"
|
||||||
|
: "=r"(rtn)
|
||||||
|
: "r"(sockfd), "r"(buf), "r"(size), "r"(flags), "r"(sockaddr), "r"(addrlen)
|
||||||
|
: "a0", "a1", "a2", "a3", "t0", "t1", "v0"
|
||||||
|
);
|
||||||
|
return rtn;
|
||||||
|
}
|
||||||
|
ssize_t recvfrom(int sockfd, const void* buf, size_t size, int flags, const void* sockaddr, socklen_t addrlen){
|
||||||
|
ssize_t rtn = 0;
|
||||||
|
asm volatile (
|
||||||
|
"li $v0, 4176\n"
|
||||||
|
"move $a0, %1\n"
|
||||||
|
"move $a1, %2\n"
|
||||||
|
"move $a2, %3\n"
|
||||||
|
"move $a3, %4\n"
|
||||||
|
"addiu $sp, $sp, -32\n"
|
||||||
|
"sw %5, 16($sp)\n"
|
||||||
|
"sw %6, 20($sp)\n"
|
||||||
|
"syscall\n"
|
||||||
|
"addiu $sp, $sp, 32\n"
|
||||||
|
"move %0, $v0\n"
|
||||||
|
: "=r"(rtn)
|
||||||
|
: "r"(sockfd), "r"(buf), "r"(size), "r"(flags), "r"(sockaddr), "r"(addrlen)
|
||||||
|
: "a0", "a1", "a2", "a3", "t0", "t1", "v0", "memory"
|
||||||
|
);
|
||||||
|
return rtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
int clock_settime(clockid_t clockid, const struct timespec *tp){
|
||||||
|
int rtn = 0;
|
||||||
|
asm volatile (
|
||||||
|
"move $a0, %1\n"
|
||||||
|
"move $a1, %2\n"
|
||||||
|
"li $v0, 4262\n"
|
||||||
|
"syscall\n"
|
||||||
|
"move %0, $v0\n"
|
||||||
|
: "=r"(rtn)
|
||||||
|
: "r"(clockid), "r"(tp)
|
||||||
|
: "a0", "a1", "v0"
|
||||||
|
);
|
||||||
|
return rtn;
|
||||||
|
}
|
||||||
|
int clock_gettime(clockid_t clockid, struct timespec *tp){
|
||||||
|
int rtn = 0;
|
||||||
|
asm volatile (
|
||||||
|
"move $a0, %1\n"
|
||||||
|
"move $a1, %2\n"
|
||||||
|
"li $v0, 4263\n"
|
||||||
|
"syscall\n"
|
||||||
|
"move %0, $v0\n"
|
||||||
|
: "=r"(rtn)
|
||||||
|
: "r"(clockid), "r"(tp)
|
||||||
|
: "a0", "a1", "v0", "memory"
|
||||||
|
);
|
||||||
|
return rtn;
|
||||||
|
}
|
||||||
|
int clock_getres(clockid_t clockid, struct timespec *res){
|
||||||
|
int rtn = 0;
|
||||||
|
asm volatile (
|
||||||
|
"move $a0, %1\n"
|
||||||
|
"move $a1, %2\n"
|
||||||
|
"li $v0, 4264\n"
|
||||||
|
"syscall\n"
|
||||||
|
"move %0, $v0\n"
|
||||||
|
: "=r"(rtn)
|
||||||
|
: "r"(clockid), "r"(res)
|
||||||
|
: "a0", "a1", "v0", "memory"
|
||||||
|
);
|
||||||
|
return rtn;
|
||||||
|
}
|
||||||
|
int clock_nanosleep(clockid_t clockid, int flags, const struct timespec *t, struct timespec* remain){
|
||||||
|
int rtn = 0;
|
||||||
|
asm volatile (
|
||||||
|
"move $a0, %1\n"
|
||||||
|
"move $a1, %2\n"
|
||||||
|
"move $a2, %3\n"
|
||||||
|
"move $a3, %4\n"
|
||||||
|
"li $v0, 4265\n"
|
||||||
|
"syscall\n"
|
||||||
|
"move %0, $v0\n"
|
||||||
|
: "=r"(rtn)
|
||||||
|
: "r"(clockid), "r"(flags), "r"(t), "r"(remain)
|
||||||
|
: "a0", "a1", "a2", "a3", "v0", "memory"
|
||||||
|
);
|
||||||
|
return rtn;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
276
arch/x86_64.c
276
arch/x86_64.c
@@ -1,53 +1,267 @@
|
|||||||
#include <stdint.h>
|
|
||||||
#if defined(__x86_64__)
|
#if defined(__x86_64__)
|
||||||
|
#include "../int.h"
|
||||||
|
#include "../sys.h"
|
||||||
|
|
||||||
|
// Start code
|
||||||
|
#ifndef _START_DEFINED
|
||||||
|
#define _START_DEFINED
|
||||||
|
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;
|
||||||
|
exit(main(argc, argv));
|
||||||
|
}
|
||||||
|
#endif /* ifndef _START_DEFINED */
|
||||||
|
|
||||||
|
// include other generic functions
|
||||||
|
#include "generic.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// syscall functions
|
||||||
|
|
||||||
#define SYS_EXIT 60
|
#define SYS_EXIT 60
|
||||||
void exit(int8_t status) {
|
void exit(int8_t status) {
|
||||||
asm volatile(
|
asm volatile("syscall" : : "a"(SYS_EXIT), "D"(status) :);
|
||||||
"syscall"
|
for (;;)
|
||||||
:
|
;
|
||||||
: "a"(SYS_EXIT), "D"(status)
|
|
||||||
:
|
|
||||||
);
|
|
||||||
for(;;);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SYS_WRITE 1
|
#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;
|
intptr_t n_written = 0;
|
||||||
asm volatile (
|
asm volatile("syscall\n"
|
||||||
"syscall\n"
|
"movq %0, %%rax\n"
|
||||||
"movq %0, %%rax\n"
|
: "=r"(n_written)
|
||||||
: "=r"(n_written)
|
: "a"(SYS_WRITE), "D"(fd), "S"(buf),
|
||||||
: "a"(SYS_WRITE), "D"(fd), "S"(buf), "d"(size) // RDI, RSI, RDX are used in x86-64 for write args
|
"d"(size) // RDI, RSI, RDX are used in x86-64 for write args
|
||||||
: "rcx", "r11", "memory"
|
: "rcx", "r11");
|
||||||
);
|
|
||||||
return n_written;
|
return n_written;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SYS_READ 0
|
#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;
|
intptr_t n_read = 0;
|
||||||
asm volatile (
|
asm volatile("syscall\n"
|
||||||
"syscall\n"
|
"movq %0, %%rax\n"
|
||||||
"movq %0, %%rax\n"
|
: "=r"(n_read)
|
||||||
: "=r"(n_read)
|
: "a"(SYS_READ), "D"(fd), "S"(buf),
|
||||||
: "a"(SYS_READ), "D"(fd), "S"(buf), "d"(size) // RDI, RSI, RDX are used in x86-64 for write args
|
"d"(size) // RDI, RSI, RDX are used in x86-64 for write args
|
||||||
: "rcx", "r11", "memory"
|
: "rcx", "r11", "memory");
|
||||||
);
|
|
||||||
return n_read;
|
return n_read;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SYS_FORK 57
|
#define SYS_FORK 57
|
||||||
uint32_t fork() {
|
uint32_t fork() {
|
||||||
uint64_t rtn;
|
uint64_t rtn;
|
||||||
asm volatile(
|
asm volatile("syscall\n" // syscall
|
||||||
"syscall\n" // syscall
|
"movq %0, %%rax\n" // save return value
|
||||||
"movq %0, %%rax\n" // save return value
|
: "=r"(rtn)
|
||||||
: "=r"(rtn)
|
: "a"(SYS_FORK)
|
||||||
: "a"(SYS_FORK)
|
:);
|
||||||
:
|
|
||||||
);
|
|
||||||
return (uint32_t)rtn;
|
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 file;
|
||||||
|
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");
|
||||||
|
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");
|
||||||
|
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");
|
||||||
|
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");
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SYS_SETSOCKOPT 54
|
||||||
|
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");
|
||||||
|
return rtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SYS_BIND 49
|
||||||
|
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");
|
||||||
|
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");
|
||||||
|
return rtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SYS_ACCEPT 43
|
||||||
|
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");
|
||||||
|
return rtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SYS_CONNECT 42
|
||||||
|
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");
|
||||||
|
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 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");
|
||||||
|
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 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");
|
||||||
|
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");
|
||||||
|
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");
|
||||||
|
return rtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SYS_CLOCK_GETRES 229
|
||||||
|
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");
|
||||||
|
return rtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SYS_CLOCK_NANOSLEEP 230
|
||||||
|
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");
|
||||||
|
return rtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SYS_RT_SIGACTION 13
|
||||||
|
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");
|
||||||
|
return rtn;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* ifdef __x86_64__ */
|
#endif /* ifdef __x86_64__ */
|
||||||
|
|||||||
104
buildtest.c
104
buildtest.c
@@ -1,44 +1,90 @@
|
|||||||
#include <stdint.h>
|
#include "int.h"
|
||||||
#include "sys.h"
|
#include "sys.h"
|
||||||
|
|
||||||
|
#define print(str) write(STDOUT, str, (sizeof str) - 1)
|
||||||
int main() {
|
void printhex(uint64_t num) {
|
||||||
uint64_t pid = fork();
|
|
||||||
|
|
||||||
// Print the pid in hex
|
|
||||||
char msg[17] = {' '};
|
char msg[17] = {' '};
|
||||||
msg[16] = '\n';
|
msg[16] = '\n';
|
||||||
for(int i = 0; i < 16; ++i) {
|
for (int i = 0; i < 16; ++i) {
|
||||||
char nibble = (pid >> ((15 - i) * 4)) & 0xf;
|
char nibble = (num >> ((15 - i) * 4)) & 0xf;
|
||||||
char c;
|
char c;
|
||||||
if (nibble > 9) {c = nibble + '7';}
|
if (nibble > 9) {
|
||||||
else {c = nibble + '0';}
|
c = nibble + '7';
|
||||||
|
} else {
|
||||||
|
c = nibble + '0';
|
||||||
|
}
|
||||||
msg[i] = c;
|
msg[i] = c;
|
||||||
}
|
}
|
||||||
write(STDIO, msg, 17);
|
write(STDOUT, msg, 17);
|
||||||
|
}
|
||||||
|
|
||||||
// Child process exits
|
int main(int argc, char* argv[]) {
|
||||||
if(pid == 0) return 0;
|
// Test the write syscall
|
||||||
//TODO: wait on child to remove zombie process
|
intptr_t n = write(STDOUT, "Hello\n", 6);
|
||||||
|
if(n != 6) return n;
|
||||||
|
|
||||||
|
// Test argc
|
||||||
|
for(int i = 0; i < argc; ++i){
|
||||||
|
int len = strlen(argv[i]);
|
||||||
|
write(STDOUT, argv[i], len);
|
||||||
|
write(STDOUT, "\n", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test the fork syscall
|
||||||
|
uint64_t pid = fork();
|
||||||
|
// Print the pid in hex
|
||||||
|
printhex(pid);
|
||||||
|
// 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);
|
||||||
|
|
||||||
#if defined(__x86_64__)
|
|
||||||
// Test the read syscall
|
// Test the read syscall
|
||||||
#define INPUT_BUFFER_LEN 4096
|
#define INPUT_BUFFER_LEN 4096
|
||||||
char input_buffer[INPUT_BUFFER_LEN] = {0};
|
char input_buffer[INPUT_BUFFER_LEN] = {0};
|
||||||
write(STDIO, "Enter some text:", 16);
|
int32_t fout = openc("outfile", O_RDWR | O_CREAT | O_TRUNC, 0664);
|
||||||
intptr_t n_read = read(STDIO, input_buffer, INPUT_BUFFER_LEN);
|
|
||||||
write(STDIO, input_buffer, n_read);
|
print("Enter some text:");
|
||||||
#endif
|
intptr_t n_read = read(STDIN, input_buffer, INPUT_BUFFER_LEN);
|
||||||
|
write(STDOUT, input_buffer, n_read);
|
||||||
|
if(fout > 0) {
|
||||||
|
write(fout, input_buffer, n_read);
|
||||||
|
fsync(fout);
|
||||||
|
close(fout);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test the open syscall
|
||||||
|
int32_t file = open("/proc/version", O_RDONLY);
|
||||||
|
if (file > 0) {
|
||||||
|
int i = read(file, input_buffer, INPUT_BUFFER_LEN);
|
||||||
|
while(i > 0) {
|
||||||
|
write(STDOUT, input_buffer, i);
|
||||||
|
i = read(file, input_buffer, INPUT_BUFFER_LEN);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
print("Could not open /proc/version\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test sleep
|
||||||
|
print("Sleeping for 5 secs\n");
|
||||||
|
struct timespec sleeptime;
|
||||||
|
sleeptime.tv_sec = 5;
|
||||||
|
while (nanosleep(&sleeptime, &sleeptime) != 0) {}
|
||||||
|
print("DONE\n");
|
||||||
|
|
||||||
return 69;
|
return 69;
|
||||||
}
|
}
|
||||||
|
|
||||||
void __libc_start_main() {exit(main());}
|
|
||||||
|
|
||||||
void _start() {
|
|
||||||
__libc_start_main();
|
|
||||||
}
|
|
||||||
|
|
||||||
void __start() {
|
|
||||||
_start();
|
|
||||||
}
|
|
||||||
|
|||||||
74
int.h
Normal file
74
int.h
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
#ifndef MINIMALINT_H
|
||||||
|
#define MINIMALINT_H
|
||||||
|
|
||||||
|
#if defined(__x86_64__) || defined(__aarch64__)
|
||||||
|
#define __WORDSIZE 64
|
||||||
|
#elif defined(__mips__)
|
||||||
|
#define __WORDSIZE 32
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef unsigned char uint8_t;
|
||||||
|
typedef unsigned short uint16_t;
|
||||||
|
typedef unsigned int uint32_t;
|
||||||
|
typedef unsigned long long uint64_t;
|
||||||
|
|
||||||
|
typedef char int8_t;
|
||||||
|
typedef short int16_t;
|
||||||
|
typedef int int32_t;
|
||||||
|
typedef long long int64_t;
|
||||||
|
|
||||||
|
#if __WORDSIZE == 64
|
||||||
|
typedef int64_t intptr_t;
|
||||||
|
typedef uint64_t uintptr_t;
|
||||||
|
#elif __WORDSIZE == 32
|
||||||
|
typedef int32_t intptr_t;
|
||||||
|
typedef uint32_t uintptr_t;
|
||||||
|
#else
|
||||||
|
#error Unsupported or unknown wordsize
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef intptr_t ssize_t;
|
||||||
|
typedef uintptr_t size_t;
|
||||||
|
|
||||||
|
typedef uint32_t socklen_t;
|
||||||
|
typedef uint32_t pid_t;
|
||||||
|
|
||||||
|
typedef long time_t;
|
||||||
|
typedef int clockid_t;
|
||||||
|
struct timespec {
|
||||||
|
time_t tv_sec; /* seconds */
|
||||||
|
long tv_nsec; /* nanoseconds */
|
||||||
|
};
|
||||||
|
|
||||||
|
// Compile time tests in supported compilers
|
||||||
|
#ifdef __SIZEOF_SHORT__
|
||||||
|
#if __SIZEOF_SHORT__ != 2
|
||||||
|
#error __SIZEOF_SHORT__ is not 2
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __SIZEOF_INT__
|
||||||
|
#if __SIZEOF_INT__ != 4
|
||||||
|
#error __SIZEOF_INT__ is not 4
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __SIZEOF_LONG_LONG__
|
||||||
|
#if __SIZEOF_LONG_LONG__ != 8
|
||||||
|
#error __SIZEOF_LONG_LONG__ is not 8
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __SIZEOF_POINTER__
|
||||||
|
#if __SIZEOF_POINTER__ != (__WORDSIZE / 8)
|
||||||
|
#error __SIZEOF_POINTER__ is not (__WORDSIZE / 8)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __SIZEOF_SIZE_T__
|
||||||
|
#if __SIZEOF_SIZE_T__ != (__WORDSIZE / 8)
|
||||||
|
#error __SIZEOF_SIZE_T__ is not (__WORDSIZE / 8)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // !MINIMALINT_H
|
||||||
53
net/ipv4.h
Normal file
53
net/ipv4.h
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
#ifndef MINIMAL_IPV4_H
|
||||||
|
#define MINIMAL_IPV4_H
|
||||||
|
// From kernel header in.h
|
||||||
|
// location: uapi/linux/in.h or linux/in.h (older kerns) or /usr/include/netinet/in.h (installed path)
|
||||||
|
|
||||||
|
#include "../sys.h"
|
||||||
|
#include "../int.h"
|
||||||
|
|
||||||
|
struct in_addr {
|
||||||
|
uint32_t s_addr;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define __SOCK_SIZE__ 16 /* sizeof(struct sockaddr) */
|
||||||
|
struct sockaddr_in {
|
||||||
|
unsigned short sin_family; // address family: AF_INET
|
||||||
|
uint16_t sin_port; // port in network byte order
|
||||||
|
struct in_addr sin_addr; // internet address
|
||||||
|
// Padding to match the size of struct sockaddr
|
||||||
|
unsigned char sin_zero[8];
|
||||||
|
};
|
||||||
|
/* Address to accept any incoming messages. */
|
||||||
|
#define INADDR_ANY ((unsigned long int) 0x00000000)
|
||||||
|
|
||||||
|
/* Standard well-defined IP protocols. */
|
||||||
|
enum {
|
||||||
|
IPPROTO_IP = 0, /* Dummy protocol for TCP */
|
||||||
|
IPPROTO_ICMP = 1, /* Internet Control Message Protocol */
|
||||||
|
IPPROTO_IGMP = 2, /* Internet Group Management Protocol */
|
||||||
|
IPPROTO_IPIP = 4, /* IPIP tunnels (older KA9Q tunnels use 94) */
|
||||||
|
IPPROTO_TCP = 6, /* Transmission Control Protocol */
|
||||||
|
IPPROTO_EGP = 8, /* Exterior Gateway Protocol */
|
||||||
|
IPPROTO_PUP = 12, /* PUP protocol */
|
||||||
|
IPPROTO_UDP = 17, /* User Datagram Protocol */
|
||||||
|
IPPROTO_IDP = 22, /* XNS IDP protocol */
|
||||||
|
IPPROTO_DCCP = 33, /* Datagram Congestion Control Protocol */
|
||||||
|
IPPROTO_RSVP = 46, /* RSVP protocol */
|
||||||
|
IPPROTO_GRE = 47, /* Cisco GRE tunnels (rfc 1701,1702) */
|
||||||
|
|
||||||
|
IPPROTO_IPV6 = 41, /* IPv6-in-IPv4 tunnelling */
|
||||||
|
|
||||||
|
IPPROTO_ESP = 50, /* Encapsulation Security Payload protocol */
|
||||||
|
IPPROTO_AH = 51, /* Authentication Header protocol */
|
||||||
|
IPPROTO_BEETPH = 94, /* IP option pseudo header for BEET */
|
||||||
|
IPPROTO_PIM = 103, /* Protocol Independent Multicast */
|
||||||
|
|
||||||
|
IPPROTO_COMP = 108, /* Compression Header protocol */
|
||||||
|
IPPROTO_SCTP = 132, /* Stream Control Transport Protocol */
|
||||||
|
|
||||||
|
IPPROTO_RAW = 255, /* Raw IP packets */
|
||||||
|
IPPROTO_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MINIMAL_IPV4_H
|
||||||
91
socktest.c
Normal file
91
socktest.c
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
#include "sys.h"
|
||||||
|
#include "int.h"
|
||||||
|
#include "net/ipv4.h"
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
char recvBuff[4096];
|
||||||
|
int socket_fd, connection_fd;
|
||||||
|
struct sockaddr_in server, client;
|
||||||
|
server.sin_family = AF_INET;
|
||||||
|
server.sin_addr.s_addr = INADDR_ANY;
|
||||||
|
|
||||||
|
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||||
|
server.sin_port = 6969;
|
||||||
|
#else
|
||||||
|
server.sin_port = 0x391b;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Create the socket
|
||||||
|
socket_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
|
||||||
|
if (socket_fd < 0) {
|
||||||
|
write(STDERR, "Socket error\n", 13);
|
||||||
|
close(socket_fd);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set socket options
|
||||||
|
int opt = 1;
|
||||||
|
if(0 > setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) {
|
||||||
|
write(STDERR, "Socket error\n", 13);
|
||||||
|
close(socket_fd);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bind the socket
|
||||||
|
if( bind(socket_fd, (struct sockaddr *)&server, sizeof(server)) < 0) {
|
||||||
|
write(STDERR, "Socket error\n", 13);
|
||||||
|
close(socket_fd);
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Listen for incoming connections
|
||||||
|
if (listen(socket_fd, 3) < 0) {
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
write(STDOUT, "Waiting for incoming connections...\n", 36);
|
||||||
|
|
||||||
|
// Get the new connection
|
||||||
|
socklen_t c = sizeof(struct sockaddr_in);
|
||||||
|
connection_fd = accept(socket_fd, (void *)&client, &c);
|
||||||
|
write(STDOUT, "Got new connection\n", 19);
|
||||||
|
if(connection_fd < 0) {
|
||||||
|
write(STDERR, "Connection error\n", 17);
|
||||||
|
close(connection_fd);
|
||||||
|
close(socket_fd);
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//char *client_ip = inet_ntoa(client.sin_addr);
|
||||||
|
//int client_port = ntohs(client.sin_port);
|
||||||
|
//printf("Connection accepted from %s:%d\n", client_ip, client_port);
|
||||||
|
|
||||||
|
// Send stuff
|
||||||
|
write(STDOUT, "Connection Established!\n", 24);
|
||||||
|
if( send(connection_fd, "Connection Established!\n", 24, 0) < 0) {
|
||||||
|
write(STDERR, "Connection error\n", 17);
|
||||||
|
close(connection_fd);
|
||||||
|
close(socket_fd);
|
||||||
|
return 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recieve stuff
|
||||||
|
write(STDOUT, "Recieving data...\n", 18);
|
||||||
|
for(;;) {
|
||||||
|
ssize_t incoming = recv(connection_fd, recvBuff, 4096, 0);
|
||||||
|
if( incoming < 0) {
|
||||||
|
write(STDERR, "Connection error\n", 17);
|
||||||
|
close(connection_fd);
|
||||||
|
close(socket_fd);
|
||||||
|
return 7;
|
||||||
|
}if(incoming == 0) break;
|
||||||
|
|
||||||
|
// Print the recieved data
|
||||||
|
write(STDOUT, recvBuff, incoming);
|
||||||
|
}
|
||||||
|
|
||||||
|
write(STDOUT, "Closing connection\n", 19);
|
||||||
|
close(connection_fd);
|
||||||
|
close(socket_fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
133
stackdump.c
Normal file
133
stackdump.c
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
#include "sys.h"
|
||||||
|
#include "int.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
Line format: "AAAAAAAAAAAAAAAA BBBB BBBB BBBB BBBB CCCCCCCC\n"
|
||||||
|
16: hex ptr
|
||||||
|
2: space
|
||||||
|
4: 2 hex bytes data
|
||||||
|
1: space
|
||||||
|
4: 2 hex bytes data
|
||||||
|
1: space
|
||||||
|
4: 2 hex bytes data
|
||||||
|
1: space
|
||||||
|
4: 2 hex bytes data
|
||||||
|
2: space
|
||||||
|
8: 8 char bytes data
|
||||||
|
1: new line
|
||||||
|
---
|
||||||
|
48: total bytes
|
||||||
|
|
||||||
|
# s0: original sp
|
||||||
|
# s1: buffer start pointer
|
||||||
|
# s2: line counter
|
||||||
|
# s3: current data being printed (both addr and *addr)
|
||||||
|
# s4: nibble/byte offset
|
||||||
|
# s5: current nibble (both binary and ascii hex)
|
||||||
|
# s6: current buffer position pointer
|
||||||
|
*/
|
||||||
|
#if defined(__x86_64__) || defined(__aarch64__)
|
||||||
|
#define WRD_LEN 64
|
||||||
|
typedef uint64_t word_t;
|
||||||
|
#define SIZEOF_WORD_T 8
|
||||||
|
#define LEN 48
|
||||||
|
#elif defined(__mips__)
|
||||||
|
#define WRD_LEN 32
|
||||||
|
typedef uint32_t word_t;
|
||||||
|
#define SIZEOF_WORD_T 4
|
||||||
|
#define LEN 26
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define NIBBLE_LEN 4
|
||||||
|
#define CHAR_LEN 8
|
||||||
|
//uint64_t* sp; // Original sp
|
||||||
|
char* sp; // Original sp
|
||||||
|
char* fp; // frame pointer
|
||||||
|
char buff[LEN]; // buffer pointer
|
||||||
|
int line; // line counter
|
||||||
|
word_t data; // Current data
|
||||||
|
int offset; // nibble/char offset
|
||||||
|
int nibble; // current nibble/char
|
||||||
|
char* pos; // buffer position
|
||||||
|
|
||||||
|
// Compile with -D _START_DEFINED
|
||||||
|
#if defined(__mips__)
|
||||||
|
void __start() {
|
||||||
|
#else
|
||||||
|
void _start() {
|
||||||
|
#endif /* ifndef defined(__mips__) */
|
||||||
|
// Save stack pointer
|
||||||
|
#if defined(__x86_64__)
|
||||||
|
asm volatile("mov %%rsp, %0\n" : "=r"(sp));
|
||||||
|
#elif defined(__mips__)
|
||||||
|
asm volatile("move %0, $sp\n" : "=r"(sp));
|
||||||
|
#elif defined(__aarch64__)
|
||||||
|
asm volatile("mov %0, sp\n" : "=r"(sp));
|
||||||
|
#else
|
||||||
|
#error arch not supported
|
||||||
|
#endif
|
||||||
|
fp = __builtin_frame_address(0);
|
||||||
|
//fp = __builtin_return_address(0);
|
||||||
|
|
||||||
|
//if(fp != sp) exit(sp - fp);
|
||||||
|
// Clear buffer with spaces and newline
|
||||||
|
for(pos=buff; pos < buff+LEN-1; ++pos) *pos = ' ';
|
||||||
|
buff[LEN-1] = '\n';
|
||||||
|
|
||||||
|
// Add some vars to see how ith changes the stack
|
||||||
|
// volatile word_t padd = 0x11;
|
||||||
|
// volatile word_t padd2 = 0x12;
|
||||||
|
|
||||||
|
// Loop until segfault
|
||||||
|
for(line = 0;;line += 1) {
|
||||||
|
// Load address of next word into data
|
||||||
|
data = (word_t)((line*SIZEOF_WORD_T) + sp);
|
||||||
|
if(fp == (char*)data) write(STDOUT, "FP\n", 3);
|
||||||
|
// reset buffer position
|
||||||
|
pos = buff;
|
||||||
|
|
||||||
|
// print addr in hex //
|
||||||
|
for(offset=WRD_LEN-NIBBLE_LEN; offset >= 0; offset -= NIBBLE_LEN) {
|
||||||
|
nibble = (data >> offset) & 0x0f; // store current nibble in nibble
|
||||||
|
// convert nibble to hex
|
||||||
|
nibble = nibble + '0';
|
||||||
|
if(nibble > '9') nibble = nibble + 7;
|
||||||
|
// write hex char to buffer
|
||||||
|
*pos = nibble;
|
||||||
|
pos += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print data as hex //
|
||||||
|
pos += 2; // Add 2 padded spaces
|
||||||
|
data = *(word_t*)data; // Load data into data
|
||||||
|
for(offset=WRD_LEN-NIBBLE_LEN; offset>=0; offset -= NIBBLE_LEN) {
|
||||||
|
nibble = (data >> offset) & 0x0f; // Store current nibble in nibble
|
||||||
|
// Convert nibble to hex char
|
||||||
|
nibble = nibble + '0';
|
||||||
|
if(nibble > '9') nibble = nibble + 7;
|
||||||
|
// Write hex char to buffer
|
||||||
|
*pos = nibble;
|
||||||
|
pos += 1;
|
||||||
|
// Add space every 2 bytes (4 nibbles)
|
||||||
|
if((offset % 16) == 0) pos += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos += 1;
|
||||||
|
|
||||||
|
// Print data as char //
|
||||||
|
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||||
|
for(offset = WRD_LEN - CHAR_LEN; offset >= 0; offset -= CHAR_LEN) {
|
||||||
|
#else
|
||||||
|
for(offset = 0; offset < WRD_LEN; offset += CHAR_LEN) {
|
||||||
|
#endif /* ifndef defined(__mips__) */
|
||||||
|
nibble = (data >> offset) & 0xff; // Store current char in nibble
|
||||||
|
if((nibble < ' ') || (nibble > '~')) *pos = '~'; // Use placeholder for non printable chars
|
||||||
|
else *pos = nibble; // Write printable char
|
||||||
|
pos += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write to STDOUT //
|
||||||
|
write(STDOUT, buff, LEN);
|
||||||
|
fsync(STDOUT);
|
||||||
|
}
|
||||||
|
}
|
||||||
147
sys.h
147
sys.h
@@ -1,21 +1,150 @@
|
|||||||
#ifndef MINIMALSYS_H
|
#ifndef MINIMALSYS_H
|
||||||
#include <stdint.h>
|
#define MINIMALSYS_H
|
||||||
|
|
||||||
|
#include "int.h"
|
||||||
|
|
||||||
void exit(int8_t status);
|
void exit(int8_t status);
|
||||||
|
|
||||||
#define STDIO 1
|
#define STDIN 0
|
||||||
|
#define STDOUT 1
|
||||||
#define STDERR 2
|
#define STDERR 2
|
||||||
intptr_t write(int32_t fd, const void* buf, intptr_t size);
|
intptr_t write(int32_t fd, const void* buf, intptr_t size);
|
||||||
#if defined(__x86_64__)
|
|
||||||
intptr_t read(int32_t fd, const void* buf, intptr_t size);
|
intptr_t read(int32_t fd, const void* buf, intptr_t size);
|
||||||
|
|
||||||
|
#define O_RDONLY 00
|
||||||
|
#define O_WRONLY 01
|
||||||
|
#define O_RDWR 02
|
||||||
|
#define AT_FDCWD -100
|
||||||
|
|
||||||
|
#if defined(__mips__)
|
||||||
|
// linux/arch/mips/include/uapi/asm/fcntl.h
|
||||||
|
#define O_APPEND 0x0008
|
||||||
|
#define O_CREAT 0x0100 /* not fcntl */
|
||||||
|
#define O_TRUNC 0x0200 /* not fcntl */
|
||||||
|
#define O_EXCL 0x0400 /* not fcntl */
|
||||||
|
#define O_NOCTTY 0x0800 /* not fcntl */
|
||||||
|
#else
|
||||||
|
// linux/include/uapi/asm-generic/fcntl.h
|
||||||
|
#define O_CREAT 1<<6
|
||||||
|
#define O_EXCL 1<<7
|
||||||
|
#define O_NOCTTY 1<<8
|
||||||
|
#define O_TRUNC 1<<9
|
||||||
|
#define O_APPEND 1<<10
|
||||||
#endif
|
#endif
|
||||||
|
int32_t openat(int32_t fd, const char* filename, uint32_t flags, uint32_t mode);
|
||||||
|
#define open(...) openat(AT_FDCWD, __VA_ARGS__, 0)
|
||||||
|
#define openc(...) openat(AT_FDCWD, __VA_ARGS__)
|
||||||
|
int close(unsigned int fd);
|
||||||
|
int fsync(unsigned int fd);
|
||||||
|
|
||||||
|
// Socket syscalls
|
||||||
|
int socket(int domain, int type, int protocol);
|
||||||
|
int setsockopt(int sockfd, int level, int optname, const void* optval, socklen_t optlen);
|
||||||
|
int bind(int sockfd, const void* sockaddr, socklen_t addrlen);
|
||||||
|
int listen(int fd, int backlog);
|
||||||
|
int accept(int sockfd, void* addr, socklen_t* addrlen);
|
||||||
|
int connect(int sockfd, void* addr, socklen_t addrlen);
|
||||||
|
ssize_t sendto(int sockfd, const void* buf, size_t size, int flags, const void* sockaddr, socklen_t addrlen);
|
||||||
|
#define send(sockfd, buf, size, flags) sendto(sockfd, buf, size, flags, 0, 0)
|
||||||
|
ssize_t recvfrom(int sockfd, const void* buf, size_t size, int flags, const void* sockaddr, socklen_t addrlen);
|
||||||
|
#define recv(sockfd, buf, size, flags) recvfrom(sockfd, buf, size, flags, 0, 0)
|
||||||
|
// Socket Domain constants
|
||||||
|
typedef unsigned short sa_family_t;
|
||||||
|
/* Supported address families. */
|
||||||
|
#define AF_UNIX 1 /* Unix domain sockets */
|
||||||
|
#define AF_LOCAL 1 /* POSIX name for AF_UNIX */
|
||||||
|
#define AF_INET 2 /* Internet IP Protocol */
|
||||||
|
#define AF_AX25 3 /* Amateur Radio AX.25 */
|
||||||
|
#define AF_INET6 10 /* IP version 6 */
|
||||||
|
#define AF_ROSE 11 /* Amateur Radio X.25 PLP */
|
||||||
|
#define AF_PACKET 17 /* Packet family */
|
||||||
|
#define AF_CAN 29 /* Controller Area Network */
|
||||||
|
#define AF_BLUETOOTH 31 /* Bluetooth sockets */
|
||||||
|
// Socket type constants
|
||||||
|
|
||||||
|
#if defined(__mips__)
|
||||||
|
// File: include/asm-mips/socket.h
|
||||||
|
enum sock_type {
|
||||||
|
SOCK_DGRAM = 1,
|
||||||
|
SOCK_STREAM = 2,
|
||||||
|
SOCK_RAW = 3,
|
||||||
|
SOCK_RDM = 4,
|
||||||
|
SOCK_SEQPACKET = 5,
|
||||||
|
SOCK_DCCP = 6,
|
||||||
|
SOCK_PACKET = 10,
|
||||||
|
};
|
||||||
|
#define SOL_SOCKET 0xffff
|
||||||
|
|
||||||
|
#define SO_DEBUG 0x0001 /* Record debugging information. */
|
||||||
|
#define SO_REUSEADDR 0x0004 /* Allow reuse of local addresses. */
|
||||||
|
#define SO_TYPE 0x1008 /* Compatible name for SO_STYLE. */
|
||||||
|
#define SO_ERROR 0x1007 /* get error status and clear */
|
||||||
|
#define SO_DONTROUTE 0x0010 /* Don't do local routing. */
|
||||||
|
#define SO_BROADCAST 0x0020 /* Allow transmission of broadcast messages. */
|
||||||
|
#define SO_SNDBUF 0x1001 /* Send buffer size. */
|
||||||
|
#define SO_RCVBUF 0x1002 /* Receive buffer. */
|
||||||
|
#define SO_KEEPALIVE 0x0008 /* Keep connections alive and send SIGPIPE when they die. */
|
||||||
|
#define SO_OOBINLINE 0x0100 /* Receive out-of-band data in-band. */
|
||||||
|
#define SO_LINGER 0x0080 /* Block on close of a reliable socket to transmit pending data. */
|
||||||
|
#define SO_REUSEPORT 0x0200 /* Allow local address and port reuse. */
|
||||||
|
#define SO_RCVLOWAT 0x1004 /* receive low-water mark */
|
||||||
|
#define SO_SNDLOWAT 0x1003 /* send low-water mark */
|
||||||
|
#define SO_RCVTIMEO 0x1006 /* receive timeout */
|
||||||
|
#define SO_SNDTIMEO 0x1005 /* send timeout */
|
||||||
|
#else
|
||||||
|
enum sock_type {
|
||||||
|
SOCK_STREAM = 1,
|
||||||
|
SOCK_DGRAM = 2,
|
||||||
|
SOCK_RAW = 3,
|
||||||
|
SOCK_RDM = 4,
|
||||||
|
SOCK_SEQPACKET = 5,
|
||||||
|
SOCK_DCCP = 6,
|
||||||
|
SOCK_PACKET = 10,
|
||||||
|
};
|
||||||
|
#define SOL_SOCKET 1
|
||||||
|
|
||||||
|
#define SO_DEBUG 1
|
||||||
|
#define SO_REUSEADDR 2
|
||||||
|
#define SO_TYPE 3
|
||||||
|
#define SO_ERROR 4
|
||||||
|
#define SO_DONTROUTE 5
|
||||||
|
#define SO_BROADCAST 6
|
||||||
|
#define SO_SNDBUF 7
|
||||||
|
#define SO_RCVBUF 8
|
||||||
|
#define SO_KEEPALIVE 9
|
||||||
|
#define SO_OOBINLINE 10
|
||||||
|
#define SO_LINGER 13
|
||||||
|
#define SO_REUSEPORT 15
|
||||||
|
#define SO_RCVLOWAT 18
|
||||||
|
#define SO_SNDLOWAT 19
|
||||||
|
#define SO_RCVTIMEO 20
|
||||||
|
#define SO_SNDTIMEO 21
|
||||||
|
#endif
|
||||||
|
#define SO_STYLE SO_TYPE /* Synonym */
|
||||||
|
/* linux-specific, might as well be the same as on i386 */
|
||||||
|
#define SO_NO_CHECK 11
|
||||||
|
#define SO_PRIORITY 12
|
||||||
|
#define SO_BSDCOMPAT 14
|
||||||
|
#define SO_PASSCRED 17
|
||||||
|
#define SO_PEERCRED 18
|
||||||
|
|
||||||
|
// Time management
|
||||||
|
#define CLOCK_REALTIME 0
|
||||||
|
#define CLOCK_MONOTONIC 1
|
||||||
|
#define CLOCK_PROCESS_CPUTIME_ID 2
|
||||||
|
#define CLOCK_THREAD_CPUTIME_ID 3
|
||||||
|
#define TIMER_ABSTIME 0x01
|
||||||
|
int clock_settime(clockid_t clockid, const struct timespec *tp);
|
||||||
|
int clock_gettime(clockid_t clockid, struct timespec *tp);
|
||||||
|
int clock_getres(clockid_t clockid, struct timespec *res);
|
||||||
|
int clock_nanosleep(clockid_t clockid, int flags, const struct timespec *t, struct timespec* remain);
|
||||||
|
#define nanosleep(t, remain) clock_nanosleep(CLOCK_MONOTONIC, 0, t, remain)
|
||||||
|
|
||||||
uint32_t fork();
|
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);
|
||||||
|
|
||||||
// Provide memset for clang
|
|
||||||
void *memset(void* s, int c, unsigned long n) {
|
|
||||||
int8_t* mem = s;
|
|
||||||
for(long int i = 0; i < n; ++i) mem[i] = c;
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
#endif // !MINIMALSYS_H
|
#endif // !MINIMALSYS_H
|
||||||
|
|||||||
Reference in New Issue
Block a user