Compare commits

...

20 Commits

Author SHA1 Message Date
Jan Nieuwenhuizen bb0a641cab
lotsa debug printing 2018-12-20 10:16:15 +01:00
Jan Nieuwenhuizen a41c019ff7
build: Support gash. 2018-12-20 09:03:00 +01:00
Jan Nieuwenhuizen 90075d68bd
test: run tests/tests2 tests. 2018-12-20 09:03:00 +01:00
Jan Nieuwenhuizen 6d88f740dd
build: Support building from bootstrap-mes. 2018-12-20 09:02:59 +01:00
Jan Nieuwenhuizen 30b55248fc
bootstrappable: Work around Nyacc-0.80.40 bug. 2018-12-20 09:02:59 +01:00
Jan Nieuwenhuizen 9bcd7c0c30
bootstrappable: Work around Nyacc-0.80.40 bug. 2018-12-20 09:02:59 +01:00
Jan Nieuwenhuizen 09604d2dfa
bootstrappable: Work around Nyacc-0.80.42 bug.
* tccgen.c (update_storage)[__MESC__]: Work around Nyacc-0.80.42 bug.
2018-12-20 09:02:58 +01:00
Jan Nieuwenhuizen b73113dc5c
bootstrappable: Remove gratuitous complex deep nesting. 2018-12-20 09:02:58 +01:00
Jan Nieuwenhuizen 0389b2d219
bootstrappable: NORETURN, ALIGN for MesCC. 2018-12-20 09:02:58 +01:00
Jan Nieuwenhuizen 1c509d5e85
bootstrappable: Force static link. 2018-12-20 09:02:58 +01:00
Jan Nieuwenhuizen 718fb1c231
bootstrappable: Work around MesCC bug.
* tccelf.c (squeeze_multi_relocs): Simplify expressions.
2018-12-20 09:02:57 +01:00
Jan Nieuwenhuizen 0ae7c6748b
bootstrappable: add tcc.h include guards to include location. 2018-12-20 09:02:57 +01:00
Jan Nieuwenhuizen abcc1e0cb2
bootstrappable: uint16_t in struct on heap. 2018-12-20 09:02:57 +01:00
Jan Nieuwenhuizen d12f4a449e
bootstrappable: handle libtcc1.a. 2018-12-20 09:02:56 +01:00
Jan Nieuwenhuizen a02a47aa94
bootstrappable: Skip tidy_section_headers.
* tccelf.c (elf_output_file)[BOOTSTRAPPABLE]: Skip tidy_section_headers.
2018-12-20 09:02:56 +01:00
Jan Nieuwenhuizen c21f824ee5
bootstrappable: HAVE_FLOAT. 2018-12-20 09:02:56 +01:00
Jan Nieuwenhuizen 194c97f0bd
bootstrappable: HAVE_BITFIELD. 2018-12-20 09:02:56 +01:00
Jan Nieuwenhuizen 59ef83545d
bootstrappable: HAVE_LONG_LONG.
* tccpp.c (parse_number)[!HAVE_LONG_LONG]: Skip overflow test.  Do not
  set TOK_CCLONG.
2018-12-20 09:02:55 +01:00
Jan Nieuwenhuizen f724254cdd
build: bootstrap build scripts.
* bootstrap.sh: New file.
* build.sh: New file.
* check.sh: New file.
* doit: New file.
* install.sh: New file.
* test.sh: New file.
2018-12-20 09:02:55 +01:00
Jan Nieuwenhuizen 1ad9950fb6
bootstrappable: Remove non-free grep test.
* tests/tests2/46_grep.c: Remove non-free grep code.
* tests/tests2/46_grep.expect: Remove.
2018-12-20 09:02:55 +01:00
32 changed files with 2744 additions and 641 deletions

8
BOOT Normal file
View File

@ -0,0 +1,8 @@
#export LIBRARY_PATH=/home/janneke/src/tinycc-seed
#export INCLUDE_PATH=/home/janneke/src/mes/include
export C_INCLUDE_PATH=/home/janneke/src/mes/include
export LIBRARY_PATH=/home/janneke/src/tinycc-seed
./configure --cc='mes-tcc -static' --cpu=i386
make ONE_SOURCE=yes CPPFLAGS=-DONE_SOURCE=yes

View File

@ -190,7 +190,7 @@ $(X)%.o : %.c $(LIBTCC_INC)
$(X)tcc.o : tcctools.c
# Host Tiny C Compiler
tcc$(EXESUF): tcc.o $(LIBTCC)
$(PROGRAM_PREFIX)tcc$(EXESUF): tcc.o $(LIBTCC)
$(CC) -o $@ $^ $(LIBS) $(LDFLAGS) $(LINK_LIBTCC)
# Cross Tiny C Compilers

View File

@ -225,12 +225,20 @@ void o(uint32_t i)
if (ind1 > cur_text_section->data_allocated)
section_realloc(cur_text_section, ind1);
cur_text_section->data[ind++] = i&255;
trace ("o "); eputs (itoa (i&255)); eputs ("\n");
trace ("o "); eputs (itoa (cur_text_section->data[ind-1])); eputs ("\n");
i>>=8;
cur_text_section->data[ind++] = i&255;
trace ("o "); eputs (itoa (i&255)); eputs ("\n");
trace ("o "); eputs (itoa (cur_text_section->data[ind-1])); eputs ("\n");
i>>=8;
cur_text_section->data[ind++] = i&255;
trace ("o "); eputs (itoa (i&255)); eputs ("\n");
trace ("o "); eputs (itoa (cur_text_section->data[ind-1])); eputs ("\n");
i>>=8;
cur_text_section->data[ind++] = i;
trace ("o "); eputs (itoa (i)); eputs ("\n");
trace ("o "); eputs (itoa (cur_text_section->data[ind-1])); eputs ("\n");
}
static uint32_t stuff_const(uint32_t op, uint32_t c)

298
boot.sh Executable file
View File

@ -0,0 +1,298 @@
#! /bin/sh
set -e
if [ "$V" = 1 -o "$V" = 2 ]; then
set -x
fi
if [ "$TCC" = ./mes-tcc ]; then
PROGRAM_PREFIX=${PROGRAM_PREFIX-boot0-}
elif [ "$TCC" = ./boot0-tcc ]; then
PROGRAM_PREFIX=${PROGRAM_PREFIX-boot1-}
elif [ "$TCC" = ./boot1-tcc ]; then
PROGRAM_PREFIX=${PROGRAM_PREFIX-boot2-}
elif [ "$TCC" = ./boot2-tcc ]; then
PROGRAM_PREFIX=${PROGRAM_PREFIX-boot3-}
elif [ "$TCC" = ./boot3-tcc ]; then
PROGRAM_PREFIX=${PROGRAM_PREFIX-boot4-}
fi
unset C_INCLUDE_PATH LIBRARY_PATH
PREFIX=${PREFIX-usr}
mkdir -p $PREFIX
ABSPREFIX=$(cd $PREFIX && pwd && (cd - 2>&1 >/dev/null)) # FIXME: Gash
GUIX=${GUIX-$(command -v guix||:)}
MES_PREFIX=${MES_PREFIX-../mes}
##MES_PREFIX=${MES_PREFIX-$(dirname $MESCC)/../share/mes}
C_INCLUDE_PATH=${C_INCLUDE_PATH-$MES_PREFIX/include}
MES_SEED=${MES_SEED-../mes-seed}
LIBRARY_PATH=${LIBRARY_PATH-..$MES_SEED}
if [ -z "$interpreter" -a -n "$GUIX" ]; then
interpreter=$($GUIX environment --ad-hoc patchelf -- patchelf --print-interpreter $(guix build --system=i686-linux hello)/bin/hello)
elif [ -x /lib/ld-linux.so.2 ]; then
# legacy non-GuixSD support
interpreter=/lib/ld-linux.so.2
fi
interpreter=${interpreter-interpreter}
if [ "$(basename $SHELL)" = gash ]; then
if [ "$PROGRAM_PREFIX" = "boot0-" ]; then
./$TCC\
-v\
-static\
-o ${PROGRAM_PREFIX}tcc\
-D inline=\
-D BOOTSTRAP=1\
-D HAVE_FLOAT_STUB=1\
-D CONFIG_TCCBOOT=1\
-D CONFIG_USE_LIBGCC=1\
-D TCC_MES_LIBC=1\
-I .\
-I $MES_PREFIX/include\
-D TCC_TARGET_I386\
-D CONFIG_TCCDIR=\"$PREFIX/lib/tcc\"\
-D CONFIG_TCC_CRTPREFIX=\"$PREFIX/lib:"{B}"/lib:.\"\
-D CONFIG_TCC_ELFINTERP=\"$interpreter\"\
-D CONFIG_TCC_LIBPATHS=\"$ABSPREFIX/lib:"{B}"/lib:.\"\
-D CONFIG_TCC_SYSINCLUDEPATHS=\"$MES_PREFIX/include:$PREFIX/include:"{B}"/include\"\
-D TCC_LIBGCC=\"$ABSPREFIX/lib/libc.a\"\
-D ONE_SOURCE=yes\
-D CONFIG_TCC_LIBTCC1=1\
-D CONFIG_TCC_STATIC=1\
-D TCC_TARGET_I386=1\
-L .\
-L $MES_SEED\
tcc.c\
-ltcc1
elif [ "$PROGRAM_PREFIX" = "boot1-" ]; then
./$TCC\
-v\
-static\
-o ${PROGRAM_PREFIX}tcc\
-D BOOTSTRAP=1\
-D HAVE_BITFIELD=1\
-D HAVE_FLOAT_STUB=1\
-D CONFIG_TCCBOOT=1\
-D CONFIG_USE_LIBGCC=1\
-D TCC_MES_LIBC=1\
-I .\
-I $MES_PREFIX/include\
-D TCC_TARGET_I386\
-D CONFIG_TCCDIR=\"$PREFIX/lib/tcc\"\
-D CONFIG_TCC_CRTPREFIX=\"$PREFIX/lib:"{B}"/lib:.\"\
-D CONFIG_TCC_ELFINTERP=\"$interpreter\"\
-D CONFIG_TCC_LIBPATHS=\"$ABSPREFIX/lib:"{B}"/lib:.\"\
-D CONFIG_TCC_SYSINCLUDEPATHS=\"$MES_PREFIX/include:$PREFIX/include:"{B}"/include\"\
-D TCC_LIBGCC=\"$ABSPREFIX/lib/libc.a\"\
-D ONE_SOURCE=yes\
-D CONFIG_TCC_LIBTCC1=1\
-D CONFIG_TCC_STATIC=1\
-D TCC_TARGET_I386=1\
-L .\
-L $MES_SEED\
tcc.c\
-ltcc1
elif [ "$PROGRAM_PREFIX" = "boot2-" ]; then
./$TCC\
-v\
-static\
-o ${PROGRAM_PREFIX}tcc\
-D BOOTSTRAP=1\
-D HAVE_BITFIELD=1\
-D HAVE_FLOAT_STUB=1\
-D HAVE_LONG_LONG=1\
-D CONFIG_TCCBOOT=1\
-D CONFIG_USE_LIBGCC=1\
-D TCC_MES_LIBC=1\
-I .\
-I $MES_PREFIX/include\
-D TCC_TARGET_I386\
-D CONFIG_TCCDIR=\"$PREFIX/lib/tcc\"\
-D CONFIG_TCC_CRTPREFIX=\"$PREFIX/lib:"{B}"/lib:.\"\
-D CONFIG_TCC_ELFINTERP=\"$interpreter\"\
-D CONFIG_TCC_LIBPATHS=\"$ABSPREFIX/lib:"{B}"/lib:.\"\
-D CONFIG_TCC_SYSINCLUDEPATHS=\"$MES_PREFIX/include:$PREFIX/include:"{B}"/include\"\
-D TCC_LIBGCC=\"$ABSPREFIX/lib/libc.a\"\
-D ONE_SOURCE=yes\
-D CONFIG_TCC_LIBTCC1=1\
-D CONFIG_TCC_STATIC=1\
-D TCC_TARGET_I386=1\
-L .\
-L $MES_SEED\
tcc.c\
-ltcc1
elif [ "$PROGRAM_PREFIX" = "boot3-" ]; then
./$TCC\
-v\
-static\
-o ${PROGRAM_PREFIX}tcc\
-D BOOTSTRAP=1\
-D HAVE_FLOAT=1\
-D HAVE_BITFIELD=1\
-D HAVE_LONG_LONG=1\
-D CONFIG_TCCBOOT=1\
-D CONFIG_USE_LIBGCC=1\
-D TCC_MES_LIBC=1\
-I .\
-I $MES_PREFIX/include\
-D TCC_TARGET_I386\
-D CONFIG_TCCDIR=\"$PREFIX/lib/tcc\"\
-D CONFIG_TCC_CRTPREFIX=\"$PREFIX/lib:"{B}"/lib:.\"\
-D CONFIG_TCC_ELFINTERP=\"$interpreter\"\
-D CONFIG_TCC_LIBPATHS=\"$ABSPREFIX/lib:"{B}"/lib:.\"\
-D CONFIG_TCC_SYSINCLUDEPATHS=\"$MES_PREFIX/include:$PREFIX/include:"{B}"/include\"\
-D TCC_LIBGCC=\"$ABSPREFIX/lib/libc.a\"\
-D ONE_SOURCE=yes\
-D CONFIG_TCC_LIBTCC1=1\
-D CONFIG_TCC_STATIC=1\
-D TCC_TARGET_I386=1\
-L .\
-L $MES_SEED\
tcc.c
elif [ "$PROGRAM_PREFIX" = "boot4-" ]; then
./$TCC\
-v\
-static\
-o ${PROGRAM_PREFIX}tcc\
-D BOOTSTRAP=1\
-D HAVE_FLOAT=1\
-D HAVE_BITFIELD=1\
-D HAVE_LONG_LONG=1\
-D CONFIG_TCCBOOT=1\
-D CONFIG_USE_LIBGCC=1\
-D TCC_MES_LIBC=1\
-I .\
-I $MES_PREFIX/include\
-D TCC_TARGET_I386\
-D CONFIG_TCCDIR=\"$PREFIX/lib/tcc\"\
-D CONFIG_TCC_CRTPREFIX=\"$PREFIX/lib:"{B}"/lib:.\"\
-D CONFIG_TCC_ELFINTERP=\"$interpreter\"\
-D CONFIG_TCC_LIBPATHS=\"$ABSPREFIX/lib:"{B}"/lib:.\"\
-D CONFIG_TCC_SYSINCLUDEPATHS=\"$MES_PREFIX/include:$PREFIX/include:"{B}"/include\"\
-D TCC_LIBGCC=\"$ABSPREFIX/lib/libc.a\"\
-D ONE_SOURCE=yes\
-D CONFIG_TCC_LIBTCC1=1\
-D CONFIG_TCC_STATIC=1\
-D TCC_TARGET_I386=1\
-L .\
-L $MES_SEED\
tcc.c
fi
else
if [ "$PROGRAM_PREFIX" = "boot0-" ]; then
BOOT_CPPFLAGS=${BOOT_CPPFLAGS-"
-D inline=
-D BOOTSTRAP=1
-D HAVE_FLOAT_STUB=1
-D CONFIG_TCCBOOT=1
-D CONFIG_USE_LIBGCC=1
-D TCC_MES_LIBC=1
"}
LIBTCC1=-ltcc1
elif [ "$PROGRAM_PREFIX" = "boot1-" ]; then
BOOT_CPPFLAGS=${BOOT_CPPFLAGS-"
-D BOOTSTRAP=1
-D HAVE_BITFIELD=1
-D HAVE_FLOAT_STUB=1
-D CONFIG_TCCBOOT=1
-D CONFIG_USE_LIBGCC=1
-D TCC_MES_LIBC=1
"}
LIBTCC1=-ltcc1
elif [ "$PROGRAM_PREFIX" = "boot2-" ]; then
BOOT_CPPFLAGS=${BOOT_CPPFLAGS-"
-D BOOTSTRAP=1
-D HAVE_BITFIELD=1
-D HAVE_FLOAT_STUB=1
-D HAVE_LONG_LONG=1
-D CONFIG_TCCBOOT=1
-D CONFIG_USE_LIBGCC=1
-D TCC_MES_LIBC=1
"}
LIBTCC1=-ltcc1
elif [ "$PROGRAM_PREFIX" = "boot3-" ]; then
BOOT_CPPFLAGS=${BOOT_CPPFLAGS-"
-D BOOTSTRAP=1
-D HAVE_FLOAT=1
-D HAVE_BITFIELD=1
-D HAVE_LONG_LONG=1
-D CONFIG_TCCBOOT=1
-D CONFIG_USE_LIBGCC=1
-D TCC_MES_LIBC=1
"}
elif [ "$PROGRAM_PREFIX" = "boot4-" ]; then
BOOT_CPPFLAGS=${BOOT_CPPFLAGS-"
-D BOOTSTRAP=1
-D HAVE_FLOAT=1
-D HAVE_BITFIELD=1
-D HAVE_LONG_LONG=1
-D CONFIG_TCCBOOT=1
-D CONFIG_USE_LIBGCC=1
-D TCC_MES_LIBC=1
"}
fi
echo $TCC\
-v\
-static\
-o ${PROGRAM_PREFIX}tcc\
$BOOT_CPPFLAGS\
-I .\
-I $MES_PREFIX/include\
-D TCC_TARGET_I386\
-D CONFIG_TCCDIR=\"$PREFIX/lib/tcc\"\
-D CONFIG_TCC_CRTPREFIX=\"$PREFIX/lib:"{B}"/lib:.\"\
-D CONFIG_TCC_ELFINTERP=\"$interpreter\"\
-D CONFIG_TCC_LIBPATHS=\"$ABSPREFIX/lib:"{B}"/lib:.\"\
-D CONFIG_TCC_SYSINCLUDEPATHS=\"$MES_PREFIX/include:$PREFIX/include:"{B}"/include\"\
-D TCC_LIBGCC=\"$ABSPREFIX/lib/libc.a\"\
-D ONE_SOURCE=yes\
-D CONFIG_TCC_LIBTCC1=1\
-D CONFIG_TCC_STATIC=1\
-D TCC_TARGET_I386=1\
-L .\
-L $MES_SEED\
tcc.c\
$LIBTCC1
./$TCC\
-v\
-static\
-o ${PROGRAM_PREFIX}tcc\
$BOOT_CPPFLAGS\
-I .\
-I $MES_PREFIX/include\
-D TCC_TARGET_I386\
-D CONFIG_TCCDIR=\"$PREFIX/lib/tcc\"\
-D CONFIG_TCC_CRTPREFIX=\"$PREFIX/lib:"{B}"/lib:.\"\
-D CONFIG_TCC_ELFINTERP=\"$interpreter\"\
-D CONFIG_TCC_LIBPATHS=\"$ABSPREFIX/lib:"{B}"/lib:.\"\
-D CONFIG_TCC_SYSINCLUDEPATHS=\"$MES_PREFIX/include:$PREFIX/include:"{B}"/include\"\
-D TCC_LIBGCC=\"$ABSPREFIX/lib/libc.a\"\
-D ONE_SOURCE=yes\
-D CONFIG_TCC_LIBTCC1=1\
-D CONFIG_TCC_STATIC=1\
-D TCC_TARGET_I386=1\
-L .\
-L $MES_SEED\
tcc.c\
$LIBTCC1
fi
for i in 1 i n; do
rm -f crt$i.o;
./${PROGRAM_PREFIX}tcc -c $MES_PREFIX/lib/linux/x86-mes-gcc/crt$i.c
done
rm -f libtcc1.a
./${PROGRAM_PREFIX}tcc -c -g -D TCC_TARGET_I386=1 -o libtcc1.o lib/libtcc1.c
./${PROGRAM_PREFIX}tcc -ar rc libtcc1.a libtcc1.o
mkdir -p $PREFIX/lib/tcc
cp libtcc1.a $PREFIX/lib/tcc
cp -f libtcc1.a $PREFIX/lib/tcc
echo "boot.sh: done"

66
bootstrap.sh Executable file
View File

@ -0,0 +1,66 @@
#! /bin/sh
set -e
if [ "$V" = 1 -o "$V" = 2 ]; then
set -x
fi
prefix=${prefix-/usr/local}
MES_PREFIX=${MES_PREFIX-mes}
MES_SEED=${MES_SEED-../mes-seed}
interpreter=${interpreter-interpreter}
cp $MES_SEED/linux/x86-mes-gcc/crt1.o crt1.o
cp $MES_SEED/linux/x86-mes-gcc/crti.o crti.o
cp $MES_SEED/linux/x86-mes-gcc/crtn.o crtn.o
mescc=$(command -v mescc)
sh $mescc --help
[ "$V" = 1 ] && echo "sh $mescc -S ... tcc.c"
sh $mescc\
-v\
-S\
-o tcc.S\
-D ONE_SOURCE=1\
-I .\
-I $MES_PREFIX/lib\
-I $MES_PREFIX/include\
-D inline=\
-D CONFIG_TCCDIR=\"$prefix/lib/tcc\"\
-D CONFIG_TCC_CRTPREFIX=\"$prefix/lib:"{B}"/lib:.\"\
-D CONFIG_TCC_ELFINTERP=\"$interpreter\"\
-D CONFIG_TCC_LIBPATHS=\"$prefix/lib:"{B}"/lib:.\"\
-D CONFIG_TCC_SYSINCLUDEPATHS=\"$MES_PREFIX/include:$prefix/include:"{B}"/include\"\
-D TCC_LIBGCC=\"$prefix/lib/libc.a\"\
-D BOOTSTRAP=1\
-D CONFIG_TCCBOOT=1\
-D CONFIG_TCC_STATIC=1\
-D CONFIG_USE_LIBGCC=1\
-D TCC_MES_LIBC=1\
-D TCC_TARGET_I386=1\
tcc.c
sh $mescc -v -g -o mes-tcc -L $MES_SEED -l c+tcc tcc.S $MES_SEED/x86-$MES_PREFIX/libc+tcc.o
rm -f libc.a
cp -f $MES_SEED/x86-mes-gcc/libc+gnu.o .
./mes-tcc -ar rc libc.a libc+gnu.o
rm -f libtcc1.a
cp -f $MES_SEED/x86-mes-gcc/libtcc1.o .
./mes-tcc -ar rc libtcc1.a libtcc1.o
if [ "$(basename $SHELL)" = gash ]; then
echo "bootstrap.sh: run boot.sh sequence manually"
else
TCC=./mes-tcc sh boot.sh
TCC=./boot0-tcc sh boot.sh
TCC=./boot1-tcc sh boot.sh
TCC=./boot2-tcc sh boot.sh
TCC=./boot3-tcc sh boot.sh
cmp boot3-tcc boot4-tcc
cp -f boot4-tcc tcc
echo "bootstrap.sh: done"
fi

20
build-gcc.sh Executable file
View File

@ -0,0 +1,20 @@
#! /bin/sh
set -ex
rm -f tcc
GUIX=${GUIX-$(command -v guix||:)}
MES_PREFIX=${MES_PREFIX-../mes}
touch config.mak
make clean
rm -f crt*.o
crt1=$(gcc --print-file-name=crt1.o)
#crtdir=$(dirname $crt1)
#crti=$(gcc --print-file-name=crti.o)
#crtn=$(gcc --print-file-name=crtn.o)
unset ONE_SOURCE
./configure --tccdir=$PWD --crtprefix=$crtdir --extra-cflags="-DHAVE_FLOAT=1 -DHAVE_BITFIELD=1"
make ETAGS
make PROGRAM_PREFIX=gcc- gcc-tcc
make libtcc1.a

62
build-x86.sh Executable file
View File

@ -0,0 +1,62 @@
#! /bin/sh
set -ex
rm -f i686-unknown-linux-gnu-tcc
# crt1=$(i686-unknown-linux-gnu-gcc --print-file-name=crt1.o)
# crtdir=$(dirname $crt1)
unset C_INCLUDE_PATH LIBRARY_PATH
PREFIX=${PREFIX-usr}
GUIX=${GUIX-$(command -v guix||:)}
MES_PREFIX=${MES_PREFIX-../mes}
MES_PREFIX=${MES_PREFIX-${MESCC%/*}/../share/mes}
MES_SEED=${MES_SEED-../mes-seed}
cp $MES_SEED/x86-mes-gcc/crt1.o crt1.o
cp $MES_SEED/x86-mes-gcc/crti.o crti.o
cp $MES_SEED/x86-mes-gcc/crtn.o crtn.o
CC=${CC-i686-unknown-linux-gnu-gcc}
CFLAGS="
-nostdinc
-nostdlib
-fno-builtin
--include=$MES_PREFIX/lib/linux/x86-mes-gcc/crt1.c
--include=$MES_PREFIX/lib/libc+tcc.c
--include=$MES_PREFIX/lib/libtcc1.c
-Wl,-Ttext-segment=0x1000000
"
if [ -z "$interpreter" -a -n "$GUIX" ]; then
interpreter=$($GUIX environment --ad-hoc patchelf -- patchelf --print-interpreter $(guix build --system=i686-linux hello)/bin/hello)
elif [ -x /lib/ld-linux.so.2 ]; then
# legacy non-GuixSD support
interpreter=/lib/ld-linux.so.2
fi
interpreter=${interpreter-interpreter}
export interpreter
mkdir -p $PREFIX/lib
ABSPREFIX=$(cd $PREFIX && pwd)
cp $MES_SEED/x86-mes-gcc/libc+tcc.o $ABSPREFIX/lib
cp $MES_SEED/x86-mes-gcc/libtcc1.o $ABSPREFIX/lib
$CC -g -o i686-unknown-linux-gnu-tcc\
$CFLAGS\
-I.\
-I $MES_PREFIX/lib\
-I $MES_PREFIX/include\
-D 'CONFIG_TCCDIR="'$PREFIX'/lib/tcc"'\
-D 'CONFIG_TCC_CRTPREFIX="'$PREFIX'/lib:{B}/lib:."'\
-D 'CONFIG_TCC_ELFINTERP="'$interpreter'"'\
-D 'CONFIG_TCC_LIBPATHS="'$ABSPREFIX'/lib:{B}/lib:."'\
-D 'CONFIG_TCC_SYSINCLUDEPATHS="'$MES_PREFIX'/include:'$PREFIX'/include:{B}/include"'\
-D CONFIG_USE_LIBGCC=1\
-D 'TCC_LIBGCC="'$ABSPREFIX'/lib/libc.a"'\
-D BOOTSTRAP=1\
-D CONFIG_TCCBOOT=1\
-D CONFIG_TCC_STATIC=1\
-D CONFIG_USE_LIBGCC=1\
-D ONE_SOURCE=1\
-D TCC_MES_LIBC=1\
-D TCC_TARGET_I386=1\
tcc.c

108
build.sh Executable file
View File

@ -0,0 +1,108 @@
#! /bin/sh
set -e
export BUILD_DEBUG
export MES_DEBUG
export MES_PREFIX
export PREFIX
export MES_SEED
export interpreter
if [ -n "$BUILD_DEBUG" ]; then
set -x
MESCCFLAGS="$MESCCFLAGS -v"
fi
rm -f tcc.E tcc.hex2 tcc.M1 tcc.m1 mes-tcc boot?-tcc
unset C_INCLUDE_PATH LIBRARY_PATH
PREFIX=${PREFIX-usr}
GUIX=${GUIX-$(command -v guix||:)}
CC=${MESCC-mescc}
MES=${MES-../mes/src/mes}
MESCC=${MESCC-mescc}
HEX2=${HEX2-hex2}
M1=${M1-M1}
BLOOD_ELF=${BLOOD_ELF-blood-elf}
MES_PREFIX=${MES_PREFIX-${MESCC%/*}/../share/mes}
#MES_PREFIX=${MES_PREFIX-../mes}
MES_SEED=${MES_SEED-../mes-seed}
cp $MES_SEED/x86-mes-gcc/crt1.o crt1.o
cp $MES_SEED/x86-mes-gcc/crti.o crti.o
cp $MES_SEED/x86-mes-gcc/crtn.o crtn.o
if [ -z "$interpreter" -a -n "$GUIX" ]; then
interpreter=$($GUIX environment --ad-hoc patchelf -- patchelf --print-interpreter $(guix build --system=i686-linux hello)/bin/hello)
elif [ -x /lib/ld-linux.so.2 ]; then
# legacy non-GuixSD support
interpreter=/lib/ld-linux.so.2
fi
interpreter=${interpreter-interpreter}
export interpreter
mkdir -p $PREFIX/lib
ABSPREFIX=$(cd $PREFIX && pwd)
cp $MES_SEED/x86-mes-gcc/libc+tcc.o $ABSPREFIX/lib
if [ -n "$ONE_SOURCE" ]; then
sh cc.sh tcc
files="tcc.S"
else
sh cc.sh tccpp
sh cc.sh tccgen
sh cc.sh tccelf
sh cc.sh tccrun
sh cc.sh i386-gen
sh cc.sh i386-link
sh cc.sh i386-asm
sh cc.sh tccasm
sh cc.sh libtcc
sh cc.sh tcc
files="
tccpp.S
tccgen.S
tccelf.S
tccrun.S
i386-gen.S
i386-link.S
i386-asm.S
tccasm.S
libtcc.S
tcc.S
"
fi
$MESCC\
$MESCCFLAGS\
-g\
-o mes-tcc\
-L $MES_SEED\
-l c+tcc\
$files\
$MES_SEED/x86-mes/libc+tcc.o
rm -f libc.a
if false; then
# ../mes/lib/linux-gcc.c:33: error: bad operand with opcode 'mov'
# it works with bootx-tcc
./mes-tcc -c -I $MES_PREFIX/include -I $MES_PREFIX/lib $MES_PREFIX/lib/libc+gnu.c
./mes-tcc -ar rc libc.a libc+gnu.o
else
##./mes-tcc -ar rc libc.a $MES_SEED/x86-mes-gcc/libc+gnu.o
cp -f $MES_SEED/x86-mes-gcc/libc+gnu.o .
./mes-tcc -ar rc libc.a libc+gnu.o
fi
rm -f libtcc1.a
cp -f $MES_SEED/x86-mes-gcc/libtcc1.o .
./mes-tcc -ar rc libtcc1.a libtcc1.o
sh boot.sh
TCC=./boot0-tcc sh boot.sh
TCC=./boot1-tcc sh boot.sh
TCC=./boot2-tcc sh boot.sh
TCC=./boot3-tcc sh boot.sh
ln -f boot4-tcc tcc

78
cc.sh Executable file
View File

@ -0,0 +1,78 @@
#! /bin/sh
set -e
if [ -n "$BUILD_DEBUG" ]; then
set -x
MESCCFLAGS="$MESCCFLAGS -v"
fi
t=$1
rm -f $t.E $t.M1 $t.m1
GUIX=${GUIX-$(command -v guix||:)}
CC=${MESCC-mescc}
MES=${MES-../mes/src/mes}
MESCC=${MESCC-mescc}
CFLAGS=${CFLAGS-}
MES_PREFIX=${MES_PREFIX-${MESCC%/*}}
ABSPREFIX=$(cd $PREFIX && pwd)
if [ -z "$interpreter" -a -n "$GUIX" ]; then
interpreter=$($GUIX environment --ad-hoc patchelf -- patchelf --print-interpreter $(guix build --system=i686-linux hello)/bin/hello)
elif [ -x /lib/ld-linux.so.2 ]; then
# legacy non-GuixSD support
interpreter=/lib/ld-linux.so.2
fi
ulimit -s 17030
if [ -n "$ONE_SOURCE" ]; then
CFLAGS="$CFLAGS -D ONE_SOURCE=$ONE_SOURCE"
fi
if [ -n "$PREPROCESS" ]; then
time sh $MESCC $MESCCFLAGS -E -o $t.E\
$CFLAGS\
-I .\
-I $MES_PREFIX/lib\
-I $MES_PREFIX/include\
-D inline=\
-D 'CONFIG_TCCDIR="'$PREFIX'/lib/tcc"'\
-D 'CONFIG_TCC_CRTPREFIX="'$PREFIX'/lib:{B}/lib:."'\
-D 'CONFIG_TCC_ELFINTERP="'$interpreter'"'\
-D 'CONFIG_TCC_LIBPATHS="'$ABSPREFIX'/lib:{B}/lib:."'\
-D 'CONFIG_TCC_SYSINCLUDEPATHS="'$MES_PREFIX'/include:'$PREFIX'/include:{B}/include"'\
-D 'TCC_LIBGCC="'$ABSPREFIX'/lib/libc.a"'\
-D BOOTSTRAP=1\
-D CONFIG_TCCBOOT=1\
-D CONFIG_TCC_STATIC=1\
-D CONFIG_USE_LIBGCC=1\
-D TCC_MES_LIBC=1\
-D TCC_TARGET_I386=1\
$t.c
time sh $MESCC $MESCCFLAGS -S -o $t.M1 $t.E
else
time sh $MESCC $MESCCFLAGS -S -o $t.M1\
$CFLAGS\
-I .\
-I $MES_PREFIX/lib\
-I $MES_PREFIX/include\
-D inline=\
-D 'CONFIG_TCCDIR="'$PREFIX'/lib/tcc"'\
-D 'CONFIG_TCC_CRTPREFIX="'$PREFIX'/lib:{B}/lib:."'\
-D 'CONFIG_TCC_ELFINTERP="'$interpreter'"'\
-D 'CONFIG_TCC_LIBPATHS="'$ABSPREFIX'/lib:{B}/lib:."'\
-D 'CONFIG_TCC_SYSINCLUDEPATHS="'$MES_PREFIX'/include:'$PREFIX'/include:{B}/include"'\
-D CONFIG_USE_LIBGCC=1\
-D 'TCC_LIBGCC="'$ABSPREFIX'/lib/libc.a"'\
-D BOOTSTRAP=1\
-D CONFIG_TCCBOOT=1\
-D CONFIG_TCC_STATIC=1\
-D CONFIG_USE_LIBGCC=1\
-D TCC_MES_LIBC=1\
-D TCC_TARGET_I386=1\
$t.c
fi
tr -d '\r' < $t.M1 > $t.S

334
check.sh Executable file
View File

@ -0,0 +1,334 @@
#! /bin/sh
###MESCC=${MESCC-mescc}
MES_ARENA=${MES_ARENA-100000000}
MES_MAX_ARENA=${MES_MAX_ARENA-100000000}
MES_STACK=${MES_STACK-10000000}
export MES_ARENA MES_MAX_ARENA MES_STACK
MES=${MES-mes}
MESCC=${MESCC-mescc}
MES_PREFIX=${MES_PREFIX-../mes}
tests="
t
00-exit-0
01-return-0
02-return-1
03-call
04-call-0
05-call-1
06-call-!1
06-!call-1
06-call-2
06-call-string
06-call-variable
06-return-void
07-include
08-assign
08-assign-negative
08-assign-global
10-if-0
11-if-1
12-if-==
13-if-!=
14-if-goto
15-if-!f
16-if-t
17-compare-ge
17-compare-gt
17-compare-le
17-compare-lt
17-compare-unsigned-ge
17-compare-unsigned-gt
17-compare-unsigned-le
17-compare-unsigned-lt
17-compare-and
17-compare-or
17-compare-and-or
17-compare-assign
17-compare-call
18-assign-shadow
20-while
21-char[]-simple
21-char[]
22-while-char[]
23-global-pointer-init-null
23-global-pointer-init
23-global-pointer-ref
23-global-pointer-pointer-ref
23-pointer-sub
23-pointer
30-strlen
31-oputs
32-call-wrap
32-compare
33-and-or
34-pre-post
35-compare-char
36-compare-arithmetic
37-compare-assign
38-compare-call-2
38-compare-call-3
38-compare-call
40-if-else
41-?
42-goto-label
43-for-do-while
44-switch
44-switch-fallthrough
44-switch-body-fallthrough
45-void-call
46-function-static
47-function-expression
48-global-static
50-assert
51-pointer-sub
51-itoa
51-strcmp
51-strncmp
53-strcpy
54-argc
54-argv
55-char-array
60-math
61-array
62-array
63-struct
63-struct-pointer
63-struct-local
63-struct-function
63-struct-assign
63-struct-array
63-struct-array-assign
63-struct-array-compare
63-struct-cell
64-make-cell
65-read
66-local-char-array
70-strchr
70-stdarg
70-printf-hello
70-printf-simple
70-printf
71-struct-array
72-typedef-struct-def
73-union-hello
73-union
74-multi-line-string
75-struct-union
76-pointer-arithmetic-pp
76-pointer-arithmetic
77-pointer-assign
78-union-struct
79-int-array-simple
79-int-array
7a-struct-char-array
7b-struct-int-array-hello
7b-struct-int-array-pointer
7b-struct-int-array
7c-dynarray
7d-cast-char
7e-struct-array-access
7f-struct-pointer-arithmetic
7g-struct-byte-word-field
7h-struct-assign
7i-struct-struct-simple
7i-struct-struct
7j-strtoull
7k-empty-for
7k-for-each-elem-simple
7k-for-each-elem
7l-struct-any-size-array-simple
7l-struct-any-size-array
7m-struct-char-array-assign
7n-struct-struct-array
7o-struct-pre-post-simple
7o-struct-pre-post
7p-struct-cast
7q-bit-field-simple
7q-bit-field
7r-sign-extend
7s-struct-short
7s-unsigned-compare
7t-function-destruct
7u-double
7u-long-long
7u-?-expression
7u-call-?
7u-inc-byte-word
7u-struct-func
7u-struct-size10
7u-vstack
80-setjmp
81-qsort
81-qsort-dupes
82-define
83-heterogenoous-init
84-struct-field-list
85-sizeof
86-strncpy
87-sscanf
88-strrchr
90-strspn
90-strpbrk
91-fseek
92-stat
93-fread-fwrite
94-unsetenv
95-signal
96-strto
97-fopen
98-fopen
99-readdir
"
broken="
t
00-exit-0
54-argc
66-local-char-array
70-strchr
91-fseek
99-readdir
"
if [ ! -x ./i686-unknown-linux-gnu-tcc ]; then
broken="$broken
02-return-1
05-call-1
"
fi
expect=$(echo $broken | wc -w)
mkdir -p scaffold/tests
set +e
pass=0
fail=0
total=0
for t in $tests; do
sh test.sh "$MES_PREFIX/scaffold/tests/$t" &> "scaffold/tests/$t".log
r=$?
total=$((total+1))
if [ $r = 0 ]; then
echo $t: [OK]
pass=$((pass+1))
else
echo $t: [FAIL]
fail=$((fail+1))
fi
done
tests="
00_assignment
01_comment
02_printf
03_struct
04_for
05_array
06_case
07_function
08_while
09_do_while
10_pointer
11_precedence
12_hashdefine
13_integer_literals
14_if
15_recursion
16_nesting
17_enum
18_include
19_pointer_arithmetic
20_pointer_comparison
21_char_array
22_floating_point
23_type_coercion
24_math_library
25_quicksort
26_character_constants
27_sizeof
28_strings
29_array_address
30_hanoi
31_args
32_led
33_ternary_op
34_array_assignment
35_sizeof
36_array_initialisers
37_sprintf
38_multiple_array_index
39_typedef
40_stdio
41_hashif
42_function_pointer
43_void_param
44_scoped_declarations
45_empty_for
47_switch_return
48_nested_break
49_bracket_evaluation
50_logical_second_arg
51_static
52_unnamed_enum
54_goto
55_lshift_type
"
broken="$broken
22_floating_point
23_type_coercion
24_math_library
49_bracket_evaluation
55_lshift_type
"
#22_floating_point ; float
#23_type_coercion ; float
#24_math_library ; float
#27_sizeof ; float
#34_array_assignment ; fails with GCC
#37_sprintf ; integer formatting unsupported
#49_bracket_evaluation ; float
mkdir -p scaffold/tinycc
expect=$(echo $broken | wc -w)
for t in $tests; do
if [ ! -f tests/tests2/"$t.c" ]; then
echo ' [SKIP]'
continue;
fi
sh test.sh tests/tests2/"$t" &> tests/tests2/"$t".log
r=$?
total=$((total+1))
if [ $r = 0 ]; then
echo $t: [OK]
pass=$((pass+1))
else
echo $t: [FAIL]
fail=$((fail+1))
fi
done
[ $expect != 0 ] && echo "expect: $expect"
[ $fail != 0 ] && echo "failed: $fail"
echo "passed: $pass"
[ $fail -lt $expect ] && echo "solved: $(($expect - $fail))"
echo "total: $total"
if [ $fail != 0 -a $fail -gt $expect ]; then
echo FAILED: $fail/$total
exit 1
elif [ $fail != 0 ]; then
echo PASS: $pass/$total
else
echo PASS: $total
fi

15
compile.sh Executable file
View File

@ -0,0 +1,15 @@
#! /bin/sh
set -ex
rm -f *.i686-unknown-linux-gnu-o *.mes-o
rm -f 1 2 1.elf 2.elf 1.a 2.a
# trivial object
./tcc -c -I ../mes/include ../mes/scaffold/main.c 2>/dev/null
./i686-unknown-linux-gnu-tcc -o main.i686-unknown-linux-gnu-o -c -I ../mes/include ../mes/scaffold/main.c 2> 1
set +e
./mes-tcc -o main.mes-o -c -I ../mes/include ../mes/scaffold/main.c &> 2
diff -y 1 2
readelf -a main.i686-unknown-linux-gnu-o > 1.elf
readelf -a main.mes-o > 2.elf
diff -y 1.elf 2.elf || :

21
d Executable file
View File

@ -0,0 +1,21 @@
#! /bin/sh
set -ex
rm -f *.o *.a *.E *.hex2 *.mesc-o *.i686-unknown-linux-gnu-o *.M1
rm -f 1 2 1.elf 2.elf
# trivial object
set +e
./tcc -c -I ../mes/mlibc/include ../mes/scaffold/main.c 2>/dev/null
./i686-unknown-linux-gnu-tcc -o main.i686-unknown-linux-gnu-o -c -I ../mes/mlibc/include ../mes/scaffold/main.c 2> 1
./tcc.mes -o main.mesc-o -c -I ../mes/mlibc/include ../mes/scaffold/main.c &> 2
diff -y 1 2
readelf -a main.i686-unknown-linux-gnu-o > 1.elf
readelf -a main.mesc-o > 2.elf
diff -y 1.elf 2.elf
# trivial bin
./tcc ../mes/scaffold/main.c
./i686-unknown-linux-gnu-tcc -o a.i686-unknown-linux-gnu-out -I ../mes/mlibc/include ../mes/scaffold/main.c 2> 1.a
./tcc.mes -o a.mes-out -I ../mes/mlibc/include ../mes/scaffold/main.c 2> 2.a
diff -y 1.a 2.a

62
doit Executable file
View File

@ -0,0 +1,62 @@
#! /bin/sh
set -ex
export BLOOD_ELF
export BUILD_DEBUG
export GUILE_LOAD_PATH
export HEX2
export M1
export MES
export MESCC
export MES_DEBUG
export MES_PREFIX
export ONE_SOURCE
export PREFIX
export PREPROCESS
export TINYCC_SEED
PREFIX=usr
HEX2=../mescc-tools/bin/hex2
M1=../mescc-tools/bin/M1
BLOOD_ELF=../mescc-tools/bin/blood-elf
MES=${MES-../mes/src/mes}
MES_ARENA=70000000
MES_MAX_ARENA=70000000
export MES_ARENA MES_MAX_ARENA
MES=guile
#MES=${MES-../mes/src/mes.gcc}
#MES=${MES-../mes/src/mes.mlibc-gcc}
MESCC=${MESCC-../mes/pre-inst-env mescc}
#GUILE_LOAD_PATH=/home/janneke/src/nyacc/module:$GUILE_LOAD_PATH
GUILE_LOAD_PATH=nyacc
MES_DEBUG=2
MES_PREFIX=${MES_PREFIX-../mes}
TINYCC_SEED=${TINYCC_SEED-../tinycc-seed}
rm -f mes
ln -sf $MES_PREFIX mes
if [ -z "$interpreter" -a -n "$GUIX" ]; then
interpreter=$($GUIX environment --ad-hoc patchelf -- patchelf --print-interpreter $(guix build --system=i686-linux hello)/bin/hello)
elif [ -x /lib/ld-linux.so.2 ]; then
# legacy non-GuixSD support
interpreter=/lib/ld-linux.so.2
fi
interpreter=${interpreter-interpreter}
export interpreter
sh build-gcc.sh
PREPROCESS=1
ONE_SOURCE=1
sh build-x86.sh
sh build.sh
sh compile.sh
sh link.sh ||:
sh check.sh
rm -rf usr
sh install.sh

View File

@ -19,7 +19,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _TCC_H
#include "tcc.h"
#endif
#define MAX_OPERANDS 3
@ -1597,6 +1599,7 @@ ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands,
ASMOperand *op;
int i, reg;
trace_enter ("asm_gen_code");
/* Strictly speaking %Xbp and %Xsp should be included in the
call-preserved registers, but currently it doesn't matter. */
#ifdef TCC_TARGET_X86_64
@ -1690,6 +1693,7 @@ ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands,
}
}
}
trace_exit ("asm_gen_code");
}
ST_FUNC void asm_clobber(uint8_t *clobber_regs, const char *str)

View File

@ -74,7 +74,9 @@ enum {
/******************************************************/
#else /* ! TARGET_DEFS_ONLY */
/******************************************************/
#ifndef _TCC_H
#include "tcc.h"
#endif
/* define to 1/0 to [not] have EBX as 4th register */
#define USE_EBX 0
@ -97,6 +99,8 @@ static unsigned long func_bound_ind;
/* XXX: make it faster ? */
ST_FUNC void g(int c)
{
trace_enter ("g");
trace ("gen o c="); eputs (itoa (c)); eputs ("\n");
int ind1;
if (nocode_wanted)
return;
@ -104,7 +108,9 @@ ST_FUNC void g(int c)
if (ind1 > cur_text_section->data_allocated)
section_realloc(cur_text_section, ind1);
cur_text_section->data[ind] = c;
trace ("gen o data="); eputs (itoa (cur_text_section->data[ind])); eputs ("\n");
ind = ind1;
trace_exit ("g");
}
ST_FUNC void o(unsigned int c)
@ -204,6 +210,7 @@ ST_FUNC void load(int r, SValue *sv)
int v, t, ft, fc, fr;
SValue v1;
trace_enter ("load");
#ifdef TCC_TARGET_PE
SValue v2;
sv = pe_getimport(sv, &v2);
@ -275,6 +282,7 @@ ST_FUNC void load(int r, SValue *sv)
o(0xc0 + r + v * 8); /* mov v, r */
}
}
trace_exit ("load");
}
/* store register 'r' in lvalue 'v' */
@ -282,6 +290,7 @@ ST_FUNC void store(int r, SValue *v)
{
int fr, bt, ft, fc;
trace_enter ("store");
#ifdef TCC_TARGET_PE
SValue v2;
v = pe_getimport(v, &v2);
@ -318,6 +327,7 @@ ST_FUNC void store(int r, SValue *v)
} else if (fr != r) {
o(0xc0 + fr + r * 8); /* mov r, fr */
}
trace_exit ("store");
}
static void gadd_sp(int val)
@ -422,6 +432,7 @@ ST_FUNC void gfunc_call(int nb_args)
int size, align, r, args_size, i, func_call;
Sym *func_sym;
trace_enter ("gfunc_call");
args_size = 0;
for(i = 0;i < nb_args; i++) {
if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
@ -501,6 +512,7 @@ ST_FUNC void gfunc_call(int nb_args)
if (args_size && func_call != FUNC_STDCALL && func_call != FUNC_FASTCALLW)
gadd_sp(args_size);
vtop--;
trace_exit ("gfunc_call");
}
#ifdef TCC_TARGET_PE
@ -518,30 +530,40 @@ ST_FUNC void gfunc_prolog(CType *func_type)
Sym *sym;
CType *type;
trace_enter ("gfunc_prolog");
sym = func_type->ref;
func_call = sym->f.func_call;
addr = 8;
loc = 0;
func_vc = 0;
trace ("gfunc_prolog 10\n");
if (func_call >= FUNC_FASTCALL1 && func_call <= FUNC_FASTCALL3) {
trace ("gfunc_prolog 11\n");
fastcall_nb_regs = func_call - FUNC_FASTCALL1 + 1;
fastcall_regs_ptr = fastcall_regs;
} else if (func_call == FUNC_FASTCALLW) {
trace ("gfunc_prolog 15\n");
fastcall_nb_regs = 2;
fastcall_regs_ptr = fastcallw_regs;
} else {
trace ("gfunc_prolog 18\n");
fastcall_nb_regs = 0;
fastcall_regs_ptr = NULL;
}
param_index = 0;
trace ("gfunc_prolog 20\n");
ind += FUNC_PROLOG_SIZE;
trace ("gfunc_prolog 21\n");
func_sub_sp_offset = ind;
trace ("gfunc_prolog 22\n");
/* if the function returns a structure, then add an
implicit pointer parameter */
func_vt = sym->type;
trace ("gfunc_prolog 23\n");
func_var = (sym->f.func_type == FUNC_ELLIPSIS);
trace ("gfunc_prolog 24\n");
#ifdef TCC_TARGET_PE
size = type_size(&func_vt,&align);
if (((func_vt.t & VT_BTYPE) == VT_STRUCT)
@ -549,29 +571,35 @@ ST_FUNC void gfunc_prolog(CType *func_type)
#else
if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
#endif
trace ("gfunc_prolog 25\n");
/* XXX: fastcall case ? */
func_vc = addr;
addr += 4;
param_index++;
}
trace ("gfunc_prolog 30\n");
/* define parameters */
while ((sym = sym->next) != NULL) {
trace ("gfunc_prolog 31 param_index="); eputs (itoa (param_index)); eputs ("\n");
type = &sym->type;
size = type_size(type, &align);
size = (size + 3) & ~3;
#ifdef FUNC_STRUCT_PARAM_AS_PTR
/* structs are passed as pointer */
if ((type->t & VT_BTYPE) == VT_STRUCT) {
trace ("gfunc_prolog 36\n");
size = 4;
}
#endif
if (param_index < fastcall_nb_regs) {
trace ("gfunc_prolog 38\n");
/* save FASTCALL register */
loc -= 4;
o(0x89); /* movl */
gen_modrm(fastcall_regs_ptr[param_index], VT_LOCAL, NULL, loc);
param_addr = loc;
} else {
trace ("gfunc_prolog 39\n");
param_addr = addr;
addr += size;
}
@ -580,6 +608,7 @@ ST_FUNC void gfunc_prolog(CType *func_type)
param_index++;
}
func_ret_sub = 0;
trace ("gfunc_prolog 50\n");
/* pascal type call or fastcall ? */
if (func_call == FUNC_STDCALL || func_call == FUNC_FASTCALLW)
func_ret_sub = addr - 8;
@ -588,15 +617,18 @@ ST_FUNC void gfunc_prolog(CType *func_type)
func_ret_sub = 4;
#endif
trace ("gfunc_prolog 60\n");
#ifdef CONFIG_TCC_BCHECK
/* leave some room for bound checking code */
if (tcc_state->do_bounds_check) {
trace ("gfunc_prolog 61\n");
func_bound_offset = lbounds_section->data_offset;
func_bound_ind = ind;
oad(0xb8, 0); /* lbound section pointer */
oad(0xb8, 0); /* call to function */
}
#endif
trace_exit ("gfunc_prolog");
}
/* generate function epilog */
@ -604,9 +636,11 @@ ST_FUNC void gfunc_epilog(void)
{
addr_t v, saved_ind;
trace ("gfunc_epilog\n");
#ifdef CONFIG_TCC_BCHECK
if (tcc_state->do_bounds_check
&& func_bound_offset != lbounds_section->data_offset) {
trace ("gfunc_epilog 01\n");
addr_t saved_ind;
addr_t *bounds_ptr;
Sym *sym_data;
@ -635,18 +669,22 @@ ST_FUNC void gfunc_epilog(void)
}
#endif
trace ("gfunc_epilog 20\n");
/* align local size to word & save local variables */
v = (-loc + 3) & -4;
#if USE_EBX
trace ("gfunc_epilog 21\n");
o(0x8b);
gen_modrm(TREG_EBX, VT_LOCAL, NULL, -(v+4));
#endif
o(0xc9); /* leave */
if (func_ret_sub == 0) {
trace ("gfunc_epilog 23\n");
o(0xc3); /* ret */
} else {
trace ("gfunc_epilog 24\n");
o(0xc2); /* ret n */
g(func_ret_sub);
g(func_ret_sub >> 8);
@ -660,6 +698,7 @@ ST_FUNC void gfunc_epilog(void)
} else
#endif
{
trace ("gfunc_epilog 30\n");
o(0xe58955); /* push %ebp, mov %esp, %ebp */
o(0xec81); /* sub esp, stacksize */
gen_le32(v);
@ -751,6 +790,8 @@ ST_FUNC void gen_opi(int op)
{
int r, fr, opc, c;
trace_enter ("gen_opi");
trace ("gen_opi op="); eputs (itoa (op)); eputs ("\n");
switch(op) {
case '+':
case TOK_ADDC1: /* add with carry generation */
@ -762,7 +803,13 @@ ST_FUNC void gen_opi(int op)
r = gv(RC_INT);
vswap();
c = vtop->c.i;
trace ("gen_opi 14 c ="); eputs (itoa (c)); eputs ("\n");
#if __MESC__
char ch = c;
if (c == ch && ((ch >= 0 && ch < 128) || c < 0)) {
#else
if (c == (char)c) {
#endif
/* generate inc and dec for smaller code */
if (c==1 && opc==0 && op != TOK_ADDC1) {
o (0x40 | r); // inc
@ -774,6 +821,7 @@ ST_FUNC void gen_opi(int op)
g(c);
}
} else {
trace ("gen_opi 20\n");
o(0x81);
oad(0xc0 | (opc << 3) | r, c);
}

View File

@ -20,7 +20,9 @@
#else /* !TARGET_DEFS_ONLY */
#ifndef _TCC_H
#include "tcc.h"
#endif
/* Returns 1 for a code relocation, 0 for a data relocation. For unknown
relocations, returns -1. */

28
install.sh Executable file
View File

@ -0,0 +1,28 @@
#! /bin/sh
if [ -n "$BUILD_DEBUG" ]; then
set -x
fi
set -e
PREFIX=${PREFIX-usr}
MES_PREFIX=${MES_PREFIX-${MESCC%/*}}
MES_SEED=${MES_SEED-../mes-seed}
mkdir -p $PREFIX/bin
cp tcc $PREFIX/bin
tar -C $MES_PREFIX -cf- include | tar -C $PREFIX -xf-
mkdir -p $PREFIX/lib
cp crt1.o $PREFIX/lib/crt1.o
cp crti.o $PREFIX/lib/crti.o
cp crtn.o $PREFIX/lib/crtn.o
mkdir -p $PREFIX/lib/tcc
cp libc.a $PREFIX/lib
cp libtcc1.a $PREFIX/lib/tcc
tar -C $MES_SEED -cf- . | tar -C $PREFIX/lib -xf-
rm -f $PREFIX/lib/linux/x86_64-mes/crt1

159
libtcc.c
View File

@ -18,7 +18,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _TCC_H
#include "tcc.h"
#endif
/********************************************************/
/* global variables */
@ -220,10 +222,14 @@ PUB_FUNC void *tcc_mallocz(unsigned long size)
PUB_FUNC void *tcc_realloc(void *ptr, unsigned long size)
{
trace_enter ("tcc_realloc");
trace ("tcc_realloc size="); eputs (itoa (size)); eputs ("\n");
void *ptr1;
ptr1 = realloc(ptr, size);
if (!ptr1 && size)
tcc_error("memory full (realloc)");
trace_exit ("tcc_realloc");
return ptr1;
}
@ -433,11 +439,16 @@ ST_FUNC void dynarray_reset(void *pp, int *n)
static void tcc_split_path(TCCState *s, void *p_ary, int *p_nb_ary, const char *in)
{
const char *p;
//eputs ("sp in="); //eputs (in); //eputs ("\n");
do {
int c;
CString str;
//eputs ("sp in="); //eputs (in); //eputs ("\n");
//if (s->nb_files) {struct filespec *f = s->files[0]; //eputs ("sp 01 file[0]="); //eputs (f->name); //eputs ("\n");}
cstr_new(&str);
//if (s->nb_files) {struct filespec *f = s->files[0]; //eputs ("sp 02 file[0]="); //eputs (f->name); //eputs ("\n");}
for (p = in; c = *p, c != '\0' && c != PATHSEP[0]; ++p) {
if (c == '{' && p[1] && p[2] == '}') {
c = p[1], p += 2;
@ -449,11 +460,15 @@ static void tcc_split_path(TCCState *s, void *p_ary, int *p_nb_ary, const char *
}
if (str.size) {
cstr_ccat(&str, '\0');
//if (s->nb_files) {struct filespec *f = s->files[0]; //eputs ("sp 14 file[0]="); //eputs (f->name); //eputs ("\n");}
dynarray_add(p_ary, p_nb_ary, tcc_strdup(str.data));
}
//if (s->nb_files) {struct filespec *f = s->files[0]; //eputs ("sp 15 file[0]="); //eputs (f->name); //eputs ("\n");}
cstr_free(&str);
//if (s->nb_files) {struct filespec *f = s->files[0]; //eputs ("sp 16 file[0]="); //eputs (f->name); //eputs ("\n");}
in = p+1;
} while (*p);
//eputs ("sp 99\n");
}
/********************************************************/
@ -570,53 +585,78 @@ PUB_FUNC void tcc_warning(const char *fmt, ...)
ST_FUNC void tcc_open_bf(TCCState *s1, const char *filename, int initlen)
{
trace_enter ("tcc_open_bf");
BufferedFile *bf;
int buflen = initlen ? initlen : IO_BUF_SIZE;
bf = tcc_mallocz(sizeof(BufferedFile) + buflen);
trace ("tcc_open_bf buflen="); eputs (itoa (buflen)); eputs ("\n");
//eputs ("tcc_open_bf bf size="); //eputs (itoa (sizeof (BufferedFile) + buflen)); //eputs ("\n");
trace ("tcc_open_bf 10\n");
bf->buf_ptr = bf->buffer;
trace ("tcc_open_bf 11\n");
bf->buf_end = bf->buffer + initlen;
trace ("tcc_open_bf 12\n");
bf->buf_end[0] = CH_EOB; /* put eob symbol */
trace ("tcc_open_bf 13\n");
pstrcpy(bf->filename, sizeof(bf->filename), filename);
trace ("tcc_open_bf 14\n");
bf->true_filename = bf->filename;
trace ("tcc_open_bf 15\n");
bf->line_num = 1;
bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
bf->fd = -1;
bf->prev = file;
file = bf;
tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
trace_exit ("tcc_open_bf");
}
ST_FUNC void tcc_close(void)
{
trace_enter ("tcc_close");
BufferedFile *bf = file;
//eputs ("tcc_close file:"); //eputs (itoa (file)); //eputs ("\n");
//eputs ("tcc_close bf->fd:"); //eputs (itoa (bf->fd)); //eputs ("\n");
//eputs ("tcc_close bf->prev:"); //eputs (itoa (bf->prev)); //eputs ("\n");
if (bf->fd > 0) {
//eputs ("tcc_close bf->filename:"); //eputs (bf->filename); //eputs ("\n");
close(bf->fd);
total_lines += bf->line_num;
}
if (bf->true_filename != bf->filename)
tcc_free(bf->true_filename);
trace ("tcc_close file->buf_ptr="); eputs (file->buf_ptr); eputs ("\n");
file = bf->prev;
tcc_free(bf);
trace_exit ("tcc_close");
}
ST_FUNC int tcc_open(TCCState *s1, const char *filename)
{
int fd;
trace_enter ("tcc_open");
trace ("tcc_open file-name="); eputs (filename); eputs ("\n");
if (strcmp(filename, "-") == 0)
fd = 0, filename = "<stdin>";
else
fd = open(filename, O_RDONLY | O_BINARY);
trace ("tcc_open fd="); eputs (itoa (fd)); eputs ("\n");
if ((s1->verbose == 2 && fd >= 0) || s1->verbose == 3)
printf("%s %*s%s\n", fd < 0 ? "nf":"->",
(int)(s1->include_stack_ptr - s1->include_stack), "", filename);
if (fd < 0)
if (fd < 0) {
trace_exit ("tcc_open");
return -1;
eputs ("tcc_open 10\n");
tcc_open_bf(s1, filename, 0);
eputs ("tcc_open 11\n");
#ifdef _WIN32
normalize_slashes(file->filename);
#endif
file->fd = fd;
trace_exit ("tcc_open");
return fd;
}
@ -626,6 +666,7 @@ static int tcc_compile(TCCState *s1)
Sym *define_start;
int filetype, is_asm;
trace_enter ("tcc_compile");
define_start = define_stack;
filetype = s1->filetype;
is_asm = filetype == AFF_TYPE_ASM || filetype == AFF_TYPE_ASMPP;
@ -635,7 +676,9 @@ static int tcc_compile(TCCState *s1)
s1->nb_errors = 0;
s1->error_set_jmp_enabled = 1;
trace ("tcc_compile 05 nb_errors="); eputs (itoa (s1->nb_errors)); eputs ("\n");
preprocess_start(s1, is_asm);
trace ("tcc_compile 06 nb_errors="); eputs (itoa (s1->nb_errors)); eputs ("\n");
if (s1->output_type == TCC_OUTPUT_PREPROCESS) {
tcc_preprocess(s1);
} else if (is_asm) {
@ -645,7 +688,9 @@ static int tcc_compile(TCCState *s1)
tcc_error_noabort("asm not supported");
#endif
} else {
trace ("tcc_compile 13 nb_errors="); eputs (itoa (s1->nb_errors)); eputs ("\n");
tccgen_compile(s1);
trace ("tcc_compile 14 nb_errors="); eputs (itoa (s1->nb_errors)); eputs ("\n");
}
}
s1->error_set_jmp_enabled = 0;
@ -657,6 +702,7 @@ static int tcc_compile(TCCState *s1)
sym_pop(&global_stack, NULL, 0);
sym_pop(&local_stack, NULL, 0);
tccelf_end_file(s1);
trace_exit ("tcc_compile");
return s1->nb_errors != 0 ? -1 : 0;
}
@ -675,23 +721,35 @@ LIBTCCAPI int tcc_compile_string(TCCState *s, const char *str)
/* define a preprocessor symbol. A value can also be provided with the '=' operator */
LIBTCCAPI void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
{
trace_enter ("tcc_define_symbol");
trace ("tcc_define_symbol value="); eputs (itoa (value)); eputs ("\n");
int len1, len2;
/* default value */
if (!value)
value = "1";
trace ("tcc_define_symbol 01\n");
len1 = strlen(sym);
trace ("tcc_define_symbol 02\n");
len2 = strlen(value);
trace ("tcc_define_symbol 03\n");
/* init file structure */
tcc_open_bf(s1, "<define>", len1 + len2 + 1);
trace ("tcc_define_symbol 04\n");
memcpy(file->buffer, sym, len1);
file->buffer[len1] = ' ';
memcpy(file->buffer + len1 + 1, value, len2);
trace ("tcc_define_symbol X="); //eputs (file->buffer); //eputs ("\n");
/* parse with define parser */
next_nomacro();
trace ("tcc_define_symbol 09\n");
parse_define();
trace ("tcc_define_symbol 10\n");
tcc_close();
trace_exit ("tcc_define_symbol");
}
/* undefine a preprocessor symbol */
@ -709,14 +767,17 @@ LIBTCCAPI void tcc_undefine_symbol(TCCState *s1, const char *sym)
/* cleanup all static data used during compilation */
static void tcc_cleanup(void)
{
if (NULL == tcc_state)
return;
while (file)
tcc_close();
tccpp_delete(tcc_state);
//eputs ("tcc_cleanup01\n");
tcc_state = NULL;
/* free sym_pools */
dynarray_reset(&sym_pools, &nb_sym_pools);
//eputs ("tcc_cleanup02\n");
/* reset symbol stack */
sym_free_first = NULL;
}
@ -725,14 +786,28 @@ LIBTCCAPI TCCState *tcc_new(void)
{
TCCState *s;
//eputs ("tcc_new\n");
tcc_cleanup();
//eputs ("tcc_new01\n");
s = tcc_mallocz(sizeof(TCCState));
//eputs ("size:"); //eputs (itoa (sizeof(TCCState))); //eputs ("\n");
//eputs ("tcc_new02\n");
//eputs ("s="); //eputs (itoa (s)); //eputs ("\n");
if (!s)
return NULL;
tcc_state = s;
trace ("tccnew include_stack="); eputs (itoa (&s->include_stack[0])); eputs ("\n");
++nb_states;
#if BOOTSTRAP
s->static_link = 1;
#endif
eputs ("tcc_new03\n");
s->alacarte_link = 1;
s->nocommon = 1;
s->warn_implicit_function_declaration = 1;
@ -889,6 +964,8 @@ LIBTCCAPI TCCState *tcc_new(void)
/* Some GCC builtins that are simple to express as macros. */
tcc_define_symbol(s, "__builtin_extract_return_addr(x)", "x");
#endif /* ndef TCC_TARGET_PE */
//eputs ("tcc_new99\n");
return s;
}
@ -994,12 +1071,35 @@ LIBTCCAPI int tcc_add_sysinclude_path(TCCState *s, const char *pathname)
return 0;
}
#if !__x86_64__
#undef eputs
#endif
#if !BOOTSTRAP // MESC
#define for_each_elem(sec, startoff, elem, type) \
for (elem = (type *) sec->data + startoff; \
elem < (type *) (sec->data + sec->data_offset); elem++)
#else
#define for_each_elem(sec, startoff, elem, type) \
elem = sec->data + sizeof (type) * startoff; \
for (;elem < ((type *) (sec->data + sec->data_offset)); elem++)
#endif
ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
{
int ret;
/* open the file */
trace ("tcc_add_file_internal filename="); eputs (filename); eputs ("\n");
ret = tcc_open(s1, filename);
trace ("tcc_add_file_internal 20 ret="); eputs (itoa (ret));; eputs ("\n");
for_each_elem(symtab_section, 1, esym, ElfW(Sym)) {
trace ("tcc_add_file_internal num="); eputs (itoa (esym->st_shndx)); eputs ("\n");
name = (char *) strtab_section->data + esym->st_name;
trace ("tcc_add_file_internal name="); eputs (name); eputs ("\n");
}
if (ret < 0) {
if (flags & AFF_PRINT_ERROR)
tcc_error_noabort("file '%s' not found", filename);
@ -1025,45 +1125,62 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
switch (obj_type) {
case AFF_BINTYPE_REL:
{
ret = tcc_load_object_file(s1, fd, 0);
trace ("tcc_add_file_internal 41 ret="); eputs (itoa (ret));; eputs ("\n");
break;
}
#ifndef TCC_TARGET_PE
case AFF_BINTYPE_DYN:
{
if (s1->output_type == TCC_OUTPUT_MEMORY) {
ret = 0;
#ifdef TCC_IS_NATIVE
if (NULL == dlopen(filename, RTLD_GLOBAL | RTLD_LAZY))
ret = -1;
#endif
trace ("tcc_add_file_internal 42 ret="); eputs (itoa (ret));; eputs ("\n");
} else {
ret = tcc_load_dll(s1, fd, filename,
(flags & AFF_REFERENCED_DLL) != 0);
trace ("tcc_add_file_internal 43 ret="); eputs (itoa (ret));; eputs ("\n");
}
break;
#endif
}
case AFF_BINTYPE_AR:
{
ret = tcc_load_archive(s1, fd);
trace ("tcc_add_file_internal 51 ret="); eputs (itoa (ret));; eputs ("\n");
break;
}
#ifdef TCC_TARGET_COFF
case AFF_BINTYPE_C67:
ret = tcc_load_coff(s1, fd);
trace ("tcc_add_file_internal 52 ret="); eputs (itoa (ret));; eputs ("\n");
break;
#endif
default:
{
#ifdef TCC_TARGET_PE
ret = pe_load_file(s1, filename, fd);
#else
/* as GNU ld, consider it is an ld script if not recognized */
ret = tcc_load_ldscript(s1);
trace ("tcc_add_file_internal 61 ret="); eputs (itoa (ret));; eputs ("\n");
#endif
if (ret < 0)
tcc_error_noabort("unrecognized file type");
break;
}
}
} else {
ret = tcc_compile(s1);
}
trace ("tcc_add_file_internal 90\n");
tcc_close();
trace_exit ("tcc_add_file_internal");
return ret;
}
@ -1094,7 +1211,11 @@ LIBTCCAPI int tcc_add_file(TCCState *s, const char *filename)
LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname)
{
trace ("tcc_add_library_path path="); eputs (pathname); eputs ("\n");
tcc_split_path(s, &s->library_paths, &s->nb_library_paths, pathname);
for(int i = 0; i < s->nb_library_paths; i++) {
trace ("tcc_add_library_path dir="); eputs (s->library_paths[i]); eputs ("\n");
}
return 0;
}
@ -1104,8 +1225,11 @@ static int tcc_add_library_internal(TCCState *s, const char *fmt,
char buf[1024];
int i;
trace ("tcc_add_library_internal file-name="); eputs (filename); eputs ("\n");
trace ("tcc_add_library_internal nb_paths="); eputs (itoa (nb_paths)); eputs ("\n");
for(i = 0; i < nb_paths; i++) {
snprintf(buf, sizeof(buf), fmt, paths[i], filename);
trace ("tcc_add_library_internal buf="); eputs (buf); eputs ("\n");
if (tcc_add_file_internal(s, buf, flags | AFF_TYPE_BIN) == 0)
return 0;
}
@ -1122,6 +1246,7 @@ ST_FUNC int tcc_add_dll(TCCState *s, const char *filename, int flags)
ST_FUNC int tcc_add_crt(TCCState *s, const char *filename)
{
trace ("tcc_add_crt file name="); eputs (filename); eputs ("\n");
if (-1 == tcc_add_library_internal(s, "%s/%s",
filename, 0, s->crt_paths, s->nb_crt_paths))
tcc_error_noabort("file '%s' not found", filename);
@ -1152,6 +1277,7 @@ LIBTCCAPI int tcc_add_library(TCCState *s, const char *libraryname)
PUB_FUNC int tcc_add_library_err(TCCState *s, const char *libname)
{
trace ("tcc_add_library_err libname="); eputs (libname); eputs ("\n");
int ret = tcc_add_library(s, libname);
if (ret < 0)
tcc_error_noabort("library '%s' not found", libname);
@ -1173,6 +1299,7 @@ LIBTCCAPI int tcc_add_symbol(TCCState *s, const char *name, const void *val)
So it is handled here as if it were in a DLL. */
pe_putimport(s, 0, name, (uintptr_t)val);
#else
trace ("tcc_add_symbol name="); eputs (name); eputs ("\n");
set_elf_sym(symtab_section, (uintptr_t)val, 0,
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
SHN_ABS, name);
@ -1237,10 +1364,13 @@ ST_FUNC int set_flag(TCCState *s, const FlagDef *flags, const char *name)
static int strstart(const char *val, const char **str)
{
//eputs ("strstart val:"); //eputs (val); //eputs ("\n");
//eputs ("strstart *str:"); //eputs (*str); //eputs ("\n");
const char *p, *q;
p = *str;
q = val;
while (*q) {
//eputs ("*q:"); //eputc (*q); //eputs ("\n");
if (*p != *q)
return 0;
p++;
@ -1427,8 +1557,13 @@ static int tcc_set_linker(TCCState *s, const char *option)
typedef struct TCCOption {
const char *name;
#if !BOOTSTRAP
uint16_t index;
uint16_t flags;
#else
int index;
int flags;
#endif
} TCCOption;
enum {
@ -1594,10 +1729,16 @@ static void parse_option_D(TCCState *s1, const char *optarg)
static void args_parser_add_file(TCCState *s, const char* filename, int filetype)
{
struct filespec *f = tcc_malloc(sizeof *f + strlen(filename));
trace ("arg_parser_add file name="); eputs (filename); eputs ("\n");
f->type = filetype;
f->alacarte = s->alacarte_link;
strcpy(f->name, filename);
trace ("arg_parser_add file f->name="); //eputs (f->name); //eputs ("\n");
trace ("arg_parser_add nb_files="); //eputs (itoa (s->nb_files)); //eputs ("\n");
dynarray_add(&s->files, &s->nb_files, f);
//struct filespec *= s->files[s->nb_files - 1];
struct filespec * fs = s->files[0];
//eputs ("arg_parser_add file fs->name="); //eputs (fs->name); //eputs ("\n");
}
static int args_parser_make_argv(const char *r, int *argc, char ***argv)
@ -1642,6 +1783,7 @@ static void args_parser_listfile(TCCState *s,
int argc = 0;
char **argv = NULL;
trace ("arg_parser_listfile filename="); eputs (filename); eputs ("\n");
fd = open(filename, O_RDONLY | O_BINARY);
if (fd < 0)
tcc_error("listfile '%s' not found", filename);
@ -1663,6 +1805,8 @@ static void args_parser_listfile(TCCState *s,
PUB_FUNC int tcc_parse_args(TCCState *s, int *pargc, char ***pargv, int optind)
{
trace ("tcc_parse_args\n");
const TCCOption *popt;
const char *optarg, *r;
const char *run = NULL;
@ -1676,7 +1820,11 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int *pargc, char ***pargv, int optind)
cstr_new(&linker_arg);
while (optind < argc) {
trace ("tcc_parse_args 02 arg:"); eputs (itoa (optind)); eputs ("\n");
r = argv[optind];
trace ("tcc_parse_args 03 r:"); eputs (r); eputs ("\n");
if (r[0] == '@' && r[1] != '\0') {
args_parser_listfile(s, r + 1, optind, &argc, &argv);
continue;
@ -1699,10 +1847,17 @@ reparse:
continue;
}
trace ("tcc_parse_args 20\n");
trace ("tcc_parse_args 20 opt0="); eputs (tcc_options[0].name); eputs ("\n");
trace ("tcc_parse_args 20 opt1="); eputs (tcc_options[1].name); eputs ("\n");
/* find option in table */
for(popt = tcc_options; ; ++popt) {
trace ("tcc_parse_args 21\n");
trace ("tcc_parse_args 22 popt:"); eputs (popt->name); eputs ("\n");
const char *p1 = popt->name;
const char *r1 = r + 1;
trace ("tcc_parse_args 23 r1:"); eputs (r1); eputs ("\n");
if (p1 == NULL)
tcc_error("invalid option -- '%s'", r);
if (!strstart(p1, &r1))
@ -1720,6 +1875,8 @@ reparse:
break;
}
trace ("pars_arg 2\n");
switch(popt->index) {
case TCC_OPTION_HELP:
return OPT_HELP;

29
link.sh Executable file
View File

@ -0,0 +1,29 @@
#! /bin/sh
set -ex
rm -f 1.a 2.a
MES_PREFIX=${MES_PREFIX-../mes}
MES_SEED=${MES_SEED-../mes-seed}
# trivial bin
###./tcc ../mes/scaffold/main.c
c=${1-$MES_PREFIX/scaffold/main}
b=scaffold/${c##*/}
rm -f "$b".mes-gcc-out
rm -f "$b".mes-out
./i686-unknown-linux-gnu-tcc\
-static -g -o "$b".mes-gcc-out -I $MES_PREFIX/include -L $MES_SEED "$c".c 2> "$b".mes-gcc-stderr
set +e
${MES_TCC-./mes-tcc}\
-static -g -o "$b".mes-out -I $MES_PREFIX/include -L $MES_SEED "$c".c 2> "$b".mes-stderr
objdump -d "$b".mes-gcc-out > "$b".mes-gcc-d
objdump -d "$b".mes-out > "$b".mes-d
#readelf -a a.i686-unknown-linux-gnu-out > 1.r
#readelf -a a.mes-out > 2.r
#diff -y 1.a 2.a
echo diff -y "$b".mes-gcc-stderr "$b".mes-stderr
echo diff -y "$b".mes-gcc-d "$b".mes-d
"$b".mes-out

29
tcc.c
View File

@ -252,10 +252,22 @@ int main(int argc0, char **argv0)
int argc; char **argv;
FILE *ppfp = stdout;
trace_enter ("main");
redo:
argc = argc0, argv = argv0;
trace ("main 01\n");
s = tcc_new();
trace ("main 02\n");
opt = tcc_parse_args(s, &argc, &argv, 1);
trace ("main 03\n");
if (s->nb_files) {
struct filespec *f = s->files[0];
trace ("main 05 file[0]="); eputs (f->name); eputs ("\n");
}
trace ("main 06\n");
if ((n | t) == 0) {
if (opt == OPT_HELP)
@ -306,7 +318,10 @@ redo:
start_time = getclock_ms();
}
trace ("main 20\n");
set_environment(s);
trace ("main 21\n");
if (s->output_type == 0)
s->output_type = TCC_OUTPUT_EXE;
tcc_set_output_type(s, s->output_type);
@ -316,14 +331,20 @@ redo:
|| s->output_type == TCC_OUTPUT_PREPROCESS) && (s->dflag & 16))
s->dflag |= t ? 32 : 0, s->run_test = ++t, n = s->nb_files;
trace ("main 23\n");
/* compile or add each files or library */
for (first_file = NULL, ret = 0;;) {
trace ("main 24 nb-files="); eputs (itoa (s->nb_files)); eputs ("\n");
trace ("main 24 n="); eputs (itoa (n)); eputs ("\n");
struct filespec *f = s->files[s->nb_files - n];
trace ("for f->name="); eputs (f->name); eputs ("\n");
s->filetype = f->type;
s->alacarte_link = f->alacarte;
if (f->type == AFF_TYPE_LIB) {
if (tcc_add_library_err(s, f->name) < 0)
ret = 1;
trace ("main 32 ret="); eputs (itoa (ret)); eputs ("\n");
} else {
if (1 == s->verbose)
printf("-> %s\n", f->name);
@ -331,7 +352,9 @@ redo:
first_file = f->name;
if (tcc_add_file(s, f->name) < 0)
ret = 1;
trace ("main 33 ret="); eputs (itoa (ret)); eputs ("\n");
}
trace ("ret="); eputs (itoa (ret)); eputs ("\n");
s->filetype = 0;
s->alacarte_link = 1;
if (--n == 0 || ret
@ -339,18 +362,23 @@ redo:
break;
}
trace ("main 40\n");
if (s->run_test) {
t = 0;
} else if (s->output_type == TCC_OUTPUT_PREPROCESS) {
;
} else if (0 == ret) {
trace ("main 42 ret == 0\n");
if (s->output_type == TCC_OUTPUT_MEMORY) {
trace ("main RUN\n");
#ifdef TCC_IS_NATIVE
ret = tcc_run(s, argc, argv);
#endif
} else {
trace ("main 44 gonna output_file\n");
if (!s->outfile)
s->outfile = default_outputfile(s, first_file);
trace ("main 45 output_file\n");
if (tcc_output_file(s, s->outfile))
ret = 1;
else if (s->gen_deps)
@ -367,5 +395,6 @@ redo:
goto redo; /* run more tests with -dt -run */
if (ppfp && ppfp != stdout)
fclose(ppfp);
trace_exit ("main");
return ret;
}

31
tcc.h
View File

@ -92,6 +92,9 @@ extern long double strtold (const char *__nptr, char **__endptr);
#ifdef _MSC_VER
# define NORETURN __declspec(noreturn)
# define ALIGNED(x) __declspec(align(x))
#elif __MESC__
#define NORETURN
#define ALIGNED(x)
#else
# define NORETURN __attribute__((noreturn))
# define ALIGNED(x) __attribute__((aligned(x)))
@ -433,6 +436,7 @@ typedef struct SValue {
/* symbol attributes */
struct SymAttr {
#if HAVE_BITFIELD
unsigned short
aligned : 5, /* alignment as log2+1 (0 == unspecified) */
packed : 1,
@ -441,14 +445,33 @@ struct SymAttr {
dllexport : 1,
dllimport : 1,
unused : 5;
#else // !HAVE_BITFIELD
struct {
unsigned aligned;
unsigned packed;
unsigned weak;
unsigned visibility;
unsigned dllexport;
unsigned dllimport;
unsigned unused;
};
#endif // !HAVE_BITFIELD
};
/* function attributes or temporary attributes for parsing */
struct FuncAttr {
#if HAVE_BITFIELD
unsigned
func_call : 3, /* calling convention (0..5), see below */
func_type : 2, /* FUNC_OLD/NEW/ELLIPSIS */
func_args : 8; /* PE __stdcall args */
#else // !HAVE_BITFIELD
struct {
unsigned func_call;
unsigned func_type;
unsigned func_args;
};
#endif // !HAVE_BITFIELD
};
/* GNUC attribute definition */
@ -466,19 +489,15 @@ typedef struct Sym {
int v; /* symbol token */
unsigned short r; /* associated register or VT_CONST/VT_LOCAL and LVAL type */
struct SymAttr a; /* symbol attributes */
union {
struct {
int c; /* associated number or Elf symbol index */
union {
int sym_scope; /* scope level for locals */
int jnext; /* next jump label */
struct FuncAttr f; /* function attributes */
int auxtype; /* bitfield access type */
};
};
long long enum_val; /* enum constant if IS_ENUM_VAL */
int *d; /* define token stream */
};
long long enum_val; /* enum constant if IS_ENUM_VAL */
int *d; /* define token stream */
CType type; /* associated type */
union {
struct Sym *next; /* next related symbol (for fields and anoms) */

View File

@ -18,7 +18,10 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _TCC_H
#include "tcc.h"
#endif
#ifdef CONFIG_TCC_ASM
ST_FUNC int asm_get_local_label_name(TCCState *s1, unsigned int n)
@ -1108,9 +1111,12 @@ static void parse_asm_operands(ASMOperand *operands, int *nb_operands_ptr,
next();
skip(']');
}
parse_mult_str(&astr, "string constant");
parse_mult_str(&astr, "parse_asm_operands string constant");
trace ("parse arm_operands tokc.str.data="); eputs (tokc.str.data); eputs ("\n");
op->constraint = tcc_malloc(astr.size);
trace ("parse arm_operands tokc.str.data="); eputs (tokc.str.data); eputs ("\n");
strcpy(op->constraint, astr.data);
trace ("parse arm_operands tokc.str.data="); eputs (tokc.str.data); eputs ("\n");
cstr_free(&astr);
skip('(');
gexpr();
@ -1149,13 +1155,17 @@ ST_FUNC void asm_instr(void)
int nb_outputs, nb_operands, i, must_subst, out_reg;
uint8_t clobber_regs[NB_ASM_REGS];
trace_enter ("asm_instr");
next();
trace ("asm_instr 01\n");
/* since we always generate the asm() instruction, we can ignore
volatile */
if (tok == TOK_VOLATILE1 || tok == TOK_VOLATILE2 || tok == TOK_VOLATILE3) {
next();
}
trace ("asm_instr 02\n");
parse_asm_str(&astr);
trace ("asm_instr astr.data="); eputs (astr.data); eputs ("\n");
nb_operands = 0;
nb_outputs = 0;
must_subst = 0;
@ -1208,6 +1218,7 @@ ST_FUNC void asm_instr(void)
#ifdef ASM_DEBUG
printf("asm: \"%s\"\n", (char *)astr.data);
#endif
trace ("asm_instr asm:"); eputs (astr.data); eputs ("\n");
if (must_subst) {
subst_asm_operands(operands, nb_operands, &astr1, &astr);
cstr_free(&astr);
@ -1217,6 +1228,7 @@ ST_FUNC void asm_instr(void)
#ifdef ASM_DEBUG
printf("subst_asm: \"%s\"\n", (char *)astr1.data);
#endif
trace ("asm_instr subst:"); eputs (astr1.data); eputs ("\n");
/* generate loads */
asm_gen_code(operands, nb_operands, nb_outputs, 0,
@ -1240,6 +1252,7 @@ ST_FUNC void asm_instr(void)
vpop();
}
cstr_free(&astr1);
trace_exit ("asm_instr");
}
ST_FUNC void asm_global_instr(void)

View File

@ -19,7 +19,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _TCC_H
#include "tcc.h"
#endif
#define MAXNSCNS 255 /* MAXIMUM NUMBER OF SECTIONS */
#define MAX_STR_TABLE 1000000

306
tccelf.c
View File

@ -18,7 +18,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _TCC_H
#include "tcc.h"
#endif
/* Define this to get some debug output during relocation processing. */
#undef DEBUG_RELOC
@ -54,27 +56,41 @@ static int new_undef_sym = 0; /* Is there a new undefined sym since last new_und
ST_FUNC void tccelf_new(TCCState *s)
{
//eputs ("tccelf_new00\n");
/* no section zero */
//eputs ("tccelf_new00 nb_sections="); //eputs (itoa (s->nb_sections)); //eputs ("\n");
dynarray_add(&s->sections, &s->nb_sections, NULL);
//eputs ("tccelf_new01\n");
/* create standard sections */
text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
//eputs ("tccelf_new02\n");
data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
//eputs ("tccelf_new3\n");
bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
//eputs ("tccelf_new04\n");
common_section = new_section(s, ".common", SHT_NOBITS, SHF_PRIVATE);
//eputs ("tccelf_new05\n");
common_section->sh_num = SHN_COMMON;
//eputs ("tccelf_new06\n");
/* symbols are always generated for linking stage */
symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
".strtab",
".hashtab", SHF_PRIVATE);
//eputs ("tccelf_new07\n");
s->symtab = symtab_section;
//eputs ("tccelf_new08\n");
//eputs ("tccelf_new09\n");
/* private symbol table for dynamic symbols */
s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE|SHF_DYNSYM,
".dynstrtab",
".dynhashtab", SHF_PRIVATE);
//eputs ("tccelf_new10\n");
get_sym_attr(s, 0, 1);
//eputs ("tccelf_new99\n");
}
#ifdef CONFIG_TCC_BCHECK
@ -155,6 +171,7 @@ ST_FUNC void tccelf_begin_file(TCCState *s1)
with previously existing symbols */
ST_FUNC void tccelf_end_file(TCCState *s1)
{
#if 0 //!__MESC__ // Nyacc 0.80.40 cpp-bug
Section *s = s1->symtab;
int first_sym, nb_syms, *tr, i;
@ -187,16 +204,23 @@ ST_FUNC void tccelf_end_file(TCCState *s1)
}
}
tcc_free(tr);
#endif
}
ST_FUNC Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
{
Section *sec;
trace_enter ("new_section");
sec = tcc_mallocz(sizeof(Section) + strlen(name));
trace ("size:"); eputs (itoa (sizeof(Section) + strlen (name))); eputs ("\n");
trace ("new_section 01\n");
trace ("name="); eputs (name); eputs ("\n");
strcpy(sec->name, name);
trace ("new_section 02\n");
sec->sh_type = sh_type;
sec->sh_flags = sh_flags;
trace ("new_section 05\n");
switch(sh_type) {
case SHT_HASH:
case SHT_REL:
@ -214,13 +238,29 @@ ST_FUNC Section *new_section(TCCState *s1, const char *name, int sh_type, int sh
break;
}
trace ("new_section 10\n");
if (sh_flags & SHF_PRIVATE) {
trace ("new_section 11\n");
dynarray_add(&s1->priv_sections, &s1->nb_priv_sections, sec);
} else {
trace ("new_section 12\n");
sec->sh_num = s1->nb_sections;
dynarray_add(&s1->sections, &s1->nb_sections, sec);
}
for (int i = 1; i < s1->nb_sections; i++) {
trace ("new_section i= "); eputs (itoa (i)); eputs ("\n");
Section *s;
#if !BOOTSTRAP
s = s1->sections[i];
#else
Section **ps = s1->sections;
s = ps[i];
#endif
trace ("new_section name="); eputs (s->name); eputs ("\n");
}
trace_exit ("new_section");
return sec;
}
@ -232,16 +272,26 @@ ST_FUNC Section *new_symtab(TCCState *s1,
Section *symtab, *strtab, *hash;
int *ptr, nb_buckets;
//eputs ("new_symtab00\n");
symtab = new_section(s1, symtab_name, sh_type, sh_flags);
//eputs ("new_symtab01\n");
//eputs ("s->hash="); //eputs (itoa (symtab->hash)); //eputs ("\n");
symtab->sh_entsize = sizeof(ElfW(Sym));
//eputs ("new_symtab02\n");
strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);
//eputs ("new_symtab03\n");
put_elf_str(strtab, "");
//eputs ("new_symtab04\n");
symtab->link = strtab;
//eputs ("new_symtab05\n");
put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL);
//eputs ("new_symtab06\n");
nb_buckets = 1;
//eputs ("new_symtab10\n");
hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);
//eputs ("new_symtab11\n");
hash->sh_entsize = sizeof(int);
symtab->hash = hash;
hash->link = symtab;
@ -276,13 +326,19 @@ ST_FUNC size_t section_add(Section *sec, addr_t size, int align)
{
size_t offset, offset1;
trace_enter ("section_add");
offset = (sec->data_offset + align - 1) & -align;
trace ("section_add 01 offset="); eputs (itoa (offset)); eputs ("\n");
offset1 = offset + size;
if (sec->sh_type != SHT_NOBITS && offset1 > sec->data_allocated)
if (sec->sh_type != SHT_NOBITS && offset1 > sec->data_allocated) {
trace ("section_add 05\n");
section_realloc(sec, offset1);
}
sec->data_offset = offset1;
trace ("section_add 08 offset1="); eputs (itoa (offset1)); eputs ("\n");
if (align > sec->sh_addralign)
sec->sh_addralign = align;
trace_exit ("section_add");
return offset;
}
@ -290,7 +346,9 @@ ST_FUNC size_t section_add(Section *sec, addr_t size, int align)
sec->data_offset. */
ST_FUNC void *section_ptr_add(Section *sec, addr_t size)
{
trace_enter ("section_ptr_add");
size_t offset = section_add(sec, size, 1);
trace_exit ("section_ptr_add");
return sec->data + offset;
}
@ -325,6 +383,7 @@ ST_FUNC int put_elf_str(Section *s, const char *sym)
int offset, len;
char *ptr;
trace ("put_elf_str\n");
len = strlen(sym) + 1;
offset = s->data_offset;
ptr = section_ptr_add(s, len);
@ -393,6 +452,10 @@ ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size,
ElfW(Sym) *sym;
Section *hs;
trace_enter ("put_elf_sym");
if (name) {
trace ("put_elf_sym 00 name="); eputs (name); eputs ("\n");
}
sym = section_ptr_add(s, sizeof(ElfW(Sym)));
if (name && name[0])
name_offset = put_elf_str(s->link, name);
@ -407,12 +470,16 @@ ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size,
sym->st_shndx = shndx;
sym_index = sym - (ElfW(Sym) *)s->data;
hs = s->hash;
trace ("put_elf_sym20 size="); eputs (itoa (sizeof (ElfW(Sym)))); eputs ("\n");
trace ("put_elf_sym21 sym_index="); eputs (itoa (sym_index)); eputs ("\n");
if (hs) {
int *ptr, *base;
trace ("put_elf_sym 21\n");
ptr = section_ptr_add(hs, sizeof(int));
base = (int *)hs->data;
/* only add global or weak symbols. */
if (ELFW(ST_BIND)(info) != STB_LOCAL) {
trace ("put_elf_sym 25\n");
/* add another hashing entry */
nbuckets = base[0];
h = elf_hash((unsigned char *)s->link->data + name_offset) % nbuckets;
@ -425,10 +492,12 @@ ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size,
rebuild_hash(s, 2 * nbuckets);
}
} else {
trace ("put_elf_sym 40\n");
*ptr = 0;
base[1]++;
}
}
trace_exit ("put_elf_sym");
return sym_index;
}
@ -439,19 +508,37 @@ ST_FUNC int find_elf_sym(Section *s, const char *name)
int nbuckets, sym_index, h;
const char *name1;
trace_enter ("find_elf_sym");
trace ("find_elf_sym name="); eputs (name); eputs ("\n");
hs = s->hash;
if (!hs)
trace ("find_elf_sym 01\n");
if (!hs) {
trace_exit ("find_elf_sym");
return 0;
}
nbuckets = ((int *)hs->data)[0];
trace ("find_elf_sym 10 nbuckets="); eputs (itoa (nbuckets)); eputs ("\n");
h = elf_hash((unsigned char *) name) % nbuckets;
trace ("find_elf_sym 11 h="); eputs (itoa (h)); eputs ("\n");
sym_index = ((int *)hs->data)[2 + h];
trace ("find_elf_sym 12 sym_index="); eputs (itoa (sym_index)); eputs ("\n");
while (sym_index != 0) {
sym = &((ElfW(Sym) *)s->data)[sym_index];
name1 = (char *) s->link->data + sym->st_name;
if (!strcmp(name, name1))
trace ("find_elf_sym 13 sym->st_name="); eputs (itoa (sym->st_name)); eputs ("\n");
trace ("find_elf_sym 14 name1= "); eputs (itoa ((int)name1 - (int)s->link->data)); eputs ("\n");
//trace ("find_elf_sym 15 name= "); eputs (itoa (name)); eputs ("\n");
trace ("find_elf_sym 16 *name= "); eputs (itoa (*name)); eputs ("\n");
trace ("find_elf_sym 17 *name1="); eputs (itoa (name1 && sym->st_name >=0 && sym->st_name < 1000 ? *name1 : 0)); eputs ("\n");
//trace ("find_elf_sym 19 name= "); eputs (name); eputs ("\n");
//trace ("find_elf_sym 18 name1= "); eputs (name1); eputs ("\n");
if (!strcmp(name, name1)) {
trace_exit ("find_elf_sym 20");
return sym_index;
}
sym_index = ((int *)hs->data)[2 + nbuckets + sym_index];
}
trace_exit ("find_elf_sym");
return 0;
}
@ -485,20 +572,35 @@ ST_FUNC void* tcc_get_symbol_err(TCCState *s, const char *name)
}
#endif
#if !BOOTSTRAP // MESC
#define for_each_elem(sec, startoff, elem, type) \
for (elem = (type *) sec->data + startoff; \
elem < (type *) (sec->data + sec->data_offset); elem++)
#else
#define for_each_elem(sec, startoff, elem, type) \
elem = sec->data + sizeof (type) * startoff; \
for (;elem < ((type *) (sec->data + sec->data_offset)); elem++)
#endif
/* add an elf symbol : check if it is already defined and patch
it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */
ST_FUNC int set_elf_sym(Section *s, addr_t value, unsigned long size,
int info, int other, int shndx, const char *name)
{
trace_enter ("set_elf_sym");
ElfW(Sym) *esym;
trace ("set_elf_sym 01 name="); eputs (name); eputs ("\n");
int sym_bind, sym_index, sym_type, esym_bind;
unsigned char sym_vis, esym_vis, new_vis;
sym_bind = ELFW(ST_BIND)(info);
trace ("set_elf_sym 02\n");
sym_type = ELFW(ST_TYPE)(info);
trace ("set_elf_sym 03\n");
sym_vis = ELFW(ST_VISIBILITY)(other);
if (sym_bind != STB_LOCAL) {
trace ("set_elf_sym 13\n");
/* we search global or weak symbols */
sym_index = find_elf_sym(s, name);
if (!sym_index)
@ -508,6 +610,7 @@ ST_FUNC int set_elf_sym(Section *s, addr_t value, unsigned long size,
&& esym->st_other == other && esym->st_shndx == shndx)
return sym_index;
if (esym->st_shndx != SHN_UNDEF) {
trace ("set_elf_sym 16\n");
esym_bind = ELFW(ST_BIND)(esym->st_info);
/* propagate the most constraining visibility */
/* STV_DEFAULT(0)<STV_PROTECTED(3)<STV_HIDDEN(2)<STV_INTERNAL(1) */
@ -557,6 +660,7 @@ ST_FUNC int set_elf_sym(Section *s, addr_t value, unsigned long size,
}
} else {
do_patch:
trace ("set_elf_sym 40\n");
esym->st_info = ELFW(ST_INFO)(sym_bind, sym_type);
esym->st_shndx = shndx;
new_undef_sym = 1;
@ -566,10 +670,31 @@ ST_FUNC int set_elf_sym(Section *s, addr_t value, unsigned long size,
}
} else {
do_def:
trace ("set_elf_sym 50\n");
sym_index = put_elf_sym(s, value, size,
ELFW(ST_INFO)(sym_bind, sym_type), other,
shndx, name);
}
trace ("set_elf_sym 90 name="); eputs (name); eputs ("\n");
ElfW(Sym) *sym;
#if 1
for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
trace ("set_elf_sym num="); eputs (itoa (sym->st_shndx)); eputs ("\n");
name = (char *) strtab_section->data + sym->st_name;
trace ("set_elf_sym name="); eputs (name); eputs ("\n");
}
#else
for (sym = symtab_section->data; sym < (symtab_section->data + symtab_section->data_offset); sym++) {
trace ("set_elf_sym num="); eputs (itoa (sym->st_shndx)); eputs ("\n");
name = strtab_section->data;
name += sym->st_name;
//name = ((char *) strtab_section->data) + sym->st_name;
trace ("set_elf_sym name="); eputs (name); eputs ("\n");
}
#endif
trace_exit ("set_elf_sym");
return sym_index;
}
@ -628,9 +753,13 @@ ST_FUNC void squeeze_multi_relocs(Section *s, size_t oldrelocoffset)
a simple insertion sort. */
for (a = oldrelocoffset + sizeof(*r); a < sr->data_offset; a += sizeof(*r)) {
ssize_t i = a - sizeof(*r);
addr = ((ElfW_Rel*)(sr->data + a))->r_offset;
///addr = ((ElfW_Rel*)(sr->data + a))->r_offset;
ElfW_Rel* ea = (ElfW_Rel*)(sr->data + a);
ElfW_Rel* ei = (ElfW_Rel*)(sr->data + i);
addr = ea->r_offset;
for (; i >= (ssize_t)oldrelocoffset &&
((ElfW_Rel*)(sr->data + i))->r_offset > addr; i -= sizeof(*r)) {
ei->r_offset > addr; i -= sizeof(*r)) {
ei = (ElfW_Rel*)(sr->data + i);
ElfW_Rel tmp = *(ElfW_Rel*)(sr->data + a);
*(ElfW_Rel*)(sr->data + a) = *(ElfW_Rel*)(sr->data + i);
*(ElfW_Rel*)(sr->data + i) = tmp;
@ -726,27 +855,40 @@ static void sort_syms(TCCState *s1, Section *s)
Section *sr;
int type, sym_index;
trace_enter ("sort_syms\n");
nb_syms = s->data_offset / sizeof(ElfW(Sym));
new_syms = tcc_malloc(nb_syms * sizeof(ElfW(Sym)));
old_to_new_syms = tcc_malloc(nb_syms * sizeof(int));
trace ("sort_syms 05\n");
/* first pass for local symbols */
p = (ElfW(Sym) *)s->data;
q = new_syms;
trace ("sort_syms 10\n");
for(i = 0; i < nb_syms; i++) {
trace ("sort_syms 11 i="); eputs (itoa (i)); eputs ("\n");
unsigned char val = p->st_info;
trace ("val="); eputs (itoa (val)); eputs ("\n");
val >>= 4;
trace ("val="); eputs (itoa (val)); eputs ("\n");
if (ELFW(ST_BIND)(p->st_info) == STB_LOCAL) {
trace ("sort_syms 12\n");
old_to_new_syms[i] = q - new_syms;
*q++ = *p;
trace ("sort_syms 13\n");
}
p++;
}
trace ("sort_syms 20\n");
/* save the number of local symbols in section header */
if( s->sh_size ) /* this 'if' makes IDA happy */
s->sh_info = q - new_syms;
/* then second pass for non local symbols */
p = (ElfW(Sym) *)s->data;
trace ("sort_syms 25\n");
for(i = 0; i < nb_syms; i++) {
trace ("sort_syms 31 i="); eputs (itoa (i)); eputs ("\n");
if (ELFW(ST_BIND)(p->st_info) != STB_LOCAL) {
old_to_new_syms[i] = q - new_syms;
*q++ = *p;
@ -754,12 +896,15 @@ static void sort_syms(TCCState *s1, Section *s)
p++;
}
trace ("sort_syms40\n");
/* we copy the new symbols to the old */
memcpy(s->data, new_syms, nb_syms * sizeof(ElfW(Sym)));
tcc_free(new_syms);
trace ("sort_syms43\n");
/* now we modify all the relocations */
for(i = 1; i < s1->nb_sections; i++) {
trace ("sort_syms 43 i="); eputs (itoa (i)); eputs ("\n");
sr = s1->sections[i];
if (sr->sh_type == SHT_RELX && sr->link == s) {
for_each_elem(sr, 0, rel, ElfW_Rel) {
@ -772,6 +917,7 @@ static void sort_syms(TCCState *s1, Section *s)
}
tcc_free(old_to_new_syms);
trace_exit ("sort_syms\n");
}
/* relocate symbol table, resolve undefined symbols if do_resolve is
@ -784,10 +930,13 @@ ST_FUNC void relocate_syms(TCCState *s1, Section *symtab, int do_resolve)
for_each_elem(symtab, 1, sym, ElfW(Sym)) {
sh_num = sym->st_shndx;
trace ("relocate_syms 01 num="); eputs (itoa (sh_num)); eputs ("\n");
if (sh_num == SHN_UNDEF) {
name = (char *) s1->symtab->link->data + sym->st_name;
trace ("relocate_syms 02 name="); eputs (name); eputs ("\n");
/* Use ld.so to resolve symbol for us (for tcc -run) */
if (do_resolve) {
trace ("relocate_syms 03\n");
#if defined TCC_IS_NATIVE && !defined TCC_TARGET_PE
void *addr = dlsym(RTLD_DEFAULT, name);
if (addr) {
@ -799,25 +948,36 @@ ST_FUNC void relocate_syms(TCCState *s1, Section *symtab, int do_resolve)
}
#endif
/* if dynamic symbol exist, it will be used in relocate_section */
} else if (s1->dynsym && find_elf_sym(s1->dynsym, name))
} else if (s1->dynsym && find_elf_sym(s1->dynsym, name)) {
trace ("relocate_syms 04\n");
goto found;
}
/* XXX: _fp_hw seems to be part of the ABI, so we ignore
it */
if (!strcmp(name, "_fp_hw"))
trace ("relocate_syms 05\n");
if (!strcmp(name, "_fp_hw")) {
trace ("relocate_syms 06\n");
goto found;
}
/* only weak symbols are accepted to be undefined. Their
value is zero */
sym_bind = ELFW(ST_BIND)(sym->st_info);
trace ("relocate_syms 08\n");
if (sym_bind == STB_WEAK)
sym->st_value = 0;
else
tcc_error_noabort("undefined symbol '%s'", name);
} else if (sh_num < SHN_LORESERVE) {
trace ("relocate_syms 20\n");
name = (char *) strtab_section->data + sym->st_name;
trace ("relocate_syms 02 name="); eputs (name); eputs ("\n");
/* add section base */
sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
trace ("relocate_syms 22\n");
}
found: ;
}
trace_exit ("relocate_syms");
}
/* relocate a given section (CPU dependent) by applying the relocations
@ -1200,7 +1360,9 @@ ST_FUNC void tcc_add_runtime(TCCState *s1)
tcc_add_dll(s1, TCC_LIBGCC, 0);
}
#endif
#if CONFIG_TCC_LIBTCC1
tcc_add_support(s1, TCC_LIBTCC1);
#endif
/* add crt end if not memory output */
if (s1->output_type != TCC_OUTPUT_MEMORY)
tcc_add_crt(s1, "crtn.o");
@ -1216,18 +1378,37 @@ static void tcc_add_linker_symbols(TCCState *s1)
int i;
Section *s;
trace_enter ("tcc_add_linker_symbols");
set_elf_sym(symtab_section,
text_section->data_offset, 0,
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
text_section->sh_num, "_etext");
ElfW(Sym) *sym;
char *name;
for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
trace ("tcc_add_linker_symbols num="); eputs (itoa (sym->st_shndx)); eputs ("\n");
name = (char *) strtab_section->data + sym->st_name;
trace ("tcc_add_linker_symbols name="); eputs (name); eputs ("\n");
}
set_elf_sym(symtab_section,
data_section->data_offset, 0,
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
data_section->sh_num, "_edata");
for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
trace ("tcc_add_linker_symbols num="); eputs (itoa (sym->st_shndx)); eputs ("\n");
name = (char *) strtab_section->data + sym->st_name;
trace ("tcc_add_linker_symbols name="); eputs (name); eputs ("\n");
}
set_elf_sym(symtab_section,
bss_section->data_offset, 0,
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
bss_section->sh_num, "_end");
for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
trace ("tcc_add_linker_symbols num="); eputs (itoa (sym->st_shndx)); eputs ("\n");
name = (char *) strtab_section->data + sym->st_name;
trace ("tcc_add_linker_symbols name="); eputs (name); eputs ("\n");
}
#ifndef TCC_TARGET_PE
/* horrible new standard ldscript defines */
add_init_array_defines(s1, ".preinit_array");
@ -1267,6 +1448,12 @@ static void tcc_add_linker_symbols(TCCState *s1)
}
next_sec: ;
}
for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
trace ("set_elf_sym num="); eputs (itoa (sym->st_shndx)); eputs ("\n");
name = (char *) strtab_section->data + sym->st_name;
trace ("set_elf_sym name="); eputs (name); eputs ("\n");
}
trace_exit ("tcc_add_linker_symbols");
}
ST_FUNC void resolve_common_syms(TCCState *s1)
@ -1333,6 +1520,7 @@ ST_FUNC void fill_got(TCCState *s1)
ElfW_Rel *rel;
int i;
trace_enter ("fill_got");
for(i = 1; i < s1->nb_sections; i++) {
s = s1->sections[i];
if (s->sh_type != SHT_RELX)
@ -1352,6 +1540,7 @@ ST_FUNC void fill_got(TCCState *s1)
}
}
}
trace_exit ("fill_got");
}
/* See put_got_entry for a description. This is the second stage
@ -1360,6 +1549,7 @@ static void fill_local_got_entries(TCCState *s1)
{
ElfW_Rel *rel;
for_each_elem(s1->got->reloc, 0, rel, ElfW_Rel) {
trace_enter ("fill_local_got_entries");
if (ELFW(R_TYPE)(rel->r_info) == R_RELATIVE) {
int sym_index = ELFW(R_SYM) (rel->r_info);
ElfW(Sym) *sym = &((ElfW(Sym) *) symtab_section->data)[sym_index];
@ -1376,6 +1566,7 @@ static void fill_local_got_entries(TCCState *s1)
#endif
}
}
trace_exit ("fill_local_got_entries");
}
/* Bind symbols of executable: resolve undefined symbols from exported symbols
@ -1519,9 +1710,13 @@ static int alloc_sec_names(TCCState *s1, int file_type, Section *strsec)
Section *s;
int textrel = 0;
trace_enter ("alloc_sec_names");
/* Allocate strings for section names */
for(i = 1; i < s1->nb_sections; i++) {
trace ("alloc_sec_names i="); eputs (itoa (i)); eputs ("\n");
s = s1->sections[i];
trace ("alloc_sec_names 02\n");
trace ("alloc_sec_names name="); eputs (s->name); eputs ("\n");
/* when generating a DLL, we include relocations but we may
patch them */
if (file_type == TCC_OUTPUT_DLL &&
@ -1535,13 +1730,19 @@ static int alloc_sec_names(TCCState *s1, int file_type, Section *strsec)
file_type == TCC_OUTPUT_OBJ ||
(s->sh_flags & SHF_ALLOC) ||
i == (s1->nb_sections - 1)) {
trace ("alloc_sec_names 10\n");
/* we output all sections if debug or object file */
s->sh_size = s->data_offset;
trace ("alloc_sec_names 11\n");
}
if (s->sh_size || (s->sh_flags & SHF_ALLOC))
trace ("alloc_sec_names 12\n");
if (s->sh_size || (s->sh_flags & SHF_ALLOC)) {
trace ("alloc_sec_names 13\n");
s->sh_name = put_elf_str(strsec, s->name);
}
}
strsec->sh_size = strsec->data_offset;
trace_exit ("alloc_sec_names");
return textrel;
}
@ -1571,6 +1772,7 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum,
ElfW(Phdr) *ph;
Section *s;
trace_enter ("layout_sections");
file_type = s1->output_type;
sh_order_index = 1;
file_offset = 0;
@ -1580,8 +1782,11 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum,
if (s1->section_align)
s_align = s1->section_align;
trace ("layout_sections 10\n");
if (phnum > 0) {
trace ("layout_sections 11\n");
if (s1->has_text_addr) {
trace ("layout_sections 12\n");
int a_offset, p_offset;
addr = s1->text_addr;
/* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
@ -1592,6 +1797,7 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum,
a_offset += s_align;
file_offset += (a_offset - p_offset);
} else {
trace ("layout_sections 20\n");
if (file_type == TCC_OUTPUT_DLL)
addr = 0;
else
@ -1600,6 +1806,7 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum,
addr += (file_offset & (s_align - 1));
}
trace ("layout_sections 30\n");
ph = &phdr[0];
/* Leave one program headers for the program interpreter and one for
the program header table itself if needed. These are done later as
@ -1614,6 +1821,7 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum,
#endif
for(j = 0; j < 2; j++) {
trace ("layout_sections j="); eputs (itoa (j)); eputs ("\n");
ph->p_type = PT_LOAD;
if (j == 0)
ph->p_flags = PF_R | PF_X;
@ -1627,8 +1835,10 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum,
symbol tables, relocations, progbits, nobits */
/* XXX: do faster and simpler sorting */
for(k = 0; k < 5; k++) {
trace ("layout_sections k="); eputs (itoa (k)); eputs ("\n");
for(i = 1; i < s1->nb_sections; i++) {
s = s1->sections[i];
trace ("layout_sections i="); eputs (itoa (i)); eputs ("\n");
/* compute if section should be included */
if (j == 0) {
if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
@ -1721,8 +1931,10 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum,
}
}
trace ("layout_sections 80\n");
/* all other sections come after */
for(i = 1; i < s1->nb_sections; i++) {
trace ("layout_sections 80 i="); eputs (itoa (i)); eputs ("\n");
s = s1->sections[i];
if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
continue;
@ -1730,11 +1942,14 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum,
file_offset = (file_offset + s->sh_addralign - 1) &
~(s->sh_addralign - 1);
trace ("layout_sections file_offset="); eputs (itoa (file_offset)); eputs ("\n");
s->sh_offset = file_offset;
if (s->sh_type != SHT_NOBITS)
file_offset += s->sh_size;
}
trace_exit ("layout_sections");
return file_offset;
}
@ -1823,14 +2038,20 @@ static int final_sections_reloc(TCCState *s1)
int i;
Section *s;
trace_enter ("final_sections_reloc");
relocate_syms(s1, s1->symtab, 0);
trace ("final_sections_reloc 01\n");
if (s1->nb_errors != 0)
if (s1->nb_errors != 0) {
trace_exit ("final_sections_reloc");
return -1;
}
trace ("final_sections_reloc 02\n");
/* relocate sections */
/* XXX: ignore sections with allocated relocations ? */
for(i = 1; i < s1->nb_sections; i++) {
trace ("final_sections_reloc 21\n");
s = s1->sections[i];
#if defined(TCC_TARGET_I386) || defined(TCC_MUSL)
if (s->reloc && s != s1->got && (s->sh_flags & SHF_ALLOC)) //gr
@ -1843,15 +2064,19 @@ static int final_sections_reloc(TCCState *s1)
relocate_section(s1, s);
}
trace ("final_sections_reloc 80\n");
/* relocate relocation entries if the relocation tables are
allocated in the executable */
for(i = 1; i < s1->nb_sections; i++) {
trace ("final_sections_reloc 81\n");
s = s1->sections[i];
if ((s->sh_flags & SHF_ALLOC) &&
s->sh_type == SHT_RELX) {
relocate_rel(s1, s);
}
}
trace_exit ("final_sections_reloc");
return 0;
}
@ -1865,6 +2090,7 @@ static void tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr,
ElfW(Ehdr) ehdr;
ElfW(Shdr) shdr, *sh;
trace_enter ("tcc_output_elf");
file_type = s1->output_type;
shnum = s1->nb_sections;
@ -1876,6 +2102,8 @@ static void tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr,
ehdr.e_phoff = sizeof(ElfW(Ehdr));
}
trace ("tcc_output_elf 10\n");
/* align to 4 */
file_offset = (file_offset + 3) & -4;
@ -1905,6 +2133,7 @@ static void tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr,
ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
#endif
#endif
trace ("tcc_output_elf 20\n");
switch(file_type) {
default:
case TCC_OUTPUT_EXE:
@ -1927,6 +2156,15 @@ static void tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr,
ehdr.e_shnum = shnum;
ehdr.e_shstrndx = shnum - 1;
trace ("tcc_output_elf 50\n");
trace ("tcc_output_elf ehdr.size="); eputs (itoa (sizeof(ElfW(Ehdr)))); eputs ("\n");
trace ("tcc_output_elf ehdr.e_machine="); eputs (itoa (ehdr.e_machine)); eputs ("\n");
trace ("tcc_output_elf ehdr.e_version="); eputs (itoa (ehdr.e_version)); eputs ("\n");
unsigned char *p = &ehdr;
for (int i = 0; i < sizeof(ElfW(Ehdr)); i++) {
if (i < 10) eputs (" ");
trace (itoa (i)); eputs (": "); eputs (itoa (p[i])); eputs ("\n");
}
fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
@ -1934,6 +2172,7 @@ static void tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr,
sort_syms(s1, symtab_section);
for(i = 1; i < s1->nb_sections; i++) {
s = s1->sections[sec_order[i]];
trace ("tcc_output_elf 50 name="); eputs (s->name); eputs ("\n");
if (s->sh_type != SHT_NOBITS) {
while (offset < s->sh_offset) {
fputc(0, f);
@ -1946,31 +2185,44 @@ static void tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr,
}
}
trace ("tcc_output_elf 60\n");
/* output section headers */
while (offset < ehdr.e_shoff) {
fputc(0, f);
offset++;
}
trace ("tcc_output_elf 70\n");
for(i = 0; i < s1->nb_sections; i++) {
trace ("tcc_output_elf 70 i="); eputs (itoa (i)); eputs ("\n");
sh = &shdr;
memset(sh, 0, sizeof(ElfW(Shdr)));
trace ("tcc_output_elf 72\n");
s = s1->sections[i];
if (s) {
trace ("tcc_output_elf 80\n");
trace ("tcc_output_elf 80 name="); eputs (s->name ? s->name : "<null>"); eputs ("\n");
sh->sh_name = s->sh_name;
sh->sh_type = s->sh_type;
sh->sh_flags = s->sh_flags;
sh->sh_entsize = s->sh_entsize;
sh->sh_info = s->sh_info;
if (s->link)
trace ("tcc_output_elf 85\n");
if (s->link) {
sh->sh_link = s->link->sh_num;
trace ("tcc_output_elf 86 sh_num="); eputs (itoa (s->link->sh_num)); eputs ("\n");
}
trace ("tcc_output_elf 87\n");
sh->sh_addralign = s->sh_addralign;
sh->sh_addr = s->sh_addr;
sh->sh_offset = s->sh_offset;
sh->sh_size = s->sh_size;
}
trace ("tcc_output_elf 90\n");
fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
trace ("tcc_output_elf 91\n");
}
trace_exit ("tcc_output_elf");
}
/* Write an elf, coff or "binary" file */
@ -1980,18 +2232,24 @@ static int tcc_write_elf_file(TCCState *s1, const char *filename, int phnum,
int fd, mode, file_type;
FILE *f;
trace_enter ("tcc_write_elf_file");
file_type = s1->output_type;
if (file_type == TCC_OUTPUT_OBJ)
mode = 0666;
else
mode = 0777;
unlink(filename);
trace ("tcc_write_elf_file 06\n");
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
trace ("tcc_write_elf_file 07\n");
if (fd < 0) {
trace ("tcc_write_elf_file fd < 0\n");
tcc_error_noabort("could not write '%s'", filename);
return -1;
}
trace ("tcc_write_elf_file 09\n");
f = fdopen(fd, "wb");
trace ("tcc_write_elf_file 10\n");
if (s1->verbose)
printf("<- %s\n", filename);
@ -2006,6 +2264,7 @@ static int tcc_write_elf_file(TCCState *s1, const char *filename, int phnum,
tcc_output_binary(s1, f, sec_order);
fclose(f);
trace_exit ("tcc_write_elf_file");
return 0;
}
@ -2017,6 +2276,7 @@ static void tidy_section_headers(TCCState *s1, int *sec_order)
Section **snew, *s;
ElfW(Sym) *sym;
trace_enter ("tidy_section_headers");
snew = tcc_malloc(s1->nb_sections * sizeof(snew[0]));
backmap = tcc_malloc(s1->nb_sections * sizeof(backmap[0]));
for (i = 0, nnew = 0, l = s1->nb_sections; i < s1->nb_sections; i++) {
@ -2053,6 +2313,7 @@ static void tidy_section_headers(TCCState *s1, int *sec_order)
s1->sections = snew;
s1->nb_sections = nnew;
tcc_free(backmap);
trace_exit ("tidy_section_headers");
}
/* Output an elf, coff or binary file */
@ -2066,6 +2327,7 @@ static int elf_output_file(TCCState *s1, const char *filename)
Section *strsec, *interp, *dynamic, *dynstr;
int textrel;
trace_enter ("elf_output_file");
file_type = s1->output_type;
s1->nb_errors = 0;
ret = -1;
@ -2079,8 +2341,17 @@ static int elf_output_file(TCCState *s1, const char *filename)
tcc_add_runtime(s1);
resolve_common_syms(s1);
trace ("elf_output_file 12\n");
for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
trace ("elf_output_file num="); eputs (itoa (sym->st_shndx)); eputs ("\n");
name = (char *) strtab_section->data + sym->st_name;
trace ("elf_output_file name="); eputs (name); eputs ("\n");
}
if (!s1->static_link) {
trace ("elf_output_file 13\n");
if (file_type == TCC_OUTPUT_EXE) {
trace ("elf_output_file 14\n");
char *ptr;
/* allow override the dynamic loader */
const char *elfint = getenv("LD_SO");
@ -2092,6 +2363,7 @@ static int elf_output_file(TCCState *s1, const char *filename)
ptr = section_ptr_add(interp, 1 + strlen(elfint));
strcpy(ptr, elfint);
}
trace ("elf_output_file 20\n");
/* add dynamic symbol table */
s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
@ -2107,7 +2379,9 @@ static int elf_output_file(TCCState *s1, const char *filename)
build_got(s1);
trace ("elf_output_file 30\n");
if (file_type == TCC_OUTPUT_EXE) {
trace ("elf_output_file 31\n");
bind_exe_dynsyms(s1);
if (s1->nb_errors)
goto the_end;
@ -2159,6 +2433,7 @@ static int elf_output_file(TCCState *s1, const char *filename)
dynamic->sh_size = dynamic->data_offset;
dynstr->sh_size = dynstr->data_offset;
}
trace ("elf_output_file 50\n");
/* compute number of program headers */
if (file_type == TCC_OUTPUT_OBJ)
@ -2184,6 +2459,7 @@ static int elf_output_file(TCCState *s1, const char *filename)
file_offset = layout_sections(s1, phdr, phnum, interp, strsec, &dyninf,
sec_order);
trace ("elf_output_file 63\n");
/* Fill remaining program header and finalize relocation related to dynamic
linking. */
if (file_type != TCC_OUTPUT_OBJ) {
@ -2210,9 +2486,14 @@ static int elf_output_file(TCCState *s1, const char *filename)
/* if building executable or DLL, then relocate each section
except the GOT which is already relocated */
ret = final_sections_reloc(s1);
trace ("elf_output_file 82\n");
if (ret)
goto the_end;
#if !BOOTSTRAP
trace ("elf_output_file 83\n");
tidy_section_headers(s1, sec_order);
trace ("elf_output_file 84\n");
#endif
/* Perform relocation to GOT or PLT entries */
if (file_type == TCC_OUTPUT_EXE && s1->static_link)
@ -2221,12 +2502,17 @@ static int elf_output_file(TCCState *s1, const char *filename)
fill_local_got_entries(s1);
}
trace ("elf_output_file 90\n");
/* Create the ELF file with name 'filename' */
ret = tcc_write_elf_file(s1, filename, phnum, phdr, file_offset, sec_order);
trace ("elf_output_file 91\n");
s1->nb_sections = shnum;
the_end:
trace ("elf_output_file 92\n");
tcc_free(sec_order);
trace ("elf_output_file 93\n");
tcc_free(phdr);
trace_exit ("elf_output_file");
return ret;
}

545
tccgen.c

File diff suppressed because it is too large Load Diff

View File

@ -18,7 +18,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _TCC_H
#include "tcc.h"
#endif
#define PE_MERGE_DATA
/* #define PE_PRINT_SECTIONS */

441
tccpp.c

File diff suppressed because it is too large Load Diff

View File

@ -18,7 +18,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _TCC_H
#include "tcc.h"
#endif
/* only native compiler supports -run */
#ifdef TCC_IS_NATIVE

View File

@ -28,7 +28,9 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef _TCC_H
#include "tcc.h"
#endif
//#define ARMAG "!<arch>\n"
#define ARFMAG "`\n"

87
test.sh Executable file
View File

@ -0,0 +1,87 @@
#! /bin/sh
set -ex
TCC=${TCC-./mes-tcc}
MESCC=${MESCC-mescc}
MES_PREFIX=${MES_PREFIX-../mes}
MES_PREFIX=${MES_PREFIX-${MESCC%/*}}
MES_SEED=${MES_SEED-../mes-seed}
OBJDUMP=${OBJDUMP-objdump}
DIFF=${DIFF-diff}
unset C_INCLUDE_PATH LIBRARY_PATH
t=${1-$MES_PREFIX/scaffold/tests/t}
mkdir -p scaffold
b=scaffold/${t##*/}
rm -f "$b".i686-unknown-linux-gnu-out
rm -f "$b".mes-out
r=0
if [ -x ./i686-unknown-linux-gnu-tcc ]; then
./i686-unknown-linux-gnu-tcc\
-c\
-o "$b".mes-gcc-o\
-nostdlib\
-g\
-m32\
-D __TINYC__=1\
-I $MES_PREFIX/include\
-I $MES_PREFIX/scaffold/tests\
-I $MES_PREFIX/scaffold/tinycc\
"$t".c &> 1
#$OBJDUMP -d "$t".mes-gcc-o > 1.s
./i686-unknown-linux-gnu-tcc\
-static\
-o "$b".mes-gcc-out\
-L .\
-L $MES_SEED\
"$b".mes-gcc-o &> 1.link
set +e
"$b".mes-gcc-out arg1 arg2 arg3 arg4 arg5 > "$b".mes-gcc-stdout
m=$?
set -e
[ -f "$t".exit ] && r=$(cat "$t".exit)
[ $m = $r ]
if [ -f "$t".expect ]; then
$DIFF -ub "$t".expect "$b".mes-gcc-stdout;
fi
fi
$TCC\
-c\
-g\
-m32\
-o "$b".mes-o\
-D __TINYC__=1\
-I $MES_PREFIX/include\
-I $MES_PREFIX/scaffold/tests\
-I $MES_PREFIX/scaffold/tinycc\
"$t".c &> 2
$OBJDUMP -d "$b".mes-o > 2.s || true
$TCC\
-static\
-o "$b".mes-out\
-g\
-m32\
-D __TINYC__=1\
-I $MES_PREFIX/include\
-I $MES_PREFIX/scaffold/tests\
-I $MES_PREFIX/scaffold/tinycc\
-L $MES_SEED\
"$t".c &> 2.link
set +e
"$b".mes-out arg1 arg2 arg3 arg4 arg5 > "$b".mes-stdout
m=$?
#$OBJDUMP -d "$t".mes-out > 2.x
set -e
[ $m = $r ]
[ -f "$t".exit ] && r=$(cat "$t".exit)
if [ -f "$t".expect ]; then
$DIFF -ub "$t".expect "$b".mes-stdout;
fi
#diff -y 1.s 2.s
#diff -y 1 2

View File

@ -1,568 +0,0 @@
/*
* The information in this document is subject to change
* without notice and should not be construed as a commitment
* by Digital Equipment Corporation or by DECUS.
*
* Neither Digital Equipment Corporation, DECUS, nor the authors
* assume any responsibility for the use or reliability of this
* document or the described software.
*
* Copyright (C) 1980, DECUS
*
* General permission to copy or modify, but not for profit, is
* hereby granted, provided that the above copyright notice is
* included and reference made to the fact that reproduction
* privileges were granted by DECUS.
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h> // tolower()
/*
* grep
*
* Runs on the Decus compiler or on vms, On vms, define as:
* grep :== "$disk:[account]grep" (native)
* grep :== "$disk:[account]grep grep" (Decus)
* See below for more information.
*/
char *documentation[] = {
"grep searches a file for a given pattern. Execute by",
" grep [flags] regular_expression file_list\n",
"Flags are single characters preceded by '-':",
" -c Only a count of matching lines is printed",
" -f Print file name for matching lines switch, see below",
" -n Each line is preceded by its line number",
" -v Only print non-matching lines\n",
"The file_list is a list of files (wildcards are acceptable on RSX modes).",
"\nThe file name is normally printed if there is a file given.",
"The -f flag reverses this action (print name no file, not if more).\n",
0 };
char *patdoc[] = {
"The regular_expression defines the pattern to search for. Upper- and",
"lower-case are always ignored. Blank lines never match. The expression",
"should be quoted to prevent file-name translation.",
"x An ordinary character (not mentioned below) matches that character.",
"'\\' The backslash quotes any character. \"\\$\" matches a dollar-sign.",
"'^' A circumflex at the beginning of an expression matches the",
" beginning of a line.",
"'$' A dollar-sign at the end of an expression matches the end of a line.",
"'.' A period matches any character except \"new-line\".",
"':a' A colon matches a class of characters described by the following",
"':d' character. \":a\" matches any alphabetic, \":d\" matches digits,",
"':n' \":n\" matches alphanumerics, \": \" matches spaces, tabs, and",
"': ' other control characters, such as new-line.",
"'*' An expression followed by an asterisk matches zero or more",
" occurrences of that expression: \"fo*\" matches \"f\", \"fo\"",
" \"foo\", etc.",
"'+' An expression followed by a plus sign matches one or more",
" occurrences of that expression: \"fo+\" matches \"fo\", etc.",
"'-' An expression followed by a minus sign optionally matches",
" the expression.",
"'[]' A string enclosed in square brackets matches any character in",
" that string, but no others. If the first character in the",
" string is a circumflex, the expression matches any character",
" except \"new-line\" and the characters in the string. For",
" example, \"[xyz]\" matches \"xx\" and \"zyx\", while \"[^xyz]\"",
" matches \"abc\" but not \"axb\". A range of characters may be",
" specified by two characters separated by \"-\". Note that,",
" [a-z] matches alphabetics, while [z-a] never matches.",
"The concatenation of regular expressions is a regular expression.",
0};
#define LMAX 512
#define PMAX 256
#define CHAR 1
#define BOL 2
#define EOL 3
#define ANY 4
#define CLASS 5
#define NCLASS 6
#define STAR 7
#define PLUS 8
#define MINUS 9
#define ALPHA 10
#define DIGIT 11
#define NALPHA 12
#define PUNCT 13
#define RANGE 14
#define ENDPAT 15
int cflag=0, fflag=0, nflag=0, vflag=0, nfile=0, debug=0;
char *pp, lbuf[LMAX], pbuf[PMAX];
char *cclass();
char *pmatch();
void store(int);
void error(char *);
void badpat(char *, char *, char *);
int match(void);
/*** Display a file name *******************************/
void file(char *s)
{
printf("File %s:\n", s);
}
/*** Report unopenable file ****************************/
void cant(char *s)
{
fprintf(stderr, "%s: cannot open\n", s);
}
/*** Give good help ************************************/
void help(char **hp)
{
char **dp;
for (dp = hp; *dp; ++dp)
printf("%s\n", *dp);
}
/*** Display usage summary *****************************/
void usage(char *s)
{
fprintf(stderr, "?GREP-E-%s\n", s);
fprintf(stderr,
"Usage: grep [-cfnv] pattern [file ...]. grep ? for help\n");
exit(1);
}
/*** Compile the pattern into global pbuf[] ************/
void compile(char *source)
{
char *s; /* Source string pointer */
char *lp; /* Last pattern pointer */
int c; /* Current character */
int o; /* Temp */
char *spp; /* Save beginning of pattern */
s = source;
if (debug)
printf("Pattern = \"%s\"\n", s);
pp = pbuf;
while (c = *s++) {
/*
* STAR, PLUS and MINUS are special.
*/
if (c == '*' || c == '+' || c == '-') {
if (pp == pbuf ||
(o=pp[-1]) == BOL ||
o == EOL ||
o == STAR ||
o == PLUS ||
o == MINUS)
badpat("Illegal occurrence op.", source, s);
store(ENDPAT);
store(ENDPAT);
spp = pp; /* Save pattern end */
while (--pp > lp) /* Move pattern down */
*pp = pp[-1]; /* one byte */
*pp = (c == '*') ? STAR :
(c == '-') ? MINUS : PLUS;
pp = spp; /* Restore pattern end */
continue;
}
/*
* All the rest.
*/
lp = pp; /* Remember start */
switch(c) {
case '^':
store(BOL);
break;
case '$':
store(EOL);
break;
case '.':
store(ANY);
break;
case '[':
s = cclass(source, s);
break;
case ':':
if (*s) {
switch(tolower(c = *s++)) {
case 'a':
case 'A':
store(ALPHA);
break;
case 'd':
case 'D':
store(DIGIT);
break;
case 'n':
case 'N':
store(NALPHA);
break;
case ' ':
store(PUNCT);
break;
default:
badpat("Unknown : type", source, s);
}
break;
}
else badpat("No : type", source, s);
case '\\':
if (*s)
c = *s++;
default:
store(CHAR);
store(tolower(c));
}
}
store(ENDPAT);
store(0); /* Terminate string */
if (debug) {
for (lp = pbuf; lp < pp;) {
if ((c = (*lp++ & 0377)) < ' ')
printf("\\%o ", c);
else printf("%c ", c);
}
printf("\n");
}
}
/*** Compile a class (within []) ***********************/
char *cclass(char *source, char *src)
/* char *source; // Pattern start -- for error msg. */
/* char *src; // Class start */
{
char *s; /* Source pointer */
char *cp; /* Pattern start */
int c; /* Current character */
int o; /* Temp */
s = src;
o = CLASS;
if (*s == '^') {
++s;
o = NCLASS;
}
store(o);
cp = pp;
store(0); /* Byte count */
while ((c = *s++) && c!=']') {
if (c == '\\') { /* Store quoted char */
if ((c = *s++) == '\0') /* Gotta get something */
badpat("Class terminates badly", source, s);
else store(tolower(c));
}
else if (c == '-' &&
(pp - cp) > 1 && *s != ']' && *s != '\0') {
c = pp[-1]; /* Range start */
pp[-1] = RANGE; /* Range signal */
store(c); /* Re-store start */
c = *s++; /* Get end char and*/
store(tolower(c)); /* Store it */
}
else {
store(tolower(c)); /* Store normal char */
}
}
if (c != ']')
badpat("Unterminated class", source, s);
if ((c = (pp - cp)) >= 256)
badpat("Class too large", source, s);
if (c == 0)
badpat("Empty class", source, s);
*cp = c;
return(s);
}
/*** Store an entry in the pattern buffer **************/
void store(int op)
{
if (pp >= &pbuf[PMAX])
error("Pattern too complex\n");
*pp++ = op;
}
/*** Report a bad pattern specification ****************/
void badpat(char *message, char *source, char *stop)
/* char *message; // Error message */
/* char *source; // Pattern start */
/* char *stop; // Pattern end */
{
fprintf(stderr, "-GREP-E-%s, pattern is\"%s\"\n", message, source);
fprintf(stderr, "-GREP-E-Stopped at byte %ld, '%c'\n",
stop-source, stop[-1]);
error("?GREP-E-Bad pattern\n");
}
/*** Scan the file for the pattern in pbuf[] ***********/
void grep(FILE *fp, char *fn)
/* FILE *fp; // File to process */
/* char *fn; // File name (for -f option) */
{
int lno, count, m;
lno = 0;
count = 0;
while (fgets(lbuf, LMAX, fp)) {
++lno;
m = match();
if ((m && !vflag) || (!m && vflag)) {
++count;
if (!cflag) {
if (fflag && fn) {
file(fn);
fn = 0;
}
if (nflag)
printf("%d\t", lno);
printf("%s\n", lbuf);
}
}
}
if (cflag) {
if (fflag && fn)
file(fn);
printf("%d\n", count);
}
}
/*** Match line (lbuf) with pattern (pbuf) return 1 if match ***/
int match()
{
char *l; /* Line pointer */
for (l = lbuf; *l; ++l) {
if (pmatch(l, pbuf))
return(1);
}
return(0);
}
/*** Match partial line with pattern *******************/
char *pmatch(char *line, char *pattern)
/* char *line; // (partial) line to match */
/* char *pattern; // (partial) pattern to match */
{
char *l; /* Current line pointer */
char *p; /* Current pattern pointer */
char c; /* Current character */
char *e; /* End for STAR and PLUS match */
int op; /* Pattern operation */
int n; /* Class counter */
char *are; /* Start of STAR match */
l = line;
if (debug > 1)
printf("pmatch(\"%s\")\n", line);
p = pattern;
while ((op = *p++) != ENDPAT) {
if (debug > 1)
printf("byte[%ld] = 0%o, '%c', op = 0%o\n",
l-line, *l, *l, op);
switch(op) {
case CHAR:
if (tolower(*l++) != *p++)
return(0);
break;
case BOL:
if (l != lbuf)
return(0);
break;
case EOL:
if (*l != '\0')
return(0);
break;
case ANY:
if (*l++ == '\0')
return(0);
break;
case DIGIT:
if ((c = *l++) < '0' || (c > '9'))
return(0);
break;
case ALPHA:
c = tolower(*l++);
if (c < 'a' || c > 'z')
return(0);
break;
case NALPHA:
c = tolower(*l++);
if (c >= 'a' && c <= 'z')
break;
else if (c < '0' || c > '9')
return(0);
break;
case PUNCT:
c = *l++;
if (c == 0 || c > ' ')
return(0);
break;
case CLASS:
case NCLASS:
c = tolower(*l++);
n = *p++ & 0377;
do {
if (*p == RANGE) {
p += 3;
n -= 2;
if (c >= p[-2] && c <= p[-1])
break;
}
else if (c == *p++)
break;
} while (--n > 1);
if ((op == CLASS) == (n <= 1))
return(0);
if (op == CLASS)
p += n - 2;
break;
case MINUS:
e = pmatch(l, p); /* Look for a match */
while (*p++ != ENDPAT); /* Skip over pattern */
if (e) /* Got a match? */
l = e; /* Yes, update string */
break; /* Always succeeds */
case PLUS: /* One or more ... */
if ((l = pmatch(l, p)) == 0)
return(0); /* Gotta have a match */
case STAR: /* Zero or more ... */
are = l; /* Remember line start */
while (*l && (e = pmatch(l, p)))
l = e; /* Get longest match */
while (*p++ != ENDPAT); /* Skip over pattern */
while (l >= are) { /* Try to match rest */
if (e = pmatch(l, p))
return(e);
--l; /* Nope, try earlier */
}
return(0); /* Nothing else worked */
default:
printf("Bad op code %d\n", op);
error("Cannot happen -- match\n");
}
}
return(l);
}
/*** Report an error ***********************************/
void error(char *s)
{
fprintf(stderr, "%s", s);
exit(1);
}
/*** Main program - parse arguments & grep *************/
int main(int argc, char **argv)
{
char *p;
int c, i;
int gotpattern;
FILE *f;
if (argc <= 1)
usage("No arguments");
if (argc == 2 && argv[1][0] == '?' && argv[1][1] == 0) {
help(documentation);
help(patdoc);
return 0;
}
nfile = argc-1;
gotpattern = 0;
for (i=1; i < argc; ++i) {
p = argv[i];
if (*p == '-') {
++p;
while (c = *p++) {
switch(tolower(c)) {
case '?':
help(documentation);
break;
case 'C':
case 'c':
++cflag;
break;
case 'D':
case 'd':
++debug;
break;
case 'F':
case 'f':
++fflag;
break;
case 'n':
case 'N':
++nflag;
break;
case 'v':
case 'V':
++vflag;
break;
default:
usage("Unknown flag");
}
}
argv[i] = 0;
--nfile;
} else if (!gotpattern) {
compile(p);
argv[i] = 0;
++gotpattern;
--nfile;
}
}
if (!gotpattern)
usage("No pattern");
if (nfile == 0)
grep(stdin, 0);
else {
fflag = fflag ^ (nfile > 0);
for (i=1; i < argc; ++i) {
if (p = argv[i]) {
if ((f=fopen(p, "r")) == NULL)
cant(p);
else {
grep(f, p);
fclose(f);
}
}
}
}
return 0;
}
/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/

View File

@ -1,3 +0,0 @@
File 46_grep.c:
/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/