summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2022-02-18 14:15:09 -0500
committerpommicket <pommicket@gmail.com>2022-02-18 14:36:44 -0500
commit06def8fb862286658ef8cfc5cebb2711faadba1e (patch)
treece1486f57de6ce8f1d05d5a5ffc85b2a73977e35
parent826d1afd58c2e064a9c8fdb09eda1b08469de1a8 (diff)
satrt readme
-rw-r--r--05/Makefile14
-rw-r--r--05/README.md42
-rw-r--r--05/tcc-0.9.27/.gitignore1
-rw-r--r--05/tcc-0.9.27/config.h8
-rw-r--r--05/tcc-0.9.27/x86_64-gen.c2
-rw-r--r--05/test.c3
-rw-r--r--05/test.s1
-rw-r--r--README.md2
8 files changed, 65 insertions, 8 deletions
diff --git a/05/Makefile b/05/Makefile
index 0a2fcb5..628d286 100644
--- a/05/Makefile
+++ b/05/Makefile
@@ -1,4 +1,6 @@
-all: out04 a.out
+TCCDIR=tcc-0.9.27
+TCC=$(TCCDIR)/tcc
+all: out04 a.out test.out README.html
in04: *.b ../04a/out04
../04a/out04 main.b in04
out04: in04 ../04/out03
@@ -9,5 +11,13 @@ out04: in04 ../04/out03
./out04 $< $@
a.out: main.c *.h out04
./out04
+test.out: $(TCC) test.s.o test.c.o
+ $(TCC) -static -nostdlib test.s.o test.c.o -o test.out
+test.s.o: $(TCC) test.s
+ $(TCC) -static -nostdlib -c test.s -o test.s.o
+test.c.o: $(TCC) test.c
+ $(TCC) -static -nostdlib -c test.c -o test.c.o
+$(TCC): $(TCCDIR)/*.c $(TCCDIR)/*.h out04
+ cd $(TCCDIR) && ../out04 tcc.c tcc
clean:
- rm -f out* README.html *.out
+ rm -f out* README.html *.out *.o $(TCC)
diff --git a/05/README.md b/05/README.md
new file mode 100644
index 0000000..276aac6
--- /dev/null
+++ b/05/README.md
@@ -0,0 +1,42 @@
+# [bootstrap](../README.md) stage 05
+
+This stage consists of a C compiler capable of compiling TCC (after some modifications
+to TCC's source code).
+Run
+
+```
+make
+```
+
+to build our C compiler and TCC. This will take some time (approx. 25 seconds on my computer).
+A test program, `test.out` will be compiled using `tcc`. If you run
+it, you should get the output
+
+```
+Hello, world!
+```
+
+So now we just compile TCC with itself, and we're done, right?
+Well, not quite...
+
+## the nightmare begins
+
+The issue here is that to compile TCC/GCC with TCC, we need libc, the C standard library functions.
+Our C compiler just includes these functions in the standard header files, but normally
+the code for them is located in a separate library file (called something like
+`/usr/lib/x86_64-linux-gnu/libc-2.31.so`).
+
+This library file is itself compiled from C source files (typically glibc).
+So, can't we just compile glibc with TCC, then compile TCC with itself?
+Well, no. Compiling glibc with TCC is basically impossible; you need to compile
+it with GCC.
+
+Other libc implementations aren't too happy about TCC either -- I tried to compile
+[musl](http://www.musl-libc.org/) for several hours, and had to give up in the end.
+
+It seems that the one option left is to make our own libc, and try to use it along with
+TCC to compile GCC.
+From there, we should be able to compile glibc with GCC. Then, we can compile GCC with GCC and glibc.
+If we do all this, we should get the same libc.so and gcc files as if we had started
+with any GCC and glibc builds. It's all very confusing.
+
diff --git a/05/tcc-0.9.27/.gitignore b/05/tcc-0.9.27/.gitignore
index c989b6b..a50ca5e 100644
--- a/05/tcc-0.9.27/.gitignore
+++ b/05/tcc-0.9.27/.gitignore
@@ -19,7 +19,6 @@ tcc
*-tcc
libtcc*.def
-config*.h
config*.mak
config.texi
conftest*
diff --git a/05/tcc-0.9.27/config.h b/05/tcc-0.9.27/config.h
new file mode 100644
index 0000000..d363b97
--- /dev/null
+++ b/05/tcc-0.9.27/config.h
@@ -0,0 +1,8 @@
+#define TCC_VERSION "0.9.27"
+#define CONFIG_TCC_STATIC 1
+#define CONFIG_TCC_ELFINTERP "/XXX"
+#define CONFIG_TCC_CRT_PREFIX "/XXX"
+#define CONFIG_SYSROOT "/XXX"
+#define inline
+#define TCC_TARGET_X86_64 1
+#define ONE_SOURCE 1
diff --git a/05/tcc-0.9.27/x86_64-gen.c b/05/tcc-0.9.27/x86_64-gen.c
index 9060ae9..ad56ed6 100644
--- a/05/tcc-0.9.27/x86_64-gen.c
+++ b/05/tcc-0.9.27/x86_64-gen.c
@@ -599,7 +599,7 @@ static void gcall_or_jmp(int is_jmp)
#ifdef TCC_TARGET_PE
greloca(cur_text_section, vtop->sym, ind + 1, R_X86_64_PC32, (int)(vtop->c.i-4));
#else
- greloca(cur_text_section, vtop->sym, ind + 1, R_X86_64_PLT32, (int)(vtop->c.i-4));
+ greloca(cur_text_section, vtop->sym, ind + 1, R_X86_64_PC32, (int)(vtop->c.i-4)); // tcc's PLT code doesn't seem to work with static builds
#endif
} else {
/* put an empty PC32 relocation */
diff --git a/05/test.c b/05/test.c
index b287d99..70c80b0 100644
--- a/05/test.c
+++ b/05/test.c
@@ -1,6 +1,5 @@
-// calling assembly functions from C is not working for some reason.
extern unsigned long __syscall(int, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
-int main(unsigned long (*_syscall)(int, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long)) {
+int main(void) {
__syscall(1, 1, (unsigned long)"Hello, world!\n", 14, 0, 0, 0);
return 42;
}
diff --git a/05/test.s b/05/test.s
index 7379247..a57a946 100644
--- a/05/test.s
+++ b/05/test.s
@@ -15,7 +15,6 @@ __syscall:
ret
_start:
- lea __syscall, %rdi
call main
mov $60, %eax
syscall
diff --git a/README.md b/README.md
index ec85c7e..e4e47f6 100644
--- a/README.md
+++ b/README.md
@@ -60,7 +60,7 @@ If you're unfamiliar with x86-64 assembly, you should check out the instruction
Bootstrapping a compiler is not an easy task, so we're trying to make it as easy
as possible. We don't even necessarily need a standard-compliant C compiler, we
only need enough to compile someone else's C compiler, specifically we'll be
-using [TCC](https://bellard.org/tcc/) since it's written in standard C89.
+using [TCC](https://bellard.org/tcc/) since it's written (mostly) in standard C89.
- efficiency is not a concern