Skip to content

Instantly share code, notes, and snippets.

@donbright
Last active September 4, 2018 09:00
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save donbright/4137ab24199239a7a67682216c51d0b8 to your computer and use it in GitHub Desktop.
Save donbright/4137ab24199239a7a67682216c51d0b8 to your computer and use it in GitHub Desktop.
This allows rudimentary usage of TinyCC on Darwin 8 i386, the core of MacOSX 10.4

Step 0.

The point of this is to install the TinyCC compiler on the Darwin 8 computer operating sysytem, running on an i386 mcahine. Darwin 801 is the open source core of Apple's Mac OSX (TM) 10.4 Tiger operating system. The hottest operating system of 2005.

These are extremely rudimentary instructions, assuming you have an extensive experience with commandline and familiarity with the various terminology and jargon.

This was streamed on raw video here, and contains full unedited details of how it was done the first time:

https://www.youtube.com/watch?v=EspzMmGudcA

Step 1. Get Darwin 8 ISO (801) for i386 from Apple and install on a computer or Virtual Machine

https://opensource.apple.com/static/iso/

Follow this vid if you cant figure it out

https://www.youtube.com/watch?v=Ww8p7eTs8LI

Recommended is i386 because ppc is probably really slow and TinyCC might not even support it.

Step 2.

Get OBJCONV from https://github.com/vertis/objconv Build and install it to /usr/local/bin using gcc

Step 3

Get TinyCC from http://www.tinycc.org and uncompress and untarit This is using 0.9.26 so all of these kludges will need altering if you use a different version.

Step 4 is to kludge the TinyCC configure and Makefile to work on Darwin8 (see the kludge.diff below)

Step 5 is to kludge some of the c code to build on Darwin8 (see the kludge.diff below)

Step 6 is to build by running 'make'

Step 7 is to test basic compilation by running 'make test' this uses Tinycc in a special mode with the '-run' flag which means, basically that its not actually linking a binary, its running the file in place. Cool but we can go farther. Make install to put it under /usr/local/bin and keep going.

Step 8 is to start using TinyCC -c to create object files and then bodge together an executable using objconv, strip, and ld in a very unusual manner that is probably a gigantic security hole. (see build.sh, below in this gist)

Step 9 is to try out some C programs.

First you can try toy programs, like 'code golf' to print the Icelandic flag.

http://codegolf.stackexchange.com/questions/85141/draw-the-national-flag-of-iceland

As you can see in the video linked above, I was able to compile Apples version of 'wc', the Un*x "word count" program to count the number of words in Sophocle's play Antigone downloaded from MIT, English translation R.C.Jebb

http://opensource.apple.com/source/text_cmds/text_cmds-47/wc/ http://classics.mit.edu/Sophocles/antigone.pl.txt

Step 10.

Imagine.


Below is some hints of the textfiles from the video.

First, a kludge bash script that will take a .c file and build a working executable

Second, a diff to show the kludges to the config and Makefile and .c file of Tinycc

Thanks for reading.

#!/bin/bash
# kludge to build executables with tinycc on Darwin BSD 8
# Don Bright 2016 , Creative Commons Zero license (public domain)
set -x
if [ ! -e $1.c ]; then
echo $ ls file.c
echo file.c
echo $ bash -x build.sh file
exit
fi
# compile to object file
tcc -D__LITTLE_ENDIAN__ $1.c -c -o $1.o
if [ $? -ne 0 ]; then
echo tcc fail;
exit
fi
# convert ELF to MACHO
objconv -fmacho -nu $1.o $1m.o
if [ $? -ne 0 ]; then
echo objconv fail;
exit
fi
# dump names (debugging)
# objconv -ds $1m.o
# get rid of local NULL symbol, to allow linker to work
strip -x $1m.o
if [ $? -ne 0 ]; then
echo strip fail;
exit
fi
# dump names (debugging)
# objconv -ds $1m.o
# linker line, taken from gcc -v
# linker kludge, taken from thin air and man ld
happylinker="-segprot __TEXT rwx rwx"
ld $happylinker -arch i386 -dynamic -o $1.out -lcrt1.o -lcrt2.o \
-L/usr/lib/gcc/darwin/3.3 -L/usr/lib/gcc/darwin \
-L/usr/libexec/gcc/darwin/i386/3.3/../../.. \
./$1m.o -lgcc -lSystem | c++filt
if [ $? -ne 0 ]; then
echo linker ld fail;
exit
fi
# verify a little bit
file $1.out
if [ $? -ne 0 ]; then
echo file check of $1.out fail;
exit
fi
chmod u+x ./$1.out
if [ $? -ne 0 ]; then
echo chmod of $1.out fail;
exit
fi
diff -c tcc-0.9.26/Makefile tcc-kludge/Makefile
*** tcc-0.9.26/Makefile Fri Feb 15 06:24:00 2013
--- tcc-kludge/Makefile Sun Sep 18 03:27:59 2016
***************
*** 97,119 ****
PROGS_CROSS=$(WIN32_CROSS) $(I386_CROSS) $(X64_CROSS) $(ARM_CROSS) $(C67_CROSS)
LIBTCC1_CROSS=lib/i386-win32/libtcc1.a
LIBTCC1=libtcc1.a
! else ifdef CONFIG_WIN32
PROGS+=tiny_impdef$(EXESUF) tiny_libmaker$(EXESUF)
NATIVE_FILES=$(WIN32_FILES)
PROGS_CROSS=$(WIN64_CROSS) $(I386_CROSS) $(X64_CROSS) $(ARM_CROSS) $(C67_CROSS)
LIBTCC1_CROSS=lib/x86_64-win32/libtcc1.a
LIBTCC1=libtcc1.a
! else ifeq ($(ARCH),i386)
NATIVE_FILES=$(I386_FILES)
PROGS_CROSS=$(X64_CROSS) $(WIN32_CROSS) $(WIN64_CROSS) $(ARM_CROSS) $(C67_CROSS)
LIBTCC1_CROSS=lib/i386-win32/libtcc1.a lib/x86_64-win32/libtcc1.a
LIBTCC1=libtcc1.a
! else ifeq ($(ARCH),x86-64)
NATIVE_FILES=$(X86_64_FILES)
PROGS_CROSS=$(I386_CROSS) $(WIN32_CROSS) $(WIN64_CROSS) $(ARM_CROSS) $(C67_CROSS)
LIBTCC1_CROSS=lib/i386-win32/libtcc1.a lib/x86_64-win32/libtcc1.a lib/i386/libtcc1.a
LIBTCC1=libtcc1.a
! else ifeq ($(ARCH),arm)
NATIVE_FILES=$(ARM_FILES)
PROGS_CROSS=$(I386_CROSS) $(X64_CROSS) $(WIN32_CROSS) $(WIN64_CROSS) $(C67_CROSS)
endif
--- 97,123 ----
PROGS_CROSS=$(WIN32_CROSS) $(I386_CROSS) $(X64_CROSS) $(ARM_CROSS) $(C67_CROSS)
LIBTCC1_CROSS=lib/i386-win32/libtcc1.a
LIBTCC1=libtcc1.a
! endif
! ifdef CONFIG_WIN32
PROGS+=tiny_impdef$(EXESUF) tiny_libmaker$(EXESUF)
NATIVE_FILES=$(WIN32_FILES)
PROGS_CROSS=$(WIN64_CROSS) $(I386_CROSS) $(X64_CROSS) $(ARM_CROSS) $(C67_CROSS)
LIBTCC1_CROSS=lib/x86_64-win32/libtcc1.a
LIBTCC1=libtcc1.a
! endif
! ifeq ($(ARCH),i386)
NATIVE_FILES=$(I386_FILES)
PROGS_CROSS=$(X64_CROSS) $(WIN32_CROSS) $(WIN64_CROSS) $(ARM_CROSS) $(C67_CROSS)
LIBTCC1_CROSS=lib/i386-win32/libtcc1.a lib/x86_64-win32/libtcc1.a
LIBTCC1=libtcc1.a
! endif
! ifeq ($(ARCH),x86-64)
NATIVE_FILES=$(X86_64_FILES)
PROGS_CROSS=$(I386_CROSS) $(WIN32_CROSS) $(WIN64_CROSS) $(ARM_CROSS) $(C67_CROSS)
LIBTCC1_CROSS=lib/i386-win32/libtcc1.a lib/x86_64-win32/libtcc1.a lib/i386/libtcc1.a
LIBTCC1=libtcc1.a
! endif
! ifeq ($(ARCH),arm)
NATIVE_FILES=$(ARM_FILES)
PROGS_CROSS=$(I386_CROSS) $(X64_CROSS) $(WIN32_CROSS) $(WIN64_CROSS) $(C67_CROSS)
endif
Only in tcc-kludge/: config.h
Only in tcc-kludge/: config.mak
Only in tcc-kludge/: config.texi
diff -c tcc-0.9.26/configure tcc-kludge/configure
*** tcc-0.9.26/configure Fri Feb 15 06:24:00 2013
--- tcc-kludge/configure Sun Sep 18 03:08:59 2016
***************
*** 47,52 ****
--- 47,53 ----
confvars=
cpu=`uname -m`
+ cpu=i386
# OS specific
targetos=`uname -s`
Common subdirectories: tcc-0.9.26/examples and tcc-kludge/examples
Common subdirectories: tcc-0.9.26/include and tcc-kludge/include
Common subdirectories: tcc-0.9.26/lib and tcc-kludge/lib
Only in tcc-kludge/: tcc-doc.info
Only in tcc-kludge/: tcc.1
diff -c tcc-0.9.26/tccrun.c tcc-kludge/tccrun.c
*** tcc-0.9.26/tccrun.c Fri Feb 15 06:24:00 2013
--- tcc-kludge/tccrun.c Sun Sep 18 03:18:17 2016
***************
*** 478,484 ****
if (level == 0) {
#if defined(__APPLE__)
! *paddr = uc->uc_mcontext->__ss.__eip;
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
*paddr = uc->uc_mcontext.mc_eip;
#elif defined(__dietlibc__)
--- 478,486 ----
if (level == 0) {
#if defined(__APPLE__)
! // *paddr = uc->uc_mcontext->__ss.__eip;
! // darwin8 kludge
! *paddr = uc->uc_mcontext->sc.sc_eip;
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
*paddr = uc->uc_mcontext.mc_eip;
#elif defined(__dietlibc__)
***************
*** 489,495 ****
return 0;
} else {
#if defined(__APPLE__)
! fp = uc->uc_mcontext->__ss.__ebp;
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
fp = uc->uc_mcontext.mc_ebp;
#elif defined(__dietlibc__)
--- 491,499 ----
return 0;
} else {
#if defined(__APPLE__)
! //fp = uc->uc_mcontext->__ss.__ebp;
! // darwin8 kludge
! fp = uc->uc_mcontext->sc.sc_ebp;
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
fp = uc->uc_mcontext.mc_ebp;
#elif defined(__dietlibc__)
Common subdirectories: tcc-0.9.26/tests and tcc-kludge/tests
Common subdirectories: tcc-0.9.26/win32 and tcc-kludge/win32
@mgttt
Copy link

mgttt commented Sep 4, 2018

interesting, and is the tcc built with this way can then build itself?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment