commit e1bb4555001f97b03a501bab39c9ad6341055161
parent bb953343daf4a229c1538a2bce2d0266f11a808c
Author: Henry Wilson <henry@henryandlizzy.uk>
Date: Mon, 22 Dec 2025 01:21:36 +0000
Initial C++ support
Diffstat:
| M | Tupfile | | | 2 | ++ |
| M | linux.h | | | 8 | ++++++++ |
| A | linux.hpp | | | 74 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| D | test.c | | | 22 | ---------------------- |
| A | test.cpp | | | 22 | ++++++++++++++++++++++ |
| A | true.cpp | | | 2 | ++ |
| M | x86_64.s | | | 50 | ++++++++++++++++++++++++++++++++++---------------- |
7 files changed, 142 insertions(+), 38 deletions(-)
diff --git a/Tupfile b/Tupfile
@@ -2,8 +2,10 @@ CFLAGS = -g -Os -fno-asynchronous-unwind-tables -fno-pic -fno-pie -no-pie -g -fn
LDFLAGS = -static -nostartfiles -nolibc -nodefaultlibs -nostdlib -fno-pic -fno-pie -no-pie -Xlinker --gc-sections
!cc = |> cc $(CFLAGS) -c -o %o %f |> obj/%B.o
+!c++ = |> c++ $(CFLAGS) -c -o %o %f |> obj/%B.o
: foreach *.c |> !cc |> {objs}
+: foreach *.cpp |> !c++ |> {objs}
run ./gen.sh
.gitignore
diff --git a/linux.h b/linux.h
@@ -1,5 +1,9 @@
#pragma once
+#ifdef __cplusplus
+extern "C" {
+#endif
+
typedef unsigned long long size_t;
typedef signed long long ssize_t;
typedef unsigned long long uintptr_t;
@@ -64,3 +68,7 @@ static unsigned get_errno(ssize_t ret)
return -ret;
return 0;
}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/linux.hpp b/linux.hpp
@@ -0,0 +1,74 @@
+#pragma once
+
+typedef unsigned long long size_t;
+typedef signed long long ssize_t;
+typedef unsigned long long uintptr_t;
+typedef signed long long intptr_t;
+typedef unsigned long long ino64_t;
+typedef signed long long off64_t;
+
+enum {
+ AT_FDCWD = -100,
+
+ O_RDONLY = 0,
+ O_WRONLY = 1,
+ O_RDWR = 2,
+
+ PROT_READ = 0x1,
+ PROT_WRITE = 0x2,
+ PROT_EXEC = 0x4,
+ MAP_FIXED = 0x10,
+ MAP_ANONYMOUS = 0x20,
+ MAP_SHARED = 0x1,
+ MAP_PRIVATE = 0x2,
+
+ DT_UNKNOWN = 0,
+ DT_FIFO = 1,
+ DT_CHR = 2,
+ DT_DIR = 4,
+ DT_BLK = 6,
+ DT_REG = 8,
+ DT_LNK = 10,
+ DT_SOCK = 12,
+ DT_WHT = 14,
+};
+
+struct iovecc
+{
+ char const* data;
+ size_t len;
+};
+
+__attribute__((noreturn))
+extern void exit(int error_code);
+
+extern int read(int fd, char* data, size_t count);
+
+extern "C" {
+extern int write(int fd, char const* data, size_t count);
+}
+extern int write(int fd, iovecc data);
+
+extern ssize_t writev(int fd, struct iovecc const* iov, size_t count);
+
+extern int openat(int fd, char const* name, int flags, int mode);
+
+extern int close(int fd);
+
+struct linux_dirent64 {
+ ino64_t d_ino; /* 64-bit inode number */
+ off64_t d_off; /* Not an offset; see getdents() */
+ unsigned short d_reclen; /* Size of this dirent */
+ unsigned char d_type; /* File type */
+ char d_name[]; /* Filename (null-terminated) */
+};
+extern ssize_t getdents64(int fd, struct linux_dirent64 dirp[], size_t count);
+
+extern intptr_t mmap(void* addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long off);
+
+static unsigned get_errno(ssize_t ret)
+{
+ if (0 > ret && ret >= -0xFFFF)
+ return -ret;
+ return 0;
+}
diff --git a/test.c b/test.c
@@ -1,22 +0,0 @@
-#include "linux.h"
-
-char const rodata[] = "rodata\n";
-char data[] = "data\n";
-char bss[4];
-
-void text()
-{
- write(1, rodata, sizeof(rodata) - 1);
- write(1, data, sizeof(data) - 1);
-
- bss[0] = 'b';
- bss[1] = 's';
- bss[2] = 's';
- bss[3] = '\n';
- write(1, bss, sizeof(bss));
-}
-
-int main()
-{
- text();
-}
diff --git a/test.cpp b/test.cpp
@@ -0,0 +1,22 @@
+#include "linux.hpp"
+
+char const rodata[] = "rodata\n";
+char data[] = "data\n";
+char bss[4];
+
+void text()
+{
+ write(1, {rodata, sizeof(rodata) - 1});
+ write(1, {data, sizeof(data) - 1});
+
+ bss[0] = 'b';
+ bss[1] = 's';
+ bss[2] = 's';
+ bss[3] = '\n';
+ write(1, bss, sizeof(bss));
+}
+
+int main()
+{
+ text();
+}
diff --git a/true.cpp b/true.cpp
@@ -0,0 +1,2 @@
+int main()
+{}
diff --git a/x86_64.s b/x86_64.s
@@ -12,14 +12,22 @@ start: # start is the entry point known to the linker
mov rdi, rax
jmp exit
-.macro _syscall, num, impl, name
+.macro extern_alias, name
.global \name
-.section .text.\name
\name:
+.endm
+
+.macro extern, name
+.section .text.\name
+extern_alias \name
+.endm
+
+.macro _syscall, num, impl
mov rax, \num
jmp \impl
.endm
+.section .text.syscall3
syscall3:
push r11
push rcx
@@ -28,6 +36,7 @@ syscall3:
pop r11
ret
+.section .text.syscall6
syscall6:
push r11
mov r10, rcx
@@ -35,18 +44,27 @@ syscall6:
pop r11
ret
-.macro syscall6, num, name
-.global \name
-.section .text.\name
-\name:
- mov rax, \num
-.endm
+extern read
+_syscall 0 syscall3
+
+extern write
+extern_alias _Z5writei6iovecc
+_syscall 1 syscall3
+
+extern close
+_syscall 3 syscall3
+
+extern mmap
+_syscall 9 syscall6
+
+extern writev
+_syscall 20 syscall3
+
+extern exit
+_syscall 60 syscall3
+
+extern getdents64
+_syscall 217 syscall3
-_syscall 0 syscall3 read
-_syscall 1 syscall3 write
-_syscall 3 syscall3 close
-_syscall 9 syscall6 mmap
-_syscall 20 syscall3 writev
-_syscall 60 syscall3 exit
-_syscall 217 syscall3 getdents64
-_syscall 257 syscall6 openat
+extern openat
+_syscall 257 syscall6