From 5ec0e6f84b47ebd8c269b581712666313f5edaef Mon Sep 17 00:00:00 2001 From: grischka Date: Sun, 21 Dec 2025 10:19:01 +0100 Subject: [PATCH] some reverts & fixes workflow: - revert 'pinact for security' for readability from 831c3fa184e3b4a93f09c7fd04170b022596aafd tccpp.c: - remove code that allows tcc to parse numbers incorrectly (*) from 829c84852012426230b0bec0efcfc1609bf4665b tccgen.c: - Revert "Relaxed the 'incompatible pointer type' warning a bit" (*) from d9ec17d33427fce6f73c5b5bb9646d3b077bb4e4. tccrun.c: - remove support for -nostdlib -run for simplicity, we require "main" with tcc -run always tccpp.c: - Revert "Free all preprocessor memmory in case of error." from c96f0cad61dbaa16c826879f65d5614e86eda8f2 Remove TinyAlloc->limit instead. Thus it can do also bigger allocs. Big TokenStrings (like 200kb+ when compiling tcc) may come from inline functions or from large initializers. Makefile/configure: - use --config-pie for configuring tcc output only - use -fPIC with clang-x86_64 to avoid 32-bit relocs libtcc.c: - fix "tcc file.c -run" i.e. -run as last argument i386-gen.c: - PIC refactor (*) sorry, but code in tcc should have a minimum of generic relevance --- .github/workflows/build.yml | 26 +- Makefile | 14 +- arm-asm.c | 5 +- arm-gen.c | 5 +- arm64-asm.c | 5 +- arm64-gen.c | 5 +- c67-gen.c | 5 +- configure | 2 +- i386-gen.c | 227 +++++-------- lib/Makefile | 11 +- lib/{get_pc_thunk.S => pic86.S} | 0 lib/run_nostdlib.c | 94 ------ libtcc.c | 15 +- riscv64-asm.c | 5 +- riscv64-gen.c | 5 +- tccasm.c | 29 +- tccelf.c | 6 - tccgen.c | 38 +-- tccpp.c | 367 ++++++++------------- tccrun.c | 33 +- tests/tests2/60_errors_and_warnings.c | 80 ----- tests/tests2/60_errors_and_warnings.expect | 42 --- x86_64-gen.c | 5 +- x86_64-link.c | 18 +- 24 files changed, 300 insertions(+), 742 deletions(-) rename lib/{get_pc_thunk.S => pic86.S} (100%) delete mode 100644 lib/run_nostdlib.c diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0f5a7193..2fbddce1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 2 steps: - - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + - uses: actions/checkout@v4 - name: make & test tcc (x86_64-linux) run: ./configure && make && make test -k @@ -17,7 +17,7 @@ jobs: runs-on: macos-15-intel timeout-minutes: 2 steps: - - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + - uses: actions/checkout@v4 - name: make & test tcc (x86_64-osx) run: ./configure && make && make test -k @@ -25,7 +25,7 @@ jobs: runs-on: macos-15 timeout-minutes: 2 steps: - - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + - uses: actions/checkout@v4 - name: make & test tcc (aarch64-osx) run: ./configure && make && make test -k @@ -33,7 +33,7 @@ jobs: runs-on: windows-2025 timeout-minutes: 6 steps: - - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + - uses: actions/checkout@v4 - name: make & test tcc (x86_64-win32) shell: cmd run: | @@ -44,7 +44,7 @@ jobs: C:\msys64\usr\bin\bash -l -c "pacman -S --noconfirm mingw-w64-x86_64-gcc" echo ::endgroup:: C:\msys64\usr\bin\bash -l -c "./configure && make && make test -k" - - uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # v1.13.0 + - uses: ilammy/msvc-dev-cmd@v1 with: arch: amd64 - name: build with MSVC (x86_64-win32) @@ -61,7 +61,7 @@ jobs: runs-on: windows-2025 timeout-minutes: 6 steps: - - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + - uses: actions/checkout@v4 - name: make & test tcc (i386-win32) shell: cmd run: | @@ -72,7 +72,7 @@ jobs: C:\msys64\usr\bin\bash -l -c "pacman -S --noconfirm mingw-w64-i686-gcc" echo ::endgroup:: C:\msys64\usr\bin\bash -l -c "./configure && make && make test -k" - - uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # v1.13.0 + - uses: ilammy/msvc-dev-cmd@v1 with: arch: x86 - name: build with MSVC (i386-win32) @@ -89,8 +89,8 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 8 steps: - - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 - - uses: uraimo/run-on-arch-action@d94c13912ea685de38fccc1109385b83fd79427d # v3.0.1 + - uses: actions/checkout@v4 + - uses: uraimo/run-on-arch-action@v3 name: make & test tcc (armv7-linux) with: arch: armv7 @@ -107,8 +107,8 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 8 steps: - - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 - - uses: uraimo/run-on-arch-action@d94c13912ea685de38fccc1109385b83fd79427d # v3.0.1 + - uses: actions/checkout@v4 + - uses: uraimo/run-on-arch-action@v3 name: make & test tcc (aarch64-linux) with: arch: aarch64 @@ -125,8 +125,8 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 8 steps: - - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 - - uses: uraimo/run-on-arch-action@d94c13912ea685de38fccc1109385b83fd79427d # v3.0.1 + - uses: actions/checkout@v4 + - uses: uraimo/run-on-arch-action@v3 name: make & test tcc (riscv64-linux) with: arch: riscv64 diff --git a/Makefile b/Makefile index 80f612bf..d21f1cad 100644 --- a/Makefile +++ b/Makefile @@ -24,11 +24,6 @@ CFLAGS += $(CPPFLAGS) VPATH = $(TOPSRC) -LTCC = $(TOP)/$(LIBTCC) -ifeq ($(CONFIG_pie),yes) -CFLAGS += -fPIE -LDFLAGS += -pie -endif - ifdef CONFIG_WIN32 CFG = -win ifneq ($(CONFIG_static),yes) @@ -296,6 +291,11 @@ tcc_p$(EXESUF): $($T_FILES) libtcc.a: $(LIBTCC_OBJ) $S$(AR) rcs $@ $^ +ifeq ($(CC_NAME)-$(ARCH),clang-x86_64) +# avoid 32-bit relocations in libtcc.a for its usage with tcc -run +libtcc.a: override CFLAGS += -fPIC +endif + # dynamic libtcc library libtcc.so: $(LIBTCC_OBJ) $S$(CC) -shared -Wl,-soname,$@ -o $@ $^ $(LIBS) $(LDFLAGS) @@ -372,7 +372,7 @@ IR = $(IM) mkdir -p $2 && cp -r $1/. $2 IM = @echo "-> $2 : $1" ; BINCHECK = $(if $(wildcard $(PROGS) *-tcc$(EXESUF)),,@echo "Makefile: nothing found to install" && exit 1) -EXTRA_O = runmain.o run_nostdlib.o bt-exe.o bt-dll.o bt-log.o bcheck.o get_pc_thunk.o +EXTRA_O = runmain.o bt-exe.o bt-dll.o bt-log.o bcheck.o # install progs & libs install-unx: @@ -394,7 +394,7 @@ endif # uninstall uninstall-unx: @rm -fv $(addprefix "$(bindir)/",$(PROGS) $(PROGS_CROSS)) - @rm -fv $(addprefix "$(libdir)/", libtcc*.a libtcc*.so libtcc.dylib,$P) + @rm -fv $(addprefix "$(libdir)/", libtcc*.a libtcc*.so libtcc.dylib) @rm -fv $(addprefix "$(includedir)/", libtcc.h) @rm -fv "$(mandir)/man1/tcc.1" "$(infodir)/tcc-doc.info" @rm -fv "$(docdir)/tcc-doc.html" diff --git a/arm-asm.c b/arm-asm.c index 417c7d04..2f9cca46 100644 --- a/arm-asm.c +++ b/arm-asm.c @@ -149,11 +149,8 @@ ST_FUNC void g(int c) if (nocode_wanted) return; ind1 = ind + 1; - if ((unsigned)ind1 > cur_text_section->data_allocated) { - if (ind1 < 0) - tcc_error("program too big"); + if (ind1 > cur_text_section->data_allocated) section_realloc(cur_text_section, ind1); - } cur_text_section->data[ind] = c; ind = ind1; } diff --git a/arm-gen.c b/arm-gen.c index eb44e22f..81fa185a 100644 --- a/arm-gen.c +++ b/arm-gen.c @@ -257,11 +257,8 @@ void o(uint32_t i) if (!cur_text_section) tcc_error("compiler error! This happens f.ex. if the compiler\n" "can't evaluate constant expressions outside of a function."); - if ((unsigned)ind1 > cur_text_section->data_allocated) { - if (ind1 < 0) - tcc_error("program too big"); + if (ind1 > cur_text_section->data_allocated) section_realloc(cur_text_section, ind1); - } cur_text_section->data[ind++] = i&255; i>>=8; cur_text_section->data[ind++] = i&255; diff --git a/arm64-asm.c b/arm64-asm.c index aa7e1ce4..a97fd642 100644 --- a/arm64-asm.c +++ b/arm64-asm.c @@ -31,11 +31,8 @@ ST_FUNC void g(int c) if (nocode_wanted) return; ind1 = ind + 1; - if ((unsigned)ind1 > cur_text_section->data_allocated) { - if (ind1 < 0) - tcc_error("program too big"); + if (ind1 > cur_text_section->data_allocated) section_realloc(cur_text_section, ind1); - } cur_text_section->data[ind] = c; ind = ind1; } diff --git a/arm64-gen.c b/arm64-gen.c index 5958f272..5bdc29e4 100644 --- a/arm64-gen.c +++ b/arm64-gen.c @@ -117,11 +117,8 @@ ST_FUNC void o(unsigned int c) int ind1 = ind + 4; if (nocode_wanted) return; - if ((unsigned)ind1 > cur_text_section->data_allocated) { - if (ind1 < 0) - tcc_error("program too big"); + if (ind1 > cur_text_section->data_allocated) section_realloc(cur_text_section, ind1); - } write32le(cur_text_section->data + ind, c); ind = ind1; } diff --git a/c67-gen.c b/c67-gen.c index ac8b3a01..ea8ab822 100644 --- a/c67-gen.c +++ b/c67-gen.c @@ -195,11 +195,8 @@ void C67_g(int c) fprintf(f, " %08X", c); #endif ind1 = ind + 4; - if ((unsigned)ind1 > (int) cur_text_section->data_allocated) { - if (ind1 < 0) - tcc_error("program too big"); + if (ind1 > (int) cur_text_section->data_allocated) section_realloc(cur_text_section, ind1); - } cur_text_section->data[ind] = c & 0xff; cur_text_section->data[ind + 1] = (c >> 8) & 0xff; cur_text_section->data[ind + 2] = (c >> 16) & 0xff; diff --git a/configure b/configure index f26a8ab8..c1abffc9 100755 --- a/configure +++ b/configure @@ -230,7 +230,7 @@ Advanced options (experts only): --config-new_dtags=yes use new ELF DTAGs (DT_RUNPATH instead of DT_RPATH) --config-codesign=no do not use codesign on apple to sign executables --config-dwarf=x use dwarf debug info instead of stabs (x=2..5) - --config-pie compile with pie + --config-pie let tcc generate position independent executables Cross build options (experimental): --cpu=CPU target CPU [$cpu] diff --git a/i386-gen.c b/i386-gen.c index 0a45fc7f..cabaaf09 100644 --- a/i386-gen.c +++ b/i386-gen.c @@ -48,7 +48,6 @@ enum { TREG_EBX, TREG_ST0, TREG_ESP = 4, - TREG_MEM = 0x20 }; @@ -90,22 +89,17 @@ ST_DATA const char * const target_machine_defs = "__i386\0" ; -/* define to 1/0 to [not] have EBX as 4th register */ -#define USE_EBX 0 #if defined CONFIG_TCC_PIC -#if USE_EBX > 0 -#error only USE_EBX or GOT_EBX can be set -#endif -#define GOT_EBX 1 +# define USE_EBX 2 #else -#define GOT_EBX 0 +# define USE_EBX 0 /* define to 1 to have EBX as 4th register */ #endif ST_DATA const int reg_classes[NB_REGS] = { /* eax */ RC_INT | RC_EAX, /* ecx */ RC_INT | RC_ECX, /* edx */ RC_INT | RC_EDX, - /* ebx */ (RC_INT | RC_EBX) * USE_EBX, + /* ebx */ (RC_INT | RC_EBX) * (USE_EBX == 1), /* st0 */ RC_FLOAT | RC_ST0, }; @@ -126,11 +120,8 @@ ST_FUNC void g(int c) if (nocode_wanted) return; ind1 = ind + 1; - if ((unsigned)ind1 > cur_text_section->data_allocated) { - if (ind1 < 0) - tcc_error("program too big"); + if (ind1 > cur_text_section->data_allocated) section_realloc(cur_text_section, ind1); - } cur_text_section->data[ind] = c; ind = ind1; } @@ -187,33 +178,23 @@ ST_FUNC void gen_fill_nops(int bytes) } #if defined CONFIG_TCC_PIC +static void gen_static_call(int v); static void get_pc_thunk(int r, int add) { - static const char *pc_thunk_name[] = { + static const char * const pc_thunk_name[] = { "__x86.get_pc_thunk.ax", "__x86.get_pc_thunk.cx", "__x86.get_pc_thunk.dx", "__x86.get_pc_thunk.bx" }; - int pc_thunk; - if (nocode_wanted) return; - - r = REG_VALUE(r); - pc_thunk = set_elf_sym(tcc_state->symtab, 0, 0, - ELFW(ST_INFO)(STB_GLOBAL, STT_FUNC), - ELFW(ST_VISIBILITY)(STV_HIDDEN), - SHN_UNDEF, pc_thunk_name[r]); - oad(0xe8, -4); /* call __x86.get_pc_thunk.rx */ - put_elf_reloc(symtab_section, cur_text_section, ind - 4, - R_386_PC32, pc_thunk); - + gen_static_call(tok_alloc_const(pc_thunk_name[r])); if (add) { Sym label = {0}; - - label.type.t = VT_VOID | VT_STATIC; + label.type.t = VT_VOID|VT_STATIC; put_extern_sym(&label, cur_text_section, ind, 0); + r = REG_VALUE(r); if (r == 0) oad(0x05, 1); /* add _GLOBAL_OFFSET_TABLE_, %eax */ else @@ -256,38 +237,37 @@ ST_FUNC void gen_addrpc32(int r, Sym *sym, int c) /* generate a modrm reference. 'op_reg' contains the additional 3 opcode bits */ -static void gen_modrm(int opc, int op_reg, int r, Sym *sym, int c) +static void gen_modrm(int opc, int op_r2, int r, Sym *sym, int c) { -#if defined CONFIG_TCC_PIC - int is_got = (op_reg & TREG_MEM) && !(sym->type.t & VT_STATIC); -#endif + int op_reg = REG_VALUE(op_r2) << 3; - op_reg = REG_VALUE(op_reg) << 3; +#if defined CONFIG_TCC_PIC + if ((r & (VT_VALMASK|VT_SYM)) == (VT_CONST|VT_SYM)) { + int is_got = (op_r2 & TREG_MEM) && !(sym->type.t & VT_STATIC); + int here = ind; + get_pc_thunk(TREG_EBX, is_got); + o(opc); + o(0x83 | op_reg); + if (is_got) { + gen_gotpcrel(r, sym, c); + } else { + gen_addrpc32(r, sym, c + (ind - here - 1)); + } + } else if ((r & VT_VALMASK) < VT_CONST && (r & TREG_MEM)) { + o(opc); + if (c) { + g(0x80 | op_reg | REG_VALUE(r)); + gen_le32(c); + } else { + g(0x00 | op_reg | REG_VALUE(r)); + } + } else +#endif if ((r & VT_VALMASK) == VT_CONST) { /* constant memory reference */ -#if defined CONFIG_TCC_PIC - if (r & VT_SYM) { - get_pc_thunk(TREG_EBX, is_got); - o(opc); - o(0x83 | op_reg); - if (is_got) - gen_gotpcrel(r, sym, c); - else { - int off = 6; - - off += opc & 0xff00 ? 1 : 0; - off += opc & 0xff0000 ? 1 : 0; - off += opc & 0xff000000 ? 1 : 0; - gen_addrpc32(r, sym, c + off); - } - } - else -#endif - { - o(opc); - o(0x05 | op_reg); - gen_addr32(r, sym, c); - } + o(opc); + o(0x05 | op_reg); + gen_addr32(r, sym, c); } else if ((r & VT_VALMASK) == VT_LOCAL) { o(opc); /* currently, we use only ebp as base */ @@ -298,14 +278,6 @@ static void gen_modrm(int opc, int op_reg, int r, Sym *sym, int c) } else { oad(0x85 | op_reg, c); } - } else if ((r & VT_VALMASK) >= TREG_MEM) { - o(opc); - if (c) { - g(0x80 | op_reg | REG_VALUE(r)); - gen_le32(c); - } else { - g(0x00 | op_reg | REG_VALUE(r)); - } } else { o(opc); g(0x00 | op_reg | (r & VT_VALMASK)); @@ -321,14 +293,13 @@ ST_FUNC void load(int r, SValue *sv) fr = sv->r; ft = sv->type.t & ~VT_DEFSIGN; fc = sv->c.i; - ft &= ~(VT_VOLATILE | VT_CONSTANT); + v = fr & VT_VALMASK; -#ifndef TCC_TARGET_PE #if defined CONFIG_TCC_PIC /* we use indirect access via got */ - if ((fr & VT_VALMASK) == VT_CONST && (fr & VT_SYM) && - (fr & VT_LVAL) && !(sv->sym->type.t & VT_STATIC)) { + if ((fr & (VT_VALMASK|VT_SYM|VT_LVAL)) == (VT_CONST|VT_SYM|VT_LVAL) + && !(sv->sym->type.t & VT_STATIC)) { /* use the result register as a temporal register */ int tr = r | TREG_MEM; if (is_float(ft)) { @@ -336,14 +307,11 @@ ST_FUNC void load(int r, SValue *sv) tr = get_reg(RC_INT) | TREG_MEM; } gen_modrm(0x8b, tr, fr, sv->sym, 0); - /* load from the temporal register */ fr = tr | VT_LVAL; } -#endif #endif - v = fr & VT_VALMASK; if (fr & VT_LVAL) { if (v == VT_LLOCAL) { v1.type.t = VT_INT; @@ -378,26 +346,23 @@ ST_FUNC void load(int r, SValue *sv) } gen_modrm(opc, r, fr, sv->sym, fc); } else { - if (v == VT_CONST) { #if defined CONFIG_TCC_PIC - if (fr & VT_SYM) { - if (sv->sym->type.t & VT_STATIC) { - get_pc_thunk(r, 0); - o(0x808d | REG_VALUE(r) * 0x900); /* lea $xx(r), r */ - gen_addrpc32(fr, sv->sym, fc + 6); - } - else { - get_pc_thunk(r, 1); - o(0x808b | REG_VALUE(r) * 0x900); /* mov $xx(r), r */ - gen_gotpcrel(r, sv->sym, fc); - } - } - else + if ((fr & (VT_VALMASK|VT_SYM)) == (VT_CONST|VT_SYM)) { + if (sv->sym->type.t & VT_STATIC) { + get_pc_thunk(r, 0); + o(0x808d | REG_VALUE(r) * 0x900); /* lea $xx(r), r */ + gen_addrpc32(fr, sv->sym, fc + 6); + } else { + get_pc_thunk(r, 1); + o(0x808b | REG_VALUE(r) * 0x900); /* mov $xx(r), r */ + gen_gotpcrel(r, sv->sym, fc); + } + } else + #endif - { - o(0xb8 + r); /* mov $xx, r */ - gen_addr32(fr, sv->sym, fc); - } + if (v == VT_CONST) { + o(0xb8 + r); /* mov $xx, r */ + gen_addr32(fr, sv->sym, fc); } else if (v == VT_LOCAL) { if (fc) { /* lea xxx(%ebp), r */ @@ -427,27 +392,9 @@ ST_FUNC void load(int r, SValue *sv) /* store register 'r' in lvalue 'v' */ ST_FUNC void store(int r, SValue *v) { - int fr, bt, ft, fc, opc, pic = 0; + int fr, bt, fc, opc; - ft = v->type.t; - fc = v->c.i; - fr = v->r & VT_VALMASK; - ft &= ~(VT_VOLATILE | VT_CONSTANT); - bt = ft & VT_BTYPE; - -#ifndef TCC_TARGET_PE -#if defined CONFIG_TCC_PIC - /* we need to access the variable via got */ - if (fr == VT_CONST - && (v->r & VT_SYM) - && !(v->sym->type.t & VT_STATIC)) { - get_pc_thunk(TREG_EBX, 1); - o(0x9b8b); /* mov xx(%ebx),%ebx */ - gen_gotpcrel(TREG_EBX, v->sym, v->c.i); - pic = 1; - } -#endif -#endif + bt = v->type.t & VT_BTYPE; /* XXX: incorrect if float reg to reg */ if (bt == VT_FLOAT) { @@ -459,26 +406,35 @@ ST_FUNC void store(int r, SValue *v) } else if (bt == VT_LDOUBLE) { opc = 0xdbc0d9; /* fld %st(0), fstpt */ r = 7; - } else if (bt == VT_SHORT) + } else if (bt == VT_SHORT) { opc = 0x8966; - else if (bt == VT_BYTE || bt == VT_BOOL) + } else if (bt == VT_BYTE || bt == VT_BOOL) { opc = 0x88; - else + } else { opc = 0x89; - if (pic) { + } + + fc = v->c.i; + fr = v->r & VT_VALMASK; + +#if defined CONFIG_TCC_PIC + /* we need to access the variable via got */ + if ((v->r & (VT_VALMASK|VT_SYM)) == (VT_CONST|VT_SYM) + && !(v->sym->type.t & VT_STATIC)) { + get_pc_thunk(TREG_EBX, 1); + o(0x9b8b); /* mov xx(%ebx),%ebx */ + gen_gotpcrel(TREG_EBX, v->sym, v->c.i); o(opc); o(3 + (r << 3)); - } - else if (fr == VT_CONST || - fr == VT_LOCAL || - (v->r & VT_LVAL)) { - gen_modrm(opc, r, v->r, v->sym, fc); + } else +#endif + + if (fr == VT_CONST || fr == VT_LOCAL || (v->r & VT_LVAL)) { + gen_modrm(opc, r, v->r, v->sym, fc); } else if (fr != r) { o(opc); o(0xc0 + fr + r * 8); /* mov r, fr */ } - else - tcc_error("store problem"); } static void gadd_sp(int val) @@ -491,20 +447,14 @@ static void gadd_sp(int val) } } -#if defined CONFIG_TCC_BCHECK || defined TCC_TARGET_PE +#if defined CONFIG_TCC_BCHECK || defined TCC_TARGET_PE || defined CONFIG_TCC_PIC static void gen_static_call(int v) { Sym *sym; sym = external_helper_sym(v); -#if defined CONFIG_TCC_PIC - get_pc_thunk(TREG_EBX, 1); - oad(0xe8, -4); - greloc(cur_text_section, sym, ind - 4, R_386_PLT32); -#else oad(0xe8, -4); greloc(cur_text_section, sym, ind - 4, R_386_PC32); -#endif } #endif @@ -512,22 +462,18 @@ static void gen_static_call(int v) static void gcall_or_jmp(int is_jmp) { int r; - if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST && (vtop->r & VT_SYM)) { + if ((vtop->r & (VT_VALMASK|VT_LVAL|VT_SYM)) == (VT_CONST|VT_SYM)) { /* constant and relocation case */ #if defined CONFIG_TCC_PIC - if (vtop->sym->type.t & VT_STATIC) { - oad(0xe8 + is_jmp, vtop->c.i - 4); /* call/jmp im */ - greloc(cur_text_section, vtop->sym, ind - 4, R_386_PC32); - } - else { + if (!(vtop->sym->type.t & VT_STATIC)) { get_pc_thunk(TREG_EBX, 1); oad(0xe8 + is_jmp, vtop->c.i - 4); /* call/jmp im */ greloc(cur_text_section, vtop->sym, ind - 4, R_386_PLT32); + return; } -#else - greloc(cur_text_section, vtop->sym, ind + 1, R_386_PC32); - oad(0xe8 + is_jmp, vtop->c.i - 4); /* call/jmp im */ #endif + oad(0xe8 + is_jmp, vtop->c.i - 4); /* call/jmp im */ + greloc(cur_text_section, vtop->sym, ind - 4, R_386_PC32); } else { /* otherwise, indirect call */ r = gv(RC_INT); @@ -679,9 +625,9 @@ ST_FUNC void gfunc_call(int nb_args) } #ifdef TCC_TARGET_PE -#define FUNC_PROLOG_SIZE (10 + USE_EBX) +#define FUNC_PROLOG_SIZE (10 + !!USE_EBX) #else -#define FUNC_PROLOG_SIZE (9 + (USE_EBX || GOT_EBX)) +#define FUNC_PROLOG_SIZE (9 + !!USE_EBX) #endif /* generate function prolog of type 't' */ @@ -786,7 +732,6 @@ ST_FUNC void gfunc_epilog(void) #if USE_EBX gen_modrm(0x8b, TREG_EBX, VT_LOCAL, NULL, -(v+4)); #endif - o(0x5b * GOT_EBX); /* pop ebx */ o(0xc9); /* leave */ if (func_ret_sub == 0) { @@ -812,7 +757,9 @@ ST_FUNC void gfunc_epilog(void) o(0x90); /* adjust to FUNC_PROLOG_SIZE */ #endif } - o(0x53 * (USE_EBX || GOT_EBX)); /* push ebx */ +#if USE_EBX + o(0x53); /* push ebx */ +#endif ind = saved_ind; } diff --git a/lib/Makefile b/lib/Makefile index be596d8f..5357e25f 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -35,7 +35,7 @@ endif XFLAGS += -I$(TOP) -I386_O = libtcc1.o get_pc_thunk.o $(COMMON_O) +I386_O = libtcc1.o $(COMMON_O) X86_64_O = libtcc1.o $(COMMON_O) ARM_O = libtcc1.o armeabi.o armflush.o $(COMMON_O) ARM64_O = lib-arm64.o $(COMMON_O) @@ -50,15 +50,15 @@ Nat = $(if $X,no,) Cbt = $(Nat)$(subst yes,,$(CONFIG_backtrace)) Cbc = $(Cbt)$(subst yes,,$(CONFIG_bcheck)) -$(Nat)COMMON_O += runmain.o run_nostdlib.o tcov.o +$(Nat)COMMON_O += runmain.o tcov.o $(Cbt)COMMON_O += bt-exe.o bt-log.o $(Cbt)WIN_O += bt-dll.o $(Cbc)COMMON_O += bcheck.o # not in libtcc1.a -EXTRA_O = runmain.o run_nostdlib.o bt-exe.o bt-dll.o bt-log.o bcheck.o get_pc_thunk.o +EXTRA_O = runmain.o bt-exe.o bt-dll.o bt-log.o bcheck.o -OBJ-i386 = $(I386_O) $(LIN_O) +OBJ-i386 = $(I386_O) pic86.o $(LIN_O) OBJ-x86_64 = $(X86_64_O) $(LIN_O) OBJ-x86_64-osx = $(X86_64_O) $(OSX_O) OBJ-i386-win32 = $(I386_O) chkstk.o $(WIN_O) @@ -90,9 +90,6 @@ $(X)%.o : %.c $(TCC) $(X)%.o : %.S $(TCC) $S$(XCC) -c $< -o $@ $(XFLAGS) -$(TOP)/%.o : %.S $(TCC) - $S$(XCC) -c $< -o $@ $(XFLAGS) - $(TOP)/%.o : %.c $(TCC) $S$(XCC) -c $< -o $@ $(XFLAGS) diff --git a/lib/get_pc_thunk.S b/lib/pic86.S similarity index 100% rename from lib/get_pc_thunk.S rename to lib/pic86.S diff --git a/lib/run_nostdlib.c b/lib/run_nostdlib.c deleted file mode 100644 index 91a7b043..00000000 --- a/lib/run_nostdlib.c +++ /dev/null @@ -1,94 +0,0 @@ -/* ------------------------------------------------------------- */ -/* support for run_nostdlib() */ - -// FIXME: implement arm64 assembler -#if defined(__aarch64__) -#define USE_ARM64_ASM -static void *alloca_arm64(unsigned long); -__asm__( -#ifdef __leading_underscore - "_alloca_arm64:\n\t" -#else - "alloca_arm64:\n\t" -#endif - ".int 0x91003c00\n\t" // add x0, x0, #15 - ".int 0x927cec00\n\t" // and x0, x0, #-16 - ".int 0xcb2063ff\n\t" // sub sp, sp, x0 - ".int 0x910003e0\n\t" // mov x0, sp - ".int 0xd65f03c0" // ret -); -static void goto_arm64(void *start); -__asm__( -#ifdef __leading_underscore - "_goto_arm64:\n\t" -#else - "goto_arm64:\n\t" -#endif - ".int 0xd61f0000" // br x0 -); -#endif - -void _run_nostdlib(void *start, int argc, char **argv, char **envp) -{ -#if !defined(_WIN32) - int i, n = 1; - unsigned long l; - char **sp, **e = envp; - - if (envp) - while (*e++) - n++; - l = (((unsigned long) argc + n + 2 + 1) & -2) * sizeof(char *); - /* nostdlib so avoid alloca() */ - /* also code below will be removed because compiler detects dead store */ -#if defined(USE_ARM64_ASM) - sp = alloca_arm64(l); -#else -#if defined(__aarch64__) - __asm__("sub sp, sp, %1\n" - "\tmov %0, sp" -#elif defined(__arm__) - __asm__("sub sp, sp, %1\n" - "\tmov %0, sp" -#elif defined(__i386__) - __asm("sub %1, %%esp\n" - "\tmov %%esp, %0" -#elif defined(__riscv) - __asm__("sub sp, sp, %1\n" - "\tmv %0, sp" -#elif defined(__x86_64__) - __asm__("subq %1, %%rsp\n" - "\tmovq %%rsp, %0" -#endif - : "=r" (sp) - : "r" (l)); -#endif - /* create sysv memory layout: argc, argv[], NULL, envp[], NULL */ - sp[0] = (char *) (__SIZE_TYPE__) argc; - for (i = 0; i < argc; i++) - sp[i + 1] = argv[i]; - sp[argc + 1] = (char *) 0; - if (envp) - for (i = 0; i < n; i++) - sp[i + argc + 2] = envp[i]; - else - sp[argc + 2] = (char *) 0; -#endif - - /* goto *start does not work for clang. Use assembly. */ -#if defined(USE_ARM64_ASM) - goto_arm64(start); -#else -#if defined(__aarch64__) - __asm__("br %0" : : "r" (start)); -#elif defined(__arm__) - __asm__("mov pc, %0" : : "r" (start)); -#elif defined(__i386__) - __asm__("jmp *%0" : : "r" (start)); -#elif defined(__riscv) - __asm__("jalr %0" : : "r" (start)); -#elif defined(__x86_64__) - __asm__("jmp *%0" : : "r" (start)); -#endif -#endif -} diff --git a/libtcc.c b/libtcc.c index f8a749db..171e3622 100644 --- a/libtcc.c +++ b/libtcc.c @@ -1899,13 +1899,8 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int *pargc, char ***pargv) args_parser_add_file(s, r, s->filetype); empty = 0; dorun: - if (run) { - /* tcc -run */ - if (tcc_set_options(s, run) < 0) - return -1; - x = 0; - goto extra_action; - } + if (run) + break; continue; } /* Also allow "tcc -run -- " */ @@ -2219,6 +2214,12 @@ unsupported_option: } if (s->link_optind < s->link_argc) return tcc_error_noabort("argument to '-Wl,%s' is missing", s->link_argv[s->link_optind]); + if (run) { + if (*run && tcc_set_options(s, run) < 0) + return -1; + x = 0; + goto extra_action; + } if (!empty) return 0; if (s->verbose == 2) diff --git a/riscv64-asm.c b/riscv64-asm.c index 2cb3b866..74cf4452 100644 --- a/riscv64-asm.c +++ b/riscv64-asm.c @@ -98,11 +98,8 @@ ST_FUNC void g(int c) if (nocode_wanted) return; ind1 = ind + 1; - if ((unsigned)ind1 > cur_text_section->data_allocated) { - if (ind1 < 0) - tcc_error("program too big"); + if (ind1 > cur_text_section->data_allocated) section_realloc(cur_text_section, ind1); - } cur_text_section->data[ind] = c; ind = ind1; } diff --git a/riscv64-gen.c b/riscv64-gen.c index 750eea80..19c76682 100644 --- a/riscv64-gen.c +++ b/riscv64-gen.c @@ -115,11 +115,8 @@ ST_FUNC void o(unsigned int c) int ind1 = ind + 4; if (nocode_wanted) return; - if ((unsigned)ind1 > cur_text_section->data_allocated) { - if (ind1 < 0) - tcc_error("program too big"); + if (ind1 > cur_text_section->data_allocated) section_realloc(cur_text_section, ind1); - } write32le(cur_text_section->data + ind, c); ind = ind1; } diff --git a/tccasm.c b/tccasm.c index c8040ef6..523cbab0 100644 --- a/tccasm.c +++ b/tccasm.c @@ -684,17 +684,14 @@ static void asm_parse_directive(TCCState *s1, int global) next(); asm_expr(s1, &e); n = e.v; - if (n != e.v || n < 0) - range: - tcc_error(".org out of range"); esym = elfsym(e.sym); if (esym) { if (esym->st_shndx != cur_text_section->sh_num) expect("constant or same-section symbol"); n += esym->st_value; - if (n < esym->st_value) - goto range; } + if (n < 0 || n > 0x100000) + tcc_error(".org out of range"); if (n < ind) tcc_error("attempt to .org backwards"); v = 0; @@ -719,8 +716,8 @@ static void asm_parse_directive(TCCState *s1, int global) do { Sym *sym; next(); - if (tok < TOK_IDENT || tok >= SYM_FIRST_ANOM) - tcc_error("Illegal symbol %s", get_tok_str(tok1, NULL)); + if (tok < TOK_IDENT) + expect("identifier"); sym = get_asm_sym(tok, NULL); if (tok1 != TOK_ASMDIR_hidden) sym->type.t &= ~VT_STATIC; @@ -816,15 +813,12 @@ static void asm_parse_directive(TCCState *s1, int global) { Sym *sym; - tok1 = tok; next(); - if (tok < TOK_IDENT || tok >= SYM_FIRST_ANOM) - goto nolab; + if (tok < TOK_IDENT) + expect("identifier"); sym = asm_label_find(tok); - if (!sym) { - nolab: - tcc_error("label not found: %s", get_tok_str(tok1, NULL)); - } + if (!sym) + tcc_error("label not found: %s", get_tok_str(tok, NULL)); /* XXX .size name,label2-label1 */ tcc_warning_c(warn_unsupported)("ignoring .size %s,*", get_tok_str(tok, NULL)); next(); @@ -840,10 +834,9 @@ static void asm_parse_directive(TCCState *s1, int global) const char *newtype; int st_type; - tok1 = tok; next(); - if (tok < TOK_IDENT || tok >= SYM_FIRST_ANOM) - tcc_error("Illegal symbol %s", get_tok_str(tok1, NULL)); + if (tok < TOK_IDENT) + expect("identifier"); sym = get_asm_sym(tok, NULL); next(); skip(','); @@ -1192,7 +1185,7 @@ static void subst_asm_operands(ASMOperand *operands, int nb_operands, modifier = *str++; index = find_constraint(operands, nb_operands, str, &str); if (index < 0) - error: + error: tcc_error("invalid operand reference after %%"); op = &operands[index]; if (modifier == 'l') { diff --git a/tccelf.c b/tccelf.c index 6b671c56..76cd0585 100644 --- a/tccelf.c +++ b/tccelf.c @@ -1840,9 +1840,6 @@ ST_FUNC void tcc_add_runtime(TCCState *s1) tcc_add_dll(s1, TCC_LIBGCC, AFF_PRINT_ERROR); } #endif -#if defined CONFIG_TCC_PIC && defined TCC_TARGET_I386 - tcc_add_support(s1, "get_pc_thunk.o"); -#endif #if defined TCC_TARGET_ARM && TARGETOS_FreeBSD tcc_add_library(s1, "gcc_s"); // unwind code #endif @@ -3103,9 +3100,6 @@ LIBTCCAPI int elf_output_obj(TCCState *s1, const char *filename) { Section *s; int i, ret, file_offset; - for(i = 1; i < s1->nb_sections; i++) - if (s1->sections[i] == NULL) - return -2; /* debugging and TCC_OUTPUT_MEMORY and do_debug = 0 */ /* Allocate strings for section names */ alloc_sec_names(s1, 1); file_offset = (sizeof (ElfW(Ehdr)) + 3) & -4; diff --git a/tccgen.c b/tccgen.c index 6519a46b..6d42de67 100644 --- a/tccgen.c +++ b/tccgen.c @@ -3589,8 +3589,7 @@ static void cast_error(CType *st, CType *dt) static void verify_assign_cast(CType *dt) { CType *st, *type1, *type2; - Sym *sym; - int dbt, sbt, qualwarn, lvl, compat; + int dbt, sbt, qualwarn, lvl; st = &vtop->type; /* source type */ dbt = dt->t & VT_BTYPE; @@ -3644,29 +3643,8 @@ static void verify_assign_cast(CType *dt) base types, though, in particular for unsigned enums and signed int targets. */ } else { - compat = 0; - /* Don't warn if the source struct (recursively) contains - destination struct as the first member. */ - if (dbt == VT_STRUCT && sbt == VT_STRUCT - && !IS_UNION(type2->t) - ) { - sym = type2->ref->next; - while (sym != NULL && (sym->type.t & VT_BTYPE) == VT_STRUCT - ) { - if (is_compatible_unqualified_types(type1, &sym->type) - ) { - compat = 1; - break; - } - if (IS_UNION(sym->type.t)) - break; - sym = sym->type.ref->next; - } - } - if( !compat ) { - tcc_warning("assignment from incompatible pointer type"); - break; - } + tcc_warning("assignment from incompatible pointer type"); + break; } } if (qualwarn) @@ -7837,9 +7815,6 @@ static void init_putv(init_params *p, CType *type, unsigned long c) ElfW_Rel *rel; esym = elfsym(vtop->sym); ssec = tcc_state->sections[esym->st_shndx]; - if (esym->st_value + (int)vtop->c.i + size > ssec->data_offset) - section_add(ssec, esym->st_value + (int)vtop->c.i + - size - ssec->data_offset, 1); memmove (ptr, ssec->data + esym->st_value + (int)vtop->c.i, size); if (ssec->reloc) { /* We need to copy over all memory contents, and that @@ -8745,13 +8720,8 @@ static int decl(int l) while (1) { /* iterate thru each declaration */ type = btype; ad = adbase; - if (l == VT_CMP) { - type_decl(&type, &ad, &v, TYPE_DIRECT | TYPE_PARAM); - } else { - type_decl(&type, &ad, &v, TYPE_DIRECT); - } + type_decl(&type, &ad, &v, l == VT_CMP ? TYPE_DIRECT | TYPE_PARAM : TYPE_DIRECT); /*ptype("decl", &type, v);*/ - if ((type.t & VT_BTYPE) == VT_FUNC) { if ((type.t & VT_STATIC) && (l != VT_CONST)) tcc_error("function without file scope cannot be static"); diff --git a/tccpp.c b/tccpp.c index b30df5ad..e19e8504 100644 --- a/tccpp.c +++ b/tccpp.c @@ -115,89 +115,49 @@ ST_FUNC void expect(const char *msg) /* ------------------------------------------------------------------------- */ /* Custom allocator for tiny objects */ -#define PP_ALLOC_INSERT(a) (a)->next = &pp_allocs; \ - (a)->prev = pp_allocs.prev; \ - pp_allocs.prev->next = (a); \ - pp_allocs.prev = (a); -#define PP_ALLOC_REMOVE(a) (a)->next->prev = (a)->prev; \ - (a)->prev->next = (a)->next; - -typedef struct pp_alloc_t { - struct pp_alloc_t *next, *prev; -} pp_alloc_t; - -static pp_alloc_t pp_allocs; - #define USE_TAL -#ifndef USE_TAL -#define tal_free(al, p) tcc_free_impl(p) -#define tal_realloc(al, p, size) tcc_realloc_impl(p, size) -#define tal_new(a,b,c) +#ifndef USE_TAL /* may cause memory leaks after errors */ +#define tal_free(al, p) tcc_free(p) +#define tal_realloc(al, p, size) tcc_realloc(p, size) +#define tal_new(a,b) #define tal_delete(a) - -static void tcc_free_impl(void *p) -{ - if (p) { - pp_alloc_t *alloc = ((pp_alloc_t *)p) - 1; - - PP_ALLOC_REMOVE(alloc); - tcc_free(alloc); - } -} - -static void *tcc_realloc_impl(void *p, unsigned size) -{ - pp_alloc_t *alloc = NULL; - - if (p) { - alloc = ((pp_alloc_t *)p) - 1; - PP_ALLOC_REMOVE(alloc); - } - if (size) { - alloc = tcc_realloc(alloc, size + sizeof(pp_alloc_t)); - PP_ALLOC_INSERT(alloc); - return alloc + 1; - } - tcc_free(alloc); - return NULL; -} #else #if !defined(MEM_DEBUG) #define tal_free(al, p) tal_free_impl(al, p) -#define tal_realloc(al, p, size) tal_realloc_impl(&al, p, size) +#define tal_realloc(al, p, size) tal_realloc_impl(al, p, size) #define TAL_DEBUG_PARAMS #else #define TAL_DEBUG MEM_DEBUG //#define TAL_INFO 1 /* collect and dump allocators stats */ #define tal_free(al, p) tal_free_impl(al, p, __FILE__, __LINE__) -#define tal_realloc(al, p, size) tal_realloc_impl(&al, p, size, __FILE__, __LINE__) -#define TAL_DEBUG_PARAMS , const char *file, int line +#define tal_realloc(al, p, size) tal_realloc_impl(al, p, size, __FILE__, __LINE__) +#define TAL_DEBUG_PARAMS , const char *sfile, int sline #endif -#define TOKSYM_TAL_SIZE (768 * 1024) /* allocator for tiny TokenSym in table_ident */ -#define TOKSTR_TAL_SIZE (768 * 1024) /* allocator for tiny TokenString instances */ -#define TOKSYM_TAL_LIMIT 256 /* prefer unique limits to distinguish allocators debug msgs */ -#define TOKSTR_TAL_LIMIT 1024 /* 256 * sizeof(int) */ +#define TOKSYM_TAL_SIZE (256 * 1024) /* allocator for TokenSym in table_ident */ +#define TOKSTR_TAL_SIZE (256 * 1024) /* allocator for TokenString instances */ typedef struct TinyAlloc { - unsigned limit; - unsigned size; - uint8_t *buffer; uint8_t *p; - unsigned nb_allocs; - struct TinyAlloc *next, *top; -#ifdef TAL_INFO - unsigned nb_peak; - unsigned nb_total; - unsigned nb_missed; + uint8_t *bufend; + struct TinyAlloc *next; + unsigned nb_allocs; + unsigned size; +#if TAL_INFO + unsigned nb_peak; + unsigned nb_total; uint8_t *peak_p; #endif + union { + uint8_t buffer[1]; + size_t _aligner_; + }; } TinyAlloc; typedef struct tal_header_t { size_t size; /* word align */ -#ifdef TAL_DEBUG +#if TAL_DEBUG int line_num; /* negative line_num used for double free check */ char file_name[40]; #endif @@ -208,33 +168,39 @@ typedef struct tal_header_t { /* ------------------------------------------------------------------------- */ -static TinyAlloc *tal_new(TinyAlloc **pal, unsigned limit, unsigned size) +static TinyAlloc *tal_new(TinyAlloc **pal, unsigned size) { - TinyAlloc *al = tcc_mallocz(sizeof(TinyAlloc)); - al->p = al->buffer = tcc_malloc(size); - al->limit = limit; - al->size = size; - if (pal) *pal = al; + TinyAlloc *al = tcc_malloc(sizeof(TinyAlloc) - sizeof (size_t) + size); + al->p = al->buffer; + al->bufend = al->buffer + size; + al->nb_allocs = 0; + al->next = *pal, *pal = al; + al->size = al->next ? al->next->size : size; +#if TAL_INFO + al->nb_peak = 0; + al->nb_total = 0; + al->peak_p = al->p; +#endif return al; } -static void tal_delete(TinyAlloc *al) +static void tal_delete(TinyAlloc **pal) { - TinyAlloc *next; + TinyAlloc *al = *pal, *next; -tail_call: - if (!al) - return; -#ifdef TAL_INFO - fprintf(stderr, "limit %4d size %7d nb_peak %5d nb_total %7d nb_missed %5d usage %5.1f%%\n", - al->limit, al->size, al->nb_peak, al->nb_total, al->nb_missed, - (al->peak_p - al->buffer) * 100.0 / al->size); +#if TAL_INFO + fprintf(stderr, "tal_delete (&tok%s_alloc):\n", pal == &toksym_alloc ? "sym" : "str"); #endif +tail_call: #if TAL_DEBUG && TAL_DEBUG != 3 /* do not check TAL leaks with -DMEM_DEBUG=3 */ +#if TAL_INFO + fprintf(stderr, " size %7d nb_peak %5d nb_total %6d usage %5.1f%%\n", + al->bufend - al->buffer, al->nb_peak, al->nb_total, + (al->peak_p - al->buffer) * 100.0 / (al->bufend - al->buffer)); +#endif if (al->nb_allocs > 0) { uint8_t *p; - fprintf(stderr, "TAL_DEBUG: memory leak %d chunk(s) (limit= %d)\n", - al->nb_allocs, al->limit); + fprintf(stderr, "TAL_DEBUG: memory leak %d chunk(s)\n", al->nb_allocs); p = al->buffer; while (p < al->p) { tal_header_t *header = (tal_header_t *)p; @@ -250,40 +216,45 @@ tail_call: } #endif next = al->next; - tcc_free(al->buffer); tcc_free(al); al = next; - goto tail_call; + if (al) + goto tail_call; + *pal = al; } -static void tal_free_impl(TinyAlloc *al, void *p TAL_DEBUG_PARAMS) +static void tal_free_impl(TinyAlloc **pal, void *p TAL_DEBUG_PARAMS) { + TinyAlloc *al, **top = pal; + tal_header_t *header; + if (!p) return; -tail_call: - if (al->buffer <= (uint8_t *)p && (uint8_t *)p < al->buffer + al->size) { -#ifdef TAL_DEBUG - tal_header_t *header = (((tal_header_t *)p) - 1); - if (header->line_num < 0) { - fprintf(stderr, "%s:%d: TAL_DEBUG: double frees chunk from\n", - file, line); - fprintf(stderr, "%s:%d: %d bytes\n", - header->file_name, (int)-header->line_num, (int)header->size); - } else - header->line_num = -header->line_num; + header = (tal_header_t *)p - 1; +#if TAL_DEBUG + if (header->line_num < 0) { + fprintf(stderr, "%s:%d: TAL_DEBUG: double frees chunk from\n", + sfile, sline); + fprintf(stderr, "%s:%d: %d bytes\n", + header->file_name, (int)-header->line_num, (int)header->size); + } else + header->line_num = -header->line_num; #endif - al->nb_allocs--; - if (!al->nb_allocs) + al = *pal; + while ((uint8_t*)p < al->buffer || (uint8_t*)p > al->bufend) + al = *(pal = &al->next); + if (0 == --al->nb_allocs) { + *pal = al->next; + if ((al->bufend - al->buffer) > al->size) { + //fprintf(stderr, "free big tal: %u\n", header->size); + tcc_free(al); + } else { + /* reset and move to front */ al->p = al->buffer; - } else if (al->next) { - al = al->next; - goto tail_call; - } - else { - pp_alloc_t *alloc = ((pp_alloc_t *)p) - 1; - - PP_ALLOC_REMOVE(alloc); - tcc_free(alloc); + al->next = *top, *top = al; + } + } else if ((uint8_t*)p + header->size == al->p) { + al->p = (uint8_t*)header; } } @@ -291,112 +262,66 @@ static void *tal_realloc_impl(TinyAlloc **pal, void *p, unsigned size TAL_DEBUG_ { tal_header_t *header; void *ret; - int is_own; - unsigned adj_size = TAL_ALIGN(size); + unsigned adj_size = TAL_ALIGN(size) + sizeof(tal_header_t); TinyAlloc *al = *pal; -tail_call: - is_own = (al->buffer <= (uint8_t *)p && (uint8_t *)p < al->buffer + al->size); - if ((!p || is_own) && size <= al->limit) { - if (al->p - al->buffer + adj_size + sizeof(tal_header_t) < al->size) { - header = (tal_header_t *)al->p; - header->size = adj_size; -#ifdef TAL_DEBUG - { int ofs = strlen(file) + 1 - sizeof header->file_name; - strcpy(header->file_name, file + (ofs > 0 ? ofs : 0)); - header->line_num = line; } -#endif - ret = al->p + sizeof(tal_header_t); - al->p += adj_size + sizeof(tal_header_t); - if (is_own) { - header = (((tal_header_t *)p) - 1); - if (p) memcpy(ret, p, header->size); -#ifdef TAL_DEBUG - header->line_num = -header->line_num; -#endif - } else { - al->nb_allocs++; - } -#ifdef TAL_INFO - if (al->nb_peak < al->nb_allocs) - al->nb_peak = al->nb_allocs; - if (al->peak_p < al->p) - al->peak_p = al->p; - al->nb_total++; -#endif + if (p) { + /* reallpc case */ + while ((uint8_t*)p < al->buffer || (uint8_t*)p > al->bufend) + al = al->next; + header = (tal_header_t *)p - 1; + if ((uint8_t*)p + header->size == al->p) + al->p = (uint8_t*)header; /* maybe reuse */ + if (al->p + adj_size > al->bufend) { + ret = tal_realloc(pal, 0, size); + memcpy(ret, p, header->size); + tal_free(pal, p); return ret; - } else if (is_own) { - al->nb_allocs--; - ret = tal_realloc(*pal, 0, size); - header = (((tal_header_t *)p) - 1); - if (p) memcpy(ret, p, header->size); -#ifdef TAL_DEBUG + } else if (al->p != (uint8_t*)header) { + memcpy((tal_header_t*)al->p + 1, p, header->size); +#if TAL_DEBUG header->line_num = -header->line_num; #endif - return ret; } - if (al->next) { - al = al->next; - } else { - TinyAlloc *bottom = al, *next = al->top ? al->top : al; - - al = tal_new(pal, next->limit, next->size * 2); - al->next = next; - bottom->top = al; - } - goto tail_call; - } - if (is_own) { - pp_alloc_t *alloc; - - al->nb_allocs--; - alloc = tcc_malloc(size + sizeof(pp_alloc_t)); - PP_ALLOC_INSERT(alloc); - ret = alloc + 1; - header = (((tal_header_t *)p) - 1); - if (p) memcpy(ret, p, header->size); -#ifdef TAL_DEBUG - header->line_num = -header->line_num; -#endif - } else if (al->next) { - al = al->next; - goto tail_call; } else { - pp_alloc_t *alloc = NULL; - - if (p) { - alloc = ((pp_alloc_t *)p) - 1; - PP_ALLOC_REMOVE(alloc); - } - if (size) { - alloc = tcc_realloc(alloc, size + sizeof(pp_alloc_t)); - PP_ALLOC_INSERT(alloc); - ret = alloc + 1; - } - else { - tcc_free(alloc); - ret = NULL; - } + /* new alloc case */ + while (al->p + adj_size > al->bufend) { + al = al->next; + if (!al) { + unsigned new_size = (*pal)->size; + if (adj_size > new_size) { + new_size = adj_size; + //fprintf(stderr, "%s:%d: alloc big tal: %u\n", file->filename, file->line_num, adj_size - sizeof(tal_header_t)); + } + al = tal_new(pal, new_size); + break; + } + } + al->nb_allocs++; + } + header = (tal_header_t *)al->p; + header->size = adj_size - sizeof(tal_header_t); + al->p += adj_size; + ret = header + 1; +#if TAL_DEBUG + { + int ofs = strlen(sfile) + 1 - sizeof header->file_name; + strcpy(header->file_name, sfile + (ofs > 0 ? ofs : 0)); + header->line_num = sline; +#if TAL_INFO + if (al->nb_peak < al->nb_allocs) + al->nb_peak = al->nb_allocs; + if (al->peak_p < al->p) + al->peak_p = al->p; + al->nb_total++; +#endif } -#ifdef TAL_INFO - al->nb_missed++; #endif return ret; } #endif /* USE_TAL */ -static void tal_alloc_init(void) -{ - pp_allocs.next = pp_allocs.prev = &pp_allocs; -} - -static void tal_alloc_free(void) -{ - while (pp_allocs.next != &pp_allocs) - tal_free(toksym_alloc /* dummy */, pp_allocs.next + 1); -} - /* ------------------------------------------------------------------------- */ /* CString handling */ static void cstr_realloc(CString *cstr, int new_size) @@ -550,7 +475,7 @@ static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len) table_ident = ptable; } - ts = tal_realloc(toksym_alloc, 0, sizeof(TokenSym) + len); + ts = tal_realloc(&toksym_alloc, 0, sizeof(TokenSym) + len); table_ident[i] = ts; ts->tok = tok_ident++; ts->sym_define = NULL; @@ -1084,20 +1009,20 @@ ST_INLN void tok_str_new(TokenString *s) ST_FUNC TokenString *tok_str_alloc(void) { - TokenString *str = tal_realloc(tokstr_alloc, 0, sizeof *str); + TokenString *str = tal_realloc(&tokstr_alloc, 0, sizeof *str); tok_str_new(str); return str; } ST_FUNC void tok_str_free_str(int *str) { - tal_free(tokstr_alloc, str); + tal_free(&tokstr_alloc, str); } ST_FUNC void tok_str_free(TokenString *str) { tok_str_free_str(str->str); - tal_free(tokstr_alloc, str); + tal_free(&tokstr_alloc, str); } ST_FUNC int *tok_str_realloc(TokenString *s, int new_size) @@ -1110,7 +1035,7 @@ ST_FUNC int *tok_str_realloc(TokenString *s, int new_size) while (size < new_size) size = size * 2; if (size > s->allocated_len) { - str = tal_realloc(tokstr_alloc, s->str, size * sizeof(int)); + str = tal_realloc(&tokstr_alloc, s->str, size * sizeof(int)); s->allocated_len = size; s->str = str; } @@ -2550,7 +2475,7 @@ static void parse_number(const char *p) } } } else { - unsigned long long n = 0, n1 = 0; + unsigned long long n, n1; int lcount, ucount, ov = 0; const char *p1; @@ -2561,6 +2486,7 @@ static void parse_number(const char *p) b = 8; q++; } + n = 0; while(1) { t = *q++; /* no need for checks except for base 10 / 8 errors */ @@ -2574,23 +2500,13 @@ static void parse_number(const char *p) t = t - '0'; if (t >= b) tcc_error("invalid digit"); + n1 = n; n = n * b + t; - if (!ov) { - /* detect overflow */ - if (n1 >= 0x1000000000000000ULL && n / b != n1) - ov = 1; - else - n1 = n; - } + /* detect overflow */ + if (n1 >= 0x1000000000000000ULL && n / b != n1) + ov = 1; } -#ifdef TCC_CUT_ON_INTEGER_LITERAL_OVERFLOW - /* On integer literal overflow use the most significant digits before - the overflow happened. Effectively this cuts the 0x1000000000000000 - from above down to 0x10000000 and allows to bootstrap tcc with 32 bit - arithmetic. */ - if (ov) - n = n1; -#endif + /* Determine the characteristics (unsigned and/or 64bit) the type of the constant must have according to the constant suffix(es) */ lcount = ucount = 0; @@ -3830,9 +3746,8 @@ ST_FUNC void tccpp_new(TCCState *s) set_idnum(i, IS_ID); /* init allocators */ - tal_new(&toksym_alloc, TOKSYM_TAL_LIMIT, TOKSYM_TAL_SIZE); - tal_new(&tokstr_alloc, TOKSTR_TAL_LIMIT, TOKSTR_TAL_SIZE); - tal_alloc_init(); + tal_new(&toksym_alloc, TOKSYM_TAL_SIZE); + tal_new(&tokstr_alloc, TOKSTR_TAL_SIZE); memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *)); memset(s->cached_includes_hash, 0, sizeof s->cached_includes_hash); @@ -3840,9 +3755,10 @@ ST_FUNC void tccpp_new(TCCState *s) cstr_new(&tokcstr); cstr_new(&cstr_buf); cstr_realloc(&cstr_buf, STRING_MAX_SIZE); + tok_str_new(&unget_buf); + tok_str_realloc(&unget_buf, TOKSTR_MAX_SIZE); tok_str_new(&tokstr_buf); tok_str_realloc(&tokstr_buf, TOKSTR_MAX_SIZE); - tok_str_new(&unget_buf); tok_ident = TOK_IDENT; p = tcc_keywords; @@ -3876,8 +3792,8 @@ ST_FUNC void tccpp_delete(TCCState *s) n = tok_ident - TOK_IDENT; if (n > total_idents) total_idents = n; - for(i = 0; i < n; i++) - tal_free(toksym_alloc, table_ident[i]); + for (i = n; --i >= 0;) + tal_free(&toksym_alloc, table_ident[i]); tcc_free(table_ident); table_ident = NULL; @@ -3888,11 +3804,8 @@ ST_FUNC void tccpp_delete(TCCState *s) tok_str_free_str(unget_buf.str); /* free allocators */ - tal_alloc_free(); - tal_delete(toksym_alloc); - toksym_alloc = NULL; - tal_delete(tokstr_alloc); - tokstr_alloc = NULL; + tal_delete(&toksym_alloc); + tal_delete(&tokstr_alloc); } /* ------------------------------------------------------------------------- */ diff --git a/tccrun.c b/tccrun.c index eca569d3..fe5a4a2c 100644 --- a/tccrun.c +++ b/tccrun.c @@ -120,10 +120,7 @@ static int rt_mem(TCCState *s1, int size) unlink(tmpfname); ftruncate(fd, size); - ptr = mmap(NULL, size * 2, PROT_READ|PROT_EXEC|(s1->do_debug ? PROT_WRITE : 0), MAP_SHARED, fd, 0); - if (ptr == MAP_FAILED) - /* Some targets do not support PROT_EXEC + PROT_WRITE */ - ptr = mmap(NULL, size * 2, PROT_READ|PROT_EXEC, MAP_SHARED, fd, 0); + ptr = mmap(NULL, size * 2, PROT_READ|PROT_EXEC, MAP_SHARED, fd, 0); /* mmap RW memory at fixed distance */ prw = mmap((char*)ptr + size, size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, fd, 0); close(fd); @@ -224,14 +221,11 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv) return 0; tcc_add_symbol(s1, "__rt_exit", rt_exit); - if (s1->nostdlib) { - tcc_add_support(s1, "run_nostdlib.o"); - s1->run_main = top_sym = s1->elf_entryname ? s1->elf_entryname : "_start"; - } else { - tcc_add_support(s1, "runmain.o"); - s1->run_main = "_runmain"; - top_sym = "main"; - } + s1->run_main = "_runmain", top_sym = "main"; + if (s1->elf_entryname) + s1->run_main = top_sym = s1->elf_entryname; + tcc_add_support(s1, "runmain.o"); + if (tcc_relocate(s1) < 0) return -1; @@ -255,19 +249,10 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv) ret = tcc_setjmp(s1, main_jb, tcc_get_symbol(s1, top_sym)); if (0 == ret) { - if (s1->nostdlib) { - void (*run_nostdlib)(void *start, int argc, char **argv, char **envp); - - run_nostdlib = (void *)get_sym_addr(s1, "_run_nostdlib", 1, 1); - if ((addr_t)-1 == (addr_t)run_nostdlib) - return -1; - run_nostdlib(prog_main, argc, argv, envp); /* never returns */ - } - else - ret = prog_main(argc, argv, envp); - } - else if (RT_EXIT_ZERO == ret) + ret = prog_main(argc, argv, envp); + } else if (RT_EXIT_ZERO == ret) { ret = 0; + } if (s1->dflag & 16 && ret) /* tcc -dt -run ... */ fprintf(s1->ppfp, "[returns %d]\n", ret), fflush(s1->ppfp); diff --git a/tests/tests2/60_errors_and_warnings.c b/tests/tests2/60_errors_and_warnings.c index 398ed236..b89d7343 100644 --- a/tests/tests2/60_errors_and_warnings.c +++ b/tests/tests2/60_errors_and_warnings.c @@ -551,84 +551,4 @@ int main(int argc, char **argv) } -#elif defined test_jmp_label - -int main(void) { - asm goto("jmp %[label]" : : : : label); -} - -#elif defined test_void_ternary - -int main() { - unsigned long b = 0; - if ((b ? (void)0 : (long long)b)) -} - -#elif defined test_init_int_string - -int fsB = ""; - -//#elif defined test_constant1 -// results differs on 32/64 bits targets -// reports 64: constant expression expected -// reports 32: constant exceeds 32 bit -//e[1.0 < r() -// -//#elif defined test_constant2 -// results differs on 32/64 bits targets -// reports 64: constant expression expected -// reports 32: constant exceeds 32 bit -//e[1 < r()-1. - -#elif defined test_asm1 - -asm (".align 8589934592"); - -#elif defined test_asm2 - -asm (".balign 8589934592"); - -#elif defined test_asm3 - -asm (".global "); - -#elif defined test_asm4 - -asm (".type (a,cr0,digit)"); - -#elif defined test_asm5 - -asm (".type $6"); - -#elif defined test_asm6 - -asm (".global $-3"); - -#elif defined test_asm7 - -asm (".global (dx,0X2D,digit)"); - -#elif defined test_asm8 - -asm (".size 0XA"); - -#elif defined test_asm9 - -asm (".weak (fs:0)"); - -#elif defined test_asm10 - -asm (".align 0"); - -#elif defined test_asm11 - -asm (".org 33824993159184"); - -//#elif defined test_big -// results differs on 32/64 bits targets -// reports 64: error: program too big -// reports 32: memory full -//asm (".org 0x7fffffff"); -//asm (".byte 1, 2, 3, 4"); - #endif diff --git a/tests/tests2/60_errors_and_warnings.expect b/tests/tests2/60_errors_and_warnings.expect index 0588f552..a90f4153 100644 --- a/tests/tests2/60_errors_and_warnings.expect +++ b/tests/tests2/60_errors_and_warnings.expect @@ -262,45 +262,3 @@ bar 15 12 34 [test_scope_3] 60_errors_and_warnings.c:548: warning: assignment from incompatible pointer type 60_errors_and_warnings.c:549: error: initialization of incomplete type - -[test_jmp_label] -60_errors_and_warnings.c:557: error: invalid operand reference after % - -[test_void_ternary] -60_errors_and_warnings.c:564: error: invalid operand types for binary operation - -[test_init_int_string] -60_errors_and_warnings.c:569: warning: assignment makes integer from pointer without a cast - -[test_asm1] -60_errors_and_warnings.c:584: error: integer out of range 8589934592 - -[test_asm2] -60_errors_and_warnings.c:588: error: integer out of range 8589934592 - -[test_asm3] -60_errors_and_warnings.c:592: error: Illegal symbol .global - -[test_asm4] -60_errors_and_warnings.c:597: error: Illegal symbol .type - -[test_asm5] -60_errors_and_warnings.c:601: error: Illegal symbol .type - -[test_asm6] -60_errors_and_warnings.c:605: error: Illegal symbol .global - -[test_asm7] -60_errors_and_warnings.c:609: error: Illegal symbol .global - -[test_asm8] -60_errors_and_warnings.c:613: error: label not found: .size - -[test_asm9] -60_errors_and_warnings.c:617: error: Illegal symbol .weak - -[test_asm10] -60_errors_and_warnings.c:620: error: alignment must be a positive power of two - -[test_asm11] -60_errors_and_warnings.c:624: error: .org out of range diff --git a/x86_64-gen.c b/x86_64-gen.c index 95b72e93..2ca1ddec 100644 --- a/x86_64-gen.c +++ b/x86_64-gen.c @@ -175,11 +175,8 @@ ST_FUNC void g(int c) if (nocode_wanted) return; ind1 = ind + 1; - if ((unsigned)ind1 > cur_text_section->data_allocated) { - if (ind1 < 0) - tcc_error("program too big"); + if (ind1 > cur_text_section->data_allocated) section_realloc(cur_text_section, ind1); - } cur_text_section->data[ind] = c; ind = ind1; } diff --git a/x86_64-link.c b/x86_64-link.c index 7456bdf0..62e20ff1 100644 --- a/x86_64-link.c +++ b/x86_64-link.c @@ -221,15 +221,13 @@ ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, qrel->r_addend = (int)read32le(ptr) + val; qrel++; } - /* ignore relocation check for stab section */ - if ((stab_section == NULL || - addr < stab_section->sh_addr || - addr >= (stab_section->sh_addr + stab_section->data_offset)) && - ((type == R_X86_64_32 && - (unsigned long long)val > 4294967295ULL) || - (type == R_X86_64_32S && - ((long long)val < -2147483648LL || (long long)val > 2147483647LL)))) - tcc_error_noabort("internal error: relocation %d failed", type); + if ((type == R_X86_64_32 ? val != (unsigned)val : val != (int)val) + /* ignore relocation check for stab section */ + && (stab_section == NULL || + addr < stab_section->sh_addr || + addr >= (stab_section->sh_addr + stab_section->data_offset))) { + tcc_error_noabort("relocation 'R_X86_64_32[S]' out of range"); + } add32le(ptr, val); break; @@ -260,7 +258,7 @@ ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, /* ignore overflow with undefined weak symbols */ if (((ElfW(Sym)*)symtab_section->data)[sym_index].st_shndx != SHN_UNDEF) #endif - tcc_error_noabort("internal error: relocation %d failed", type); + tcc_error_noabort("relocation '%d' out of range", type); } add32le(ptr, diff); }