Compare commits

..
3 Commits
Author SHA1 Message Date
veclavtlica 3db75378c4 generalization of syscalls 2026-10-07 17:16:18 +03:00
veclavtlica e7abe1a1d2 fix auth read 2026-10-07 12:05:28 +03:00
veclavtlica 1e200cc7f2 more generic tiny.ld 2026-10-07 11:26:22 +03:00
11 changed files with 249 additions and 64 deletions
+50
View File
@@ -1,8 +1,11 @@
#include "../std.h" #include "../std.h"
#include "../str.h"
#include <assert.h> #include <assert.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <tgmath.h> #include <tgmath.h>
void *com_std_alloc(void *ptr, size_t size) { void *com_std_alloc(void *ptr, size_t size) {
@@ -19,3 +22,50 @@ double com_std_sqrt(double v) { return sqrt(v); }
double com_std_fabs(double v) { return fabs(v); } double com_std_fabs(double v) { return fabs(v); }
double com_std_sin(double v) { return sin(v); } double com_std_sin(double v) { return sin(v); }
double com_std_cos(double v) { return cos(v); } double com_std_cos(double v) { return cos(v); }
com_std_fd com_std_open(char *path, uint32_t flags) {
com_std_assert(flags != 0);
char *mode = flags & COM_STD_OPEN_READ && flags & COM_STD_OPEN_WRITE ? "r+"
: flags & COM_STD_OPEN_READ ? "r"
: "w";
return fopen(path, mode);
}
bool com_std_write(com_std_fd fd, char *data, uint32_t bytes) {
com_std_assert(fd != NULL && data != NULL && bytes != 0);
bool s = fwrite(data, 1, bytes, fd) == bytes;
fflush(fd);
return s;
}
int32_t com_std_read(com_std_fd fd, char *data, uint32_t upto) {
com_std_assert(fd != NULL && data != NULL && upto != 0);
return fread(data, 1, upto, fd);
}
bool com_std_sfwd(com_std_fd fd, uint32_t bytes) {
com_std_assert(fd != NULL && bytes != 0);
return fseek(fd, bytes, SEEK_CUR) == 0;
}
com_std_fd com_std_socket(bool isnetwork) {
if (!isnetwork) {
int sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
return fdopen(sockfd, "w+b");
} else
return NULL;
}
bool com_std_connect(com_std_fd fd, bool isnetwork, char *address) {
com_std_assert(address != NULL);
if (!isnetwork) {
struct sockaddr_un addr = {.sun_family = AF_UNIX};
__builtin_memcpy(&addr.sun_path, address, com_str_ext_len(address));
return connect(fileno(fd), (struct sockaddr *)&addr, sizeof(addr)) == 0;
} else
return NULL;
}
void com_std_exit(uint32_t status) { exit(status); }
void com_std_close(com_std_fd fd) { fclose(fd); }
+93
View File
@@ -0,0 +1,93 @@
/*
AMD64 specific Linux std parts.
*/
#include "linux.c"
#include "../std.h"
#include <fcntl.h>
#include <stdarg.h>
#include <stdint.h>
#include <sys/socket.h>
#include <sys/un.h>
inline com_std_fd com_std_open(char *path, uint32_t flags) {
com_std_assert(flags != 0);
uint32_t mode = flags & COM_STD_OPEN_READ && flags & COM_STD_OPEN_WRITE
? O_RDWR
: flags & COM_STD_OPEN_READ ? O_RDONLY
: O_WRONLY;
long ret;
__asm__ volatile("syscall"
: "=a"(ret)
: "a"(2), "D"(path), "S"(mode)
: "rcx", "r11", "memory");
if (ret <= 0) /* Mark NULL, removing error code */
ret = 0;
return (void *)ret;
}
inline bool com_std_write(com_std_fd fd, char const *data, uint32_t bytes) {
long ret;
__asm__ volatile("syscall"
: "=a"(ret)
: "a"(1), "D"(fd), "S"(data), "d"(bytes)
: "rcx", "r11", "memory");
return ret == bytes;
}
inline int32_t com_std_read(com_std_fd fd, char *data, uint32_t upto) {
long ret;
__asm__ volatile("syscall"
: "=a"(ret)
: "a"(0), "D"(fd), "S"(data), "d"(upto)
: "rcx", "r11", "memory");
return ret;
}
inline bool com_std_sfwd(com_std_fd fd, uint32_t bytes) {
long ret;
__asm__ volatile("syscall"
: "=a"(ret)
: "a"(8), "D"(fd), "S"(bytes), "d"(SEEK_CUR)
: "rcx", "r11", "memory");
return ret >= 0; /* TODO: Check whether offset is bytes offset exactly? */
}
inline com_std_fd com_std_socket(bool isnetwork) {
if (!isnetwork) {
int32_t sockfd;
__asm__ volatile("syscall"
: "=a"(sockfd)
: "a"(41), "D"(AF_UNIX), "S"(SOCK_STREAM), "d"(0)
: "rcx", "r11", "memory");
if (sockfd < 0)
sockfd = 0;
return (void *)(int64_t)sockfd;
} else
return NULL;
}
inline bool com_std_connect(com_std_fd fd, bool isnetwork, char *address) {
com_std_assert(address != NULL);
if (!isnetwork) {
struct sockaddr_un addr = {.sun_family = AF_UNIX};
__builtin_memcpy(&addr.sun_path, address, com_str_ext_len(address));
int32_t ret;
__asm__ volatile("syscall"
: "=a"(ret)
: "a"(42), "D"(fd), "S"(&addr), "d"(sizeof addr)
: "rcx", "r11", "memory");
return ret == 0;
} else
return NULL;
}
inline void com_std_exit(uint32_t status) {
__asm__ volatile("syscall" : : "a"(60), "D"(status) : "rcx", "r11", "memory");
__builtin_unreachable();
}
inline void com_std_close(com_std_fd fd) {
__asm__ volatile("syscall" : : "a"(3), "D"(fd) : "rcx", "r11", "memory");
}
+8 -4
View File
@@ -1,3 +1,7 @@
/*
Generic linux std parts.
*/
#include "../def.h" #include "../def.h"
#include "../std.h" #include "../std.h"
#include "../str.h" #include "../str.h"
@@ -8,18 +12,18 @@ void *com_std_alloc(void *ptr, size_t size) { return NULL; }
void com_std_assert(bool holds) { void com_std_assert(bool holds) {
/* TODO: Write line info to stderr as well. */ /* TODO: Write line info to stderr as well. */
if (!holds) if (!holds)
com_std_syscall(__NR_exit, -1, 0, 0); com_std_exit(-1);
} }
/* TODO: Figure out a way to make it easy to deal with. */ /* TODO: Figure out a way to make it easy to deal with. */
void com_std_printf(char const *fmt, ...) { void com_std_printf(char const *fmt, ...) {
com_std_syscall(1, 1, (intptr_t)fmt, com_str_ext_len(fmt)); com_std_write((void *)1, fmt, com_str_ext_len(fmt));
} }
void com_std_print_str(char const *str, uint32_t len, bool newline) { void com_std_print_str(char const *str, uint32_t len, bool newline) {
com_std_syscall(1, 1, (intptr_t)str, len); com_std_write((void *)1, str, len);
if (newline) if (newline)
com_std_syscall(1, 1, (intptr_t)"\n", 1); com_std_write((void *)1, "\n", 1);
} }
double com_std_sqrt(double v) { return __builtin_sqrt(v); } double com_std_sqrt(double v) { return __builtin_sqrt(v); }
+21
View File
@@ -1,5 +1,8 @@
#include "../std.h" #include "../std.h"
#include <stdbool.h>
#include <stddef.h>
void *com_std_alloc(void *ptr, size_t size) { return NULL; } void *com_std_alloc(void *ptr, size_t size) { return NULL; }
void com_std_assert(bool holds) {} void com_std_assert(bool holds) {}
void com_std_printf(char const *fmt, ...) {} void com_std_printf(char const *fmt, ...) {}
@@ -15,6 +18,24 @@ double com_std_sin(double v) { return 0; }
double com_std_cos(double v) { return 0; } double com_std_cos(double v) { return 0; }
#endif #endif
com_std_fd com_std_open(char *path, uint32_t flags) { return NULL; }
bool com_std_write(com_std_fd fd, char const *data, uint32_t bytes) {
return false;
}
int32_t com_std_read(com_std_fd fd, char *data, uint32_t upto) { return -1; }
bool com_std_sfwd(com_std_fd fd, uint32_t bytes) { return false; }
com_std_fd com_std_socket(bool isnetwork) { return NULL; }
bool com_std_connect(com_std_fd fd, bool isnetwork, char *address) {
return false;
}
void com_std_exit(uint32_t status) {
__builtin_trap();
while (1) {
}
__builtin_unreachable();
}
void com_std_close(com_std_fd fd) { return; }
// void memcpy(void *__restrict dest, const void *__restrict src, size_t n) { // void memcpy(void *__restrict dest, const void *__restrict src, size_t n) {
// __builtin_memcpy(dest, src, n); // __builtin_memcpy(dest, src, n);
// }; // };
+1 -1
View File
@@ -14,7 +14,7 @@
#define COM_BIN_NAT_ENDIAN (1 << 2) #define COM_BIN_NAT_ENDIAN (1 << 2)
typedef struct com_bin_interface { typedef struct com_bin_interface {
/* Attempts to read exactly N bytes, returns false if it cannot. */ /* Attempts to read exactly N bytes, return false if it cannot. */
bool (*readn)(void *ctx, char *into, uint32_t bytes); bool (*readn)(void *ctx, char *into, uint32_t bytes);
bool (*skipn)(void *ctx, uint32_t bytes); bool (*skipn)(void *ctx, uint32_t bytes);
} com_bin_interface; } com_bin_interface;
+2 -2
View File
@@ -39,8 +39,8 @@ typedef struct com_buf {
p_v->flags = p_f | COM_BUF_STACK; \ p_v->flags = p_f | COM_BUF_STACK; \
p_v->typesz = sizeof(p_t); p_v->typesz = sizeof(p_t);
#define com_buf_index(p_t, p_v, p_i) \ #define com_buf_index_as(p_t, p_v, p_i) \
(p_t *)(&(p_v)->data[(p_v)->typesz * (p_i)]) (p_t *)(&(p_v)->data[sizeof(p_t) * (p_i)])
/* Dynamic allocation to persist no matter the function flow. */ /* Dynamic allocation to persist no matter the function flow. */
struct com_buf *com_buf_make(uint32_t cap, uint32_t flags); struct com_buf *com_buf_make(uint32_t cap, uint32_t flags);
+13 -13
View File
@@ -10,21 +10,21 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#if COM_DEF_TARGET == COM_DEF_TARGET_LINUX /* Generic system interface, linux/bsd derived. */
#include <sys/syscall.h> typedef void *com_std_fd;
#define COM_STD_OPEN_READ (1 << 0)
static inline long com_std_syscall(long number, long arg1, long arg2, #define COM_STD_OPEN_WRITE (1 << 1)
long arg3) { com_std_fd com_std_open(char *path, uint32_t flags);
long ret; bool com_std_write(com_std_fd fd, char const *data, uint32_t bytes);
__asm__ volatile("syscall" int32_t com_std_read(com_std_fd fd, char *data, uint32_t upto);
: "=a"(ret) bool com_std_sfwd(com_std_fd fd, uint32_t bytes);
: "a"(number), "D"(arg1), "S"(arg2), "d"(arg3) com_std_fd com_std_socket(bool isnetwork);
: "rcx", "r11", "memory"); bool com_std_connect(com_std_fd sock, bool isnetwork, char *address);
return ret; void com_std_exit(uint32_t status) __attribute__((noreturn));
} void com_std_close(com_std_fd fd);
#endif
/* TODO: Remove, use buffer semantics instead. */ /* TODO: Remove, use buffer semantics instead. */
/* Instead have a mmap functions here. */
/* Note: Freeing is done by passing 0 size to pointer. */ /* Note: Freeing is done by passing 0 size to pointer. */
void *com_std_alloc(void *ptr, size_t size); void *com_std_alloc(void *ptr, size_t size);
+44 -22
View File
@@ -24,12 +24,12 @@
bool quited = false; bool quited = false;
bool fileread(void *ctx, char *into, uint32_t bytes) { bool fileread(void *ctx, char *into, uint32_t bytes) {
return com_std_syscall(0, (intptr_t)ctx, (intptr_t)into, bytes); return com_std_read(ctx, into, bytes) == bytes;
} }
bool fileskip(void *ctx, uint32_t bytes) { bool fileskip(void *ctx, uint32_t bytes) { return com_std_sfwd(ctx, bytes); }
return com_std_syscall(8, (intptr_t)ctx, bytes, 1) >= 0;
} #define AUTH_ENTRY_MAGIC_COOKIE "MIT-MAGIC-COOKIE-1"
static struct plr_x11_auth_entry { static struct plr_x11_auth_entry {
uint16_t family; uint16_t family;
@@ -39,10 +39,8 @@ static struct plr_x11_auth_entry {
} plr_x11_read_auth_entry(struct com_bin *b, struct com_buf *buf) { } plr_x11_read_auth_entry(struct com_bin *b, struct com_buf *buf) {
struct plr_x11_auth_entry result = {0}; struct plr_x11_auth_entry result = {0};
if (!com_bin_read_u16(b, &result.family)) { if (!com_bin_read_u16(b, &result.family))
com_std_printf("Failure to initialize X11\n");
goto BREAK; goto BREAK;
}
uint16_t addres_len; uint16_t addres_len;
if (!com_bin_read_u16(b, &addres_len)) if (!com_bin_read_u16(b, &addres_len))
goto BREAK; goto BREAK;
@@ -63,11 +61,11 @@ static struct plr_x11_auth_entry {
if (!com_bin_read_u16(b, &data_len)) if (!com_bin_read_u16(b, &data_len))
goto BREAK; goto BREAK;
uint32_t data_idx; uint32_t data_idx;
if (!com_bin_read_bufbi(b, buf, &data_idx, name_len)) if (!com_bin_read_bufbi(b, buf, &data_idx, data_len))
goto BREAK; goto BREAK;
result.auth_name = com_buf_index(struct com_buf, buf, name_idx); result.auth_name = com_buf_index_as(struct com_buf, buf, name_idx);
result.auth_data = com_buf_index(struct com_buf, buf, data_idx); result.auth_data = com_buf_index_as(struct com_buf, buf, data_idx);
result.success = true; result.success = true;
return result; return result;
BREAK: BREAK:
@@ -75,6 +73,24 @@ BREAK:
return result; return result;
} }
static bool plr_x11_handshake(struct plr_x11_auth_entry auth_entry) {
struct {
uint8_t endianness;
uint8_t pad0;
uint16_t major_version;
uint16_t minor_version;
uint16_t auth_len;
uint16_t auth_data_len;
uint16_t pad1;
} __attribute__((packed)) request = {
.endianness = 'l',
.major_version = 11,
.auth_len = sizeof(AUTH_ENTRY_MAGIC_COOKIE) - 1, // IS -1 NEEDED?
.auth_data_len = auth_entry.auth_data->len,
};
return true;
}
// TODO: correct error handling. // TODO: correct error handling.
extern int plr_display_x11_main(int argc, char *argv[]) { extern int plr_display_x11_main(int argc, char *argv[]) {
char test_string[] = "what is this?"; char test_string[] = "what is this?";
@@ -106,15 +122,13 @@ extern int plr_display_x11_main(int argc, char *argv[]) {
/* TODO: Move init to separate func. */ /* TODO: Move init to separate func. */
/* Open X11 socket for communication. */ /* Open X11 socket for communication. */
int const xfd = com_std_syscall(41, AF_UNIX, SOCK_STREAM, 0); com_std_fd const xfd = com_std_socket(false);
if (xfd < 0) { if (!xfd) {
com_std_printf("Failure to initialize X11\n"); com_std_printf("Failure to initialize X11\n");
return -1; return -1;
} }
struct sockaddr_un const addr = {.sun_family = AF_UNIX, if (!com_std_connect(xfd, false, "/tmp/.X11-unix/X0")) {
.sun_path = "/tmp/.X11-unix/X0"};
if (com_std_syscall(42, xfd, (intptr_t)&addr, sizeof addr)) {
com_std_printf("Failure to initialize X11\n"); com_std_printf("Failure to initialize X11\n");
return -1; return -1;
} }
@@ -131,7 +145,7 @@ extern int plr_display_x11_main(int argc, char *argv[]) {
} }
/* Open it and parse. */ /* Open it and parse. */
int const xauthfd = com_std_syscall(2, (intptr_t)xauthpath, O_RDONLY, 0); com_std_fd const xauthfd = com_std_open(xauthpath, COM_STD_OPEN_READ);
if (xauthfd < 0) { if (xauthfd < 0) {
com_std_printf("Failure to initialize X11\n"); com_std_printf("Failure to initialize X11\n");
return -1; return -1;
@@ -143,13 +157,21 @@ extern int plr_display_x11_main(int argc, char *argv[]) {
.flags = COM_BIN_BIG_ENDIAN, .flags = COM_BIN_BIG_ENDIAN,
.interface = {.readn = fileread, .skipn = fileskip}}; .interface = {.readn = fileread, .skipn = fileskip}};
struct plr_x11_auth_entry auth_entry = /* Loop over auth entries until we find magic cookie one. */
plr_x11_read_auth_entry(&xauthbin, xauthbuf); struct plr_x11_auth_entry auth_entry;
do {
com_buf_clear(xauthbuf);
auth_entry = plr_x11_read_auth_entry(&xauthbin, xauthbuf);
} while (auth_entry.success && auth_entry.family != 256);
if (!auth_entry.success) {
com_std_printf("Failure to initialize X11\n");
return -1;
}
com_std_print_str(auth_entry.auth_name->data, auth_entry.auth_name->len, com_std_close(xauthfd);
true);
com_std_print_str(auth_entry.auth_data->data, auth_entry.auth_data->len, /* TODO: Check for auth_entry.name == MAGIC ? */
true); plr_x11_handshake(auth_entry);
com_buf_free(xauthbuf); com_buf_free(xauthbuf);
+10 -5
View File
@@ -1,6 +1,7 @@
CC = clang CC = clang
RELEASE ?= 0 RELEASE ?= 0 # Optimize.
SQUEEZE ?= 0 DEBUG ?= 1 # Emit debug info.
SQUEEZE ?= 0 # Nuclear option to save space.
BITS ?= 64 BITS ?= 64
CFLAGS = -Wall -std=gnu99 -flto=thin -ffast-math -fno-ident -fvisibility=hidden CFLAGS = -Wall -std=gnu99 -flto=thin -ffast-math -fno-ident -fvisibility=hidden
ifeq ($(MAKECMDGOALS),linux) ifeq ($(MAKECMDGOALS),linux)
@@ -23,10 +24,13 @@ ifeq ($(MAKECMDGOALS),wasm)
CFLAGS += -Wl,--compress-relocations CFLAGS += -Wl,--compress-relocations
endif endif
endif endif
ifeq ($(RELEASE), 0) ifeq ($(DEBUG), 1)
CFLAGS += -g3 -O1 CFLAGS += -g3
else else
CFLAGS += -Wl,--strip-all -DNDEBUG -O3 -fuse-ld=lld -fmerge-all-constants -Wl,-O3 \ CFLAGS += -DNDEBUG -Wl,--strip-all
endif
ifeq ($(RELEASE), 1)
CFLAGS += -O1 -fuse-ld=lld -fmerge-all-constants -Wl,-O3 \
-ffunction-sections -fdata-sections -Wl,--gc-sections \ -ffunction-sections -fdata-sections -Wl,--gc-sections \
-Wl,-mllvm,--vectorize-slp=true \ -Wl,-mllvm,--vectorize-slp=true \
-Wl,-mllvm,--enable-gvn-hoist=true -Wl,-mllvm,--enable-gvn-hoist=true
@@ -55,6 +59,7 @@ wasm: CFLAGS += --target=wasm32 -nostdlib -Wl,--no-entry -msimd128 -mbulk-memory
wasm: wasm:
$(CC) -o player.wasm $(WASM) $(CFLAGS) $(CC) -o player.wasm $(WASM) $(CFLAGS)
# TODO: Use https://github.com/amindlost/pmodew
dos: $(DOS) $(DEPS) dos: $(DOS) $(DEPS)
wcl386 -bt=dos4g -ox -l=dos4g $(DOS) wcl386 -bt=dos4g -ox -l=dos4g $(DOS)
+1 -1
View File
@@ -12,7 +12,7 @@
#include "./draw.c" #include "./draw.c"
#if COM_DEF_TARGET == COM_DEF_TARGET_LINUX #if COM_DEF_TARGET == COM_DEF_TARGET_LINUX
#include "../Common/Std/linux.c" #include "../Common/Std/linux-amd64.c"
#include "../Common/Timer/stub.c" #include "../Common/Timer/stub.c"
#include "./Display/x11.c" #include "./Display/x11.c"
#include "./Main/linux.c" #include "./Main/linux.c"
+5 -15
View File
@@ -1,5 +1,3 @@
OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
OUTPUT_ARCH(i386:x86-64)
ENTRY(_start) ENTRY(_start)
PHDRS PHDRS
@@ -24,6 +22,10 @@ SECTIONS
*(.data*) *(.data*)
} }
.shstrtab : {
*(.shstrtab*)
}
.bss : { .bss : {
*(.bss*) *(.bss*)
*(COMMON) *(COMMON)
@@ -31,18 +33,6 @@ SECTIONS
/* Discard bloat and unnecessary ELF sections */ /* Discard bloat and unnecessary ELF sections */
/DISCARD/ : { /DISCARD/ : {
*(.note.GNU-stack) *(*)
*(.gnu_debuglink)
*(.gnu.lto_*)
*(.note.gnu.build-id)
*(.eh_frame_hdr)
*(.eh_frame_entry)
*(.eh_frame)
*(.comment)
*(.interp)
*(.dynsym)
*(.dynstr)
*(.hash)
*(.gnu.hash)
} }
} }