Commit Graph

1163 Commits

Author SHA1 Message Date
grischka
828ccde9fc arm: define TCC_ARM_VERSION for cross compiler 2013-01-30 18:39:36 +01:00
grischka
b7e75ccdb0 tccpe: no debug, no stabs 2013-01-30 18:39:26 +01:00
grischka
17cf0dcf70 configure: use relative paths for in-tree build
Also
- move CPPFLAGS to Makefile
- Use top_srcdir in lib/Makefile
2013-01-30 18:39:09 +01:00
Thomas Preud'homme
6ccee6edb3 Add my copyright for changes in arm-gen.c 2013-01-30 17:34:19 +01:00
Thomas Preud'homme
5fa135f9eb Changelog update 2013-01-30 17:13:40 +01:00
Thomas Preud'homme
01e1eecdbe Update Changelog 2013-01-30 17:07:18 +01:00
Thomas Preud'homme
52947e5844 Favor arm hardfloat over arm softfloat.
Favor ARM hardfloat over ARM softfloat calling convention. In
particular, this solve the problem of the raspbian distribution where
the softfloat ld.so pathname (lib/ld-linux.so.3) is actually a symlink
to the hardfloat ld.so pathname (/lib/arm-linux-gnueabihf/ld-2.13.so).
2013-01-29 18:15:23 +01:00
Thomas Preud'homme
bcac413c30 Fix overflow detection in ARM relocation
Fix overflow detection for R_ARM_CALL, R_ARM_PC24, R_ARM_JUMP24 and
R_ARM_PLT32 relocations on ARM. 26 bits means 25 bits for positive and
negative offsets !
2013-01-28 19:13:25 +01:00
Thomas Preud'homme
0f81512d7d Fix stack alignment on 8 bytes at function call
Ensure stack pointer is correctly adjusted in prolog to be aligned on 8
bytes after the change of frame linking.
2013-01-27 01:08:01 +01:00
Thomas Preud'homme
f3e5649150 Don't do builtin_frame_address test with ARM gcc
gcc fails the builtin_frame_address test on ARM so we disable it. As a
consequence, the diff between gcc and tcc's output is unecessarily
bigger. Given the big size of the diff currently, this doesn't make a
big difference but may allow to detect a regression in tcc's
implementation of builtin_frame_address.
2013-01-26 20:31:14 +01:00
Thomas Preud'homme
f63c750942 Organize frames in a real linked list on ARM
Change the linking of the frames on ARM. Instead of having fp points 12
bytes above where the old fp is stored, let fp points where the old fp
is stored. That is, we switch from:

|   .    |
|   .    |
|   .    |
|        |
| params | <-- fp
 --------
| oldlr  |
 --------
| oldip  |
 --------
| oldfp  |
 --------

to:

|   .    |
|   .    |
|   .    |
|        |
| params |
 --------
| oldlr  |
 --------
| oldip  |
 --------
| oldfp  | <-- fp
 --------
2013-01-26 20:09:04 +01:00
Thomas Preud'homme
de35a3389f Use gcc to generate tcctest.gcc 2013-01-25 20:14:10 +01:00
Thomas Preud'homme
f8cde52984 Link STT_GNU_IFUNC into STT_FUNC in executable.
Indirect functions shall have STT_FUNC type in executable dynsym
section. Indeed, a dlsym call following a lazy resolution would pick the
symbol value from the executable dynsym entry. This would contain the
address of the function wanted by the caller of dlsym instead of the
address of the function that would return that address.
2013-01-25 20:06:51 +01:00
grischka
b89793d10a win32: _mingw.h: do not undef NULL
Not wise if stddef.h was already included. This is related to commit

    3aa26a794e

Instead hack stddef.h to have identical definition and thus
avoid the issue mentionned there.
2013-01-24 19:49:58 +01:00
Thomas Preud'homme
6b6eea60f3 Fix [f]getc return value usage in 40_stdio test
Store [f]getc return value into an int instead of char, as per
prototype. This fix an issue when char is unsigned (as is on arm for
both tcc and gcc).
2013-01-24 10:55:18 +01:00
grischka
c5892fe4f5 Revert "Optimize vswap()"
This reverts commit 63193d1794.

Had some problems (_STATIC_ASSERT) and was too ugly anyway.
For retry, I'd suggest to implement a general function
    static inline void memswap (void *p1, void* p2, size_t n);
and then use that.  If you do so, please keep the original code
as comment.
2013-01-14 18:41:37 +01:00
grischka
2daf8b96a8 Revert mistake in "win32: malloc.h: fix win32 ... _STATIC_ASSERT"
from commit fc574f1498.

The files from include are copied to win32/include with make
install or build-tcc.bat.
2013-01-14 18:41:36 +01:00
Thomas Preud'homme
f7b417723e Fix out-of-tree build with relative path to root
Fix path of Makefile symlinks in a out-of-tree build where the root
directory of the source is given as a relative path.
2013-01-14 18:18:27 +01:00
Thomas Preud'homme
a4e630c7d9 Install libtcc.h when invoking make install
This fix commit e79281f58e
2013-01-14 18:16:17 +01:00
Thomas Preud'homme
8c56b0cf90 Revert "Added what I call virtual io to tinycc this way we can make a monolitic executable or library that contains all needed to compile programs, truly tinycc portable."
This reverts commit 59e18aee0e.
tcc is being stabilized now in order to do a new release soon.
Therefore, such a change is not appropriate now.
2013-01-14 17:34:07 +01:00
Thomas Preud'homme
60a3ff5f2c Revert "pe: fix tcc not linking to user32 and gdi32"
This reverts commit 943574aba5.
The empty string in "libs" was intended behavior, as can be seen from
the "if (0 == *p)" below.
2013-01-14 17:21:06 +01:00
Thomas Preud'homme
5e7954b408 Stop setting -Wno-unused-result switch in Makefile
This commit revert commit 061b5799cc and
subsequent commits to detect whether -Wno-unused-result is supported or
not by the compiler used to compile tcc. No warning about unused results
is issued in a normal build and thus this switch is only needed if
calling make with extra switches in CFLAGS or CPPFLAGS. It should thus
be added with the extra switches when calling make and not in the
Makefile.
2013-01-13 23:38:33 +01:00
Thomas Preud'homme
ea583f7b8a Fix C99ism in vswap()
Declare vtopl in vswap at the beginning of the function before any
assignments. Doing otherwise means C99 is assumed when compiling.
2013-01-13 23:38:33 +01:00
mingodad
59e18aee0e Added what I call virtual io to tinycc this way we can make a monolitic executable or library that contains all needed to compile programs, truly tinycc portable.
Tested under linux exec the "mk-it" shell script and you'll end up with a portable tinycc executable that doesn't depend on anything else.
2013-01-11 00:04:38 +00:00
grischka
0a8c7d143e Fix "Optimize cstr_reset() to only reset string to empty"
This fixes commit 8eb92e6052

Remove memory leak.
2013-01-06 17:21:33 +01:00
grischka
2358b378b3 tccpp: alternative fix for #include_next infinite loop bug
This replaces commit 3d409b0889

- revert old fix in libtcc.c
- #include_next: look up the file in the include stack to see
  if it is already included.
Also:
- streamline include code
- remove 'type' from struct CachedInclude (obsolete because we check
  full filename anyway)
- remove inc_type & inc_filename from struct Bufferedfile (obsolete)
- fix bug with TOK_FLAG_ENDIF not being reset
- unrelated: get rid of an 'variable potentially uninitialized' warning
2013-01-06 17:20:44 +01:00
Thomas Preud'homme
e92dbe4686 Stop returning 0 in cmp_comparison_test
cmp_comparison_test has no return value and should thus not return 0.
2013-01-06 12:26:53 +01:00
Thomas Preud'homme
eb028a8f42 Honor CC when testing for -Wno-unused-result
The compiler used for compiling tcc is the one referenced in the
CC variable. As such, the check for -Wno-unused-result presence should
be done on CC.
2013-01-06 12:22:56 +01:00
Roy
fc574f1498 win32: malloc.h: fix win32 tcc-tcc complication by correcting _STATIC_ASSERT, ideas from mingw-w64 changeset 4293
stdarg.h, stddef.h: _mingw.h needs them
2012-12-31 08:59:50 +08:00
Kirill Smelkov
63193d1794 Optimize vswap()
vswap() is called often enough and shows in profile and it was easy to
hand optimize swapping vtop[-1] and vtop[0] - instead of large (28 bytes
on i386) tmp variable and two memory to memory copies, let's swap areas
by longs through registers with streamlined assembly.

For

    $ ./tcc -B. -bench -DONE_SOURCE -DCONFIG_MULTIARCHDIR=\"i386-linux-gnu\" -c tcc.c

before:

 # Overhead      Command        Shared Object                                          Symbol
 # ........  ...........  ...................  ..............................................
 #
     15.19%          tcc  tcc                  [.] next_nomacro1
      5.19%          tcc  libc-2.13.so         [.] _int_malloc
      4.57%          tcc  tcc                  [.] next
      3.36%          tcc  tcc                  [.] tok_str_add2
      3.03%          tcc  tcc                  [.] macro_subst_tok
      2.93%          tcc  tcc                  [.] macro_subst
      2.53%          tcc  tcc                  [.] next_nomacro_spc
      2.49%          tcc  tcc                  [.] vswap
      2.36%          tcc  libc-2.13.so         [.] _int_free

       │    ST_FUNC void vswap(void)
       │    {
  1,96 │      push   %edi
  2,65 │      push   %esi
  1,08 │      sub    $0x20,%esp
       │        SValue tmp;
       │
       │        /* cannot let cpu flags if other instruction are generated. Also
       │           avoid leaving VT_JMP anywhere except on the top of the stack
       │           because it would complicate the code generator. */
       │        if (vtop >= vstack) {
  0,98 │      mov    0x8078cac,%eax
       │      cmp    $0x8078d3c,%eax
  1,18 │   ┌──jb     24
       │   │        int v = vtop->r & VT_VALMASK;
  1,08 │   │  mov    0x8(%eax),%edx
  0,78 │   │  and    $0x3f,%edx
       │   │        if (v == VT_CMP || (v & ~1) == VT_JMP)
  0,78 │   │  cmp    $0x33,%edx
  0,69 │   │↓ je     54
  0,59 │   │  and    $0xfffffffe,%edx
  0,49 │   │  cmp    $0x34,%edx
  0,29 │   │↓ je     54
       │   │            gv(RC_INT);
       │   │    }
       │   │    tmp = vtop[0];
  1,08 │24:└─→lea    0x4(%esp),%edi
  0,39 │      mov    $0x7,%ecx
       │      mov    %eax,%esi
 14,41 │      rep    movsl %ds:(%esi),%es:(%edi)
       │        vtop[0] = vtop[-1];
  9,51 │      lea    -0x1c(%eax),%esi
  1,96 │      mov    $0x7,%cl
       │      mov    %eax,%edi
 17,06 │      rep    movsl %ds:(%esi),%es:(%edi)
       │        vtop[-1] = tmp;
 10,20 │      mov    0x8078cac,%edi
  2,35 │      sub    $0x1c,%edi
  0,78 │      lea    0x4(%esp),%esi
       │      mov    $0x7,%cl
 15,20 │      rep    movsl %ds:(%esi),%es:(%edi)
       │    }
  9,90 │      add    $0x20,%esp
  2,25 │      pop    %esi
  1,67 │      pop    %edi
  0,69 │      ret

after:

 # Overhead      Command        Shared Object                                          Symbol
 # ........  ...........  ...................  ..............................................
 #
     15.27%          tcc  tcc                  [.] next_nomacro1
      5.08%          tcc  libc-2.13.so         [.] _int_malloc
      4.57%          tcc  tcc                  [.] next
      3.17%          tcc  tcc                  [.] tok_str_add2
      3.12%          tcc  tcc                  [.] macro_subst
      2.99%          tcc  tcc                  [.] macro_subst_tok
      2.43%          tcc  tcc                  [.] next_nomacro_spc
      2.32%          tcc  libc-2.13.so         [.] _int_free

      . . .

      0.71%          tcc  tcc                  [.] vswap

       │    ST_FUNC void vswap(void)
       │    {
  7,22 │      push   %eax
       │        /* cannot let cpu flags if other instruction are generated. Also
       │           avoid leaving VT_JMP anywhere except on the top of the stack
       │           because it would complicate the code generator. */
       │        if (vtop >= vstack) {
 11,34 │      mov    0x8078cac,%eax
  2,75 │      cmp    $0x8078d3c,%eax
  0,34 │   ┌──jb     20
       │   │        int v = vtop->r & VT_VALMASK;
  0,34 │   │  mov    0x8(%eax),%edx
  8,93 │   │  and    $0x3f,%edx
       │   │        if (v == VT_CMP || (v & ~1) == VT_JMP)
  2,06 │   │  cmp    $0x33,%edx
  2,41 │   │↓ je     74
  2,41 │   │  and    $0xfffffffe,%edx
  0,34 │   │  cmp    $0x34,%edx
  2,41 │   │↓ je     74
       │   │        vtopl[-1*VSIZEL + i] = tmpl;    \
       │   │      } do {} while (0)
       │   │
       │   │    VSWAPL(15); VSWAPL(14); VSWAPL(13); VSWAPL(12);
       │   │    VSWAPL(11); VSWAPL(10); VSWAPL( 9); VSWAPL( 8);
       │   │    VSWAPL( 7); VSWAPL( 6); VSWAPL( 5); VSWAPL( 4);
  2,06 │20:└─→mov    0x18(%eax),%edx
  1,37 │      mov    -0x4(%eax),%ecx
  2,06 │      mov    %ecx,0x18(%eax)
  1,37 │      mov    %edx,-0x4(%eax)
  2,06 │      mov    0x14(%eax),%edx
  2,06 │      mov    -0x8(%eax),%ecx
  2,41 │      mov    %ecx,0x14(%eax)
  3,09 │      mov    %edx,-0x8(%eax)
  3,09 │      mov    0x10(%eax),%edx
  1,72 │      mov    -0xc(%eax),%ecx
  2,75 │      mov    %ecx,0x10(%eax)
  1,72 │      mov    %edx,-0xc(%eax)
       │        VSWAPL( 3); VSWAPL( 2); VSWAPL( 1); VSWAPL( 0);
  2,41 │      mov    0xc(%eax),%edx
  2,41 │      mov    -0x10(%eax),%ecx
  2,41 │      mov    %ecx,0xc(%eax)
  0,69 │      mov    %edx,-0x10(%eax)
  1,72 │      mov    0x8(%eax),%edx
  0,69 │      mov    -0x14(%eax),%ecx
  1,03 │      mov    %ecx,0x8(%eax)
  1,37 │      mov    %edx,-0x14(%eax)
  1,37 │      mov    0x4(%eax),%edx
  0,69 │      mov    -0x18(%eax),%ecx
  3,09 │      mov    %ecx,0x4(%eax)
  2,06 │      mov    %edx,-0x18(%eax)
  1,37 │      mov    (%eax),%edx
  2,41 │      mov    -0x1c(%eax),%ecx
  1,37 │      mov    %ecx,(%eax)
  4,12 │      mov    %edx,-0x1c(%eax)
       │        }
       │
       │    #   undef VSWAPL
       │    #   undef VSIZEL
       │    }
  1,03 │      pop    %eax
  3,44 │      ret

Overal speedup:

    # best of 5 runs
    before: 8268 idents, 47203 lines, 1526763 bytes, 0.148 s, 319217 lines/s, 10.3 MB/s
    after:  8273 idents, 47231 lines, 1527685 bytes, 0.146 s, 324092 lines/s, 10.5 MB/s

Static ASSERT macro taken from CCAN's[1] build_assert[2] which is in
public domain.

[1] http://ccodearchive.net/
[2] http://git.ozlabs.org/?p=ccan;a=blob;f=ccan/build_assert/build_assert.h;h=24e59c44cd930173178ac9b6e101b0af64a879e9;hb=HEAD
2012-12-21 20:46:26 +04:00
Kirill Smelkov
8eb92e6052 Optimize cstr_reset() to only reset string to empty, not call free() and later malloc()
A CString could be reset to empty just setting its .size to 0.

If memory was already allocated, that would be remembered in
.data_allocated and .size_allocated and on consequent string
manipulations that memory will be used without immediate need to call
malloc().

For

    $ ./tcc -B. -bench -DONE_SOURCE -DCONFIG_MULTIARCHDIR=\"i386-linux-gnu\" -c tcc.c

after the patch malloc/free are called less often:

(tcc is run in loop; perf record -a sleep 10 && perf report)
before:

 # Overhead      Command       Shared Object                                      Symbol
 # ........  ...........  ..................  ..........................................
 #
     13.89%          tcc  tcc                 [.] next_nomacro1
      4.73%          tcc  libc-2.13.so        [.] _int_malloc
      4.39%          tcc  tcc                 [.] next
      2.94%          tcc  tcc                 [.] tok_str_add2
      2.78%          tcc  tcc                 [.] macro_subst_tok
      2.75%          tcc  libc-2.13.so        [.] free
      2.74%          tcc  tcc                 [.] macro_subst
      2.63%          tcc  libc-2.13.so        [.] _int_free
      2.28%          tcc  tcc                 [.] vswap
      2.24%          tcc  tcc                 [.] next_nomacro_spc
      2.06%          tcc  libc-2.13.so        [.] realloc
      2.00%          tcc  libc-2.13.so        [.] malloc
      1.99%          tcc  tcc                 [.] unary
      1.85%          tcc  libc-2.13.so        [.] __i686.get_pc_thunk.bx
      1.76%  kworker/0:1  [kernel.kallsyms]   [k] delay_tsc
      1.70%          tcc  tcc                 [.] next_nomacro
      1.62%          tcc  tcc                 [.] preprocess
      1.41%          tcc  libc-2.13.so        [.] __memcmp_ssse3
      1.38%          tcc  [kernel.kallsyms]   [k] memset
      1.10%          tcc  tcc                 [.] g
      1.06%          tcc  tcc                 [.] parse_btype
      1.05%          tcc  tcc                 [.] sym_push2
      1.04%          tcc  libc-2.13.so        [.] _int_realloc
      1.00%          tcc  libc-2.13.so        [.] malloc_consolidate

after:

 # Overhead      Command       Shared Object                                          Symbol
 # ........  ...........  ..................  ..............................................
 #
     15.26%          tcc  tcc                 [.] next_nomacro1
      5.07%          tcc  libc-2.13.so        [.] _int_malloc
      4.62%          tcc  tcc                 [.] next
      3.22%          tcc  tcc                 [.] tok_str_add2
      3.03%          tcc  tcc                 [.] macro_subst_tok
      3.02%          tcc  tcc                 [.] macro_subst
      2.59%          tcc  tcc                 [.] next_nomacro_spc
      2.44%          tcc  tcc                 [.] vswap
      2.39%          tcc  libc-2.13.so        [.] _int_free
      2.28%          tcc  libc-2.13.so        [.] free
      2.22%          tcc  tcc                 [.] unary
      2.07%          tcc  libc-2.13.so        [.] realloc
      1.97%          tcc  libc-2.13.so        [.] malloc
      1.70%          tcc  tcc                 [.] preprocess
      1.69%          tcc  libc-2.13.so        [.] __i686.get_pc_thunk.bx
      1.68%          tcc  tcc                 [.] next_nomacro
      1.59%          tcc  [kernel.kallsyms]   [k] memset
      1.55%          tcc  libc-2.13.so        [.] __memcmp_ssse3
      1.22%          tcc  tcc                 [.] parse_comment
      1.11%          tcc  tcc                 [.] g
      1.11%          tcc  tcc                 [.] sym_push2
      1.10%          tcc  tcc                 [.] parse_btype
      1.10%          tcc  libc-2.13.so        [.] _int_realloc
      1.06%          tcc  tcc                 [.] vsetc
      0.98%          tcc  libc-2.13.so        [.] malloc_consolidate

and this gains small speedup for tcc:

    # best of 5 runs
    before: 8268 idents, 47191 lines, 1526670 bytes, 0.153 s, 307997 lines/s, 10.0 MB/s
    after:  8268 idents, 47203 lines, 1526763 bytes, 0.148 s, 319217 lines/s, 10.3 MB/s
2012-12-21 20:46:26 +04:00
Akim Demaille
e79281f58e build: fix out-of-tree install
Makefile (install): Fix installation of headers.
Do not try to install twice libtcc.h, once should be enough.
2012-12-21 14:23:28 +01:00
Akim Demaille
7667a8887a build: fix out-of-tree build
* Makefile (TCC-VERSION): Use top_srcdir.
2012-12-21 14:17:23 +01:00
Akim Demaille
8adfb4a419 build: simplify the makefiles
* Makefile: use "else if" to improve readability.
2012-12-21 14:17:16 +01:00
Akim Demaille
017bbbfee1 configure: support absolete out-of-tree builds
configure: handle the case of absolute paths.
Reported by grishka.
2012-12-21 13:57:22 +01:00
Akim Demaille
d7264e0218 configure: style changes
* configure: use more here-documents.
2012-12-21 13:49:15 +01:00
Akim Demaille
ba49862de6 configure: prefer here-documents
* configure: use here-documents to improve readability and
reduce the clutter.
2012-12-21 13:47:00 +01:00
Akim Demaille
9c9ca2032b configure: style changes
* configure (case $targetos): Improve readibility.
(case $cpu): New, to improve readability compare to if + test.
2012-12-21 13:45:22 +01:00
grischka
5ebc6a964d Makefile: revamp "tar" target
- Creates release tarball from *current* git branch
- Includes tcc-doc.html
- converts important windows files files to CRLF
  (requirement for the cmd.exe batch processor, convenience for
   reading the txt in notepad)
2012-12-20 21:29:57 +01:00
grischka
b174399340 win32: build-tcc.bat: get rid of hardcoded VERSION string
Also:
 - put libtcc.def into libtcc dir
 - remove ar references
 - remove libtcc_test from build
2012-12-20 21:20:54 +01:00
Akim Demaille
3f09b90d21 build: fix VPATH builds
* configure (fn_dirname): New.
Use it to ensure the creation of proper symlinks to Makefiles.
(config.mak): Define top_builddir and top_srcdir.
(CPPFLAGS): Be sure to find the headers.
* Makefile, lib/Makefile, tests/Makefile, tests2/Makefile: Adjust
to set VPATH properly.
Fix confusion between top_builddir and top_srcdir.
2012-12-18 10:06:20 +01:00
Roy
d815896d4c bcheck: there is no unistd.h in win32. 2012-12-10 09:51:49 +08:00
Kirill Smelkov
a55ecf6d2c Repair bounds-checking more, this time tcc -b -run tcc.c -run tcc.c -run tcctest.c works
Hello up there. On the list Grischka made a point that we can't recommend using
-b as long as tcc -b tcc.c doesn't produce anything useful. Now it does, so
please don't treat -b mode as second class citizen anymore.

Thanks,
Kirill

* bcheck2:
  tests: Add tests for compile/run tcc.c with `tcc -b` then compile tcc.c again, then run tcctest.c
  lib/bcheck: Fix code typo in __bound_delete_region()
  lib/bcheck: Don't assume heap goes right after bss
  Make tcc work after self-compiling with bounds-check enabled
2012-12-09 19:51:20 +04:00
Kirill Smelkov
031ff872be tests: Add tests for compile/run tcc.c with tcc -b then compile tcc.c again, then run tcctest.c
Just like with test[123] add their test[123]b variants. After previous 3
patchs all test pass here on Debian GNU/Linux on i385 with gcc-4.7 with
or without memory randomization turned on.
2012-12-09 19:43:40 +04:00
Kirill Smelkov
dbeb4faf21 lib/bcheck: Fix code typo in __bound_delete_region()
We were calling get_page() with t2 index which is not correct, since
get_page() operate on t1 indices. The bug is here from day-1, from
60f781c4 (first version of bounds checker) and show as a crash in
__bound_delete_region() at program exit:

    $ ./tcc   -B. -DTCC_TARGET_I386 -DCONFIG_MULTIARCHDIR=\"i386-linux-gnu\" -b -run -DONE_SOURCE \
      ./tcc.c -B. -DTCC_TARGET_I386 -DCONFIG_MULTIARCHDIR=\"i386-linux-gnu\"    -run -DONE_SOURCE \
      ./tcc.c -B. -run tests/tcctest.c

    (lot's of correct output from tcctest)
    Runtime error: dereferencing invalid pointer
    at 0xa7c21cc4 __bound_delete_region()
    by (nil) ???
    Segmentation fault

The fix is simple - last page should be get through t1_end, like it is
done in __bound_new_region().

After this patch, tcc is being able to compile itself with -b, then
compile itself again and run tcctest with correct output. Tests follow.
2012-12-09 19:33:47 +04:00
Kirill Smelkov
efd9d92b7c lib/bcheck: Don't assume heap goes right after bss
At startup __bound_init() wants to mark malloc zone as invalid memory,
so that any access to memory on heap, not allocated through malloc be
invalid. Other pages are initialized as empty regions, access to which
is not treated as invalid by bounds-checking.

The problem is code incorrectly assumed that heap goes right after bss,
and that is not correct for two cases:

    1) if we are running from `tcc -b -run`, program text data and bss
       will be already in malloced memory, possibly in mmaped region
       insead of heap, and marking memory as invalid from _end
       will not cover heap and probably wrongly mark correct regions.

    2) if address space randomization is turned on, again heap does not
       start from _end, and we'll mark as invalid something else instead
       of malloc area.

For example with the following diagnostic patch ...

    diff --git a/tcc.c b/tcc.c
    index 5dd5725..31c46e8 100644
    --- a/tcc.c
    +++ b/tcc.c
    @@ -479,6 +479,8 @@ static int parse_args(TCCState *s, int argc, char **argv)
         return optind;
     }

    +extern int _etext, _edata, _end;
    +
     int main(int argc, char **argv)
     {
         int i;
    @@ -487,6 +489,18 @@ int main(int argc, char **argv)
         int64_t start_time = 0;
         const char *default_file = NULL;

    +    void *brk;
    +
    +    brk = sbrk(0);
    +
    +    fprintf(stderr, "\n>>> TCC\n\n");
    +    fprintf(stderr, "etext:\t%10p\n",  &_etext);
    +    fprintf(stderr, "edata:\t%10p\n",  &_edata);
    +    fprintf(stderr, "end:\t%10p\n",    &_end);
    +    fprintf(stderr, "brk:\t%10p\n",    brk);
    +    fprintf(stderr, "stack:\t%10p\n",  &brk);
    +
    +    fprintf(stderr, "&errno: %p\n", &errno);
         s = tcc_new();

         output_type = TCC_OUTPUT_EXE;

    diff --git a/tccrun.c b/tccrun.c
    index 531f46a..25ed30a 100644
    --- a/tccrun.c
    +++ b/tccrun.c
    @@ -91,6 +91,8 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
         int (*prog_main)(int, char **);
         int ret;

    +    fprintf(stderr, "\n\ntcc_run() ...\n\n");
    +
         if (tcc_relocate(s1, TCC_RELOCATE_AUTO) < 0)
             return -1;

    diff --git a/lib/bcheck.c b/lib/bcheck.c
    index ea5b233..8b26a5f 100644
    --- a/lib/bcheck.c
    +++ b/lib/bcheck.c
    @@ -296,6 +326,8 @@ static void mark_invalid(unsigned long addr, unsigned long size)
         start = addr;
         end = addr + size;

    +    fprintf(stderr, "mark_invalid  %10p - %10p\n", (void *)addr, (void *)end);
    +
         t2_start = (start + BOUND_T3_SIZE - 1) >> BOUND_T3_BITS;
         if (end != 0)
             t2_end = end >> BOUND_T3_BITS;

... Look how memory is laid out for `tcc -b -run ...`:

    $ ./tcc -B. -b -DTCC_TARGET_I386 -DCONFIG_MULTIARCHDIR=\"i386-linux-gnu\"  -run   \
        -DONE_SOURCE ./tcc.c -B. -c x.c

    >>> TCC

    etext:   0x8065477
    edata:   0x8070220
    end:     0x807a95c
    brk:     0x807b000
    stack:  0xaffff0f0
    &errno: 0xa7e25688

    tcc_run() ...

    mark_invalid  0xfff80000 -      (nil)
    mark_invalid  0xa7c31d98 - 0xafc31d98

    >>> TCC

    etext:  0xa7c22767
    edata:  0xa7c2759c
    end:    0xa7c31d98
    brk:     0x8211000
    stack:  0xafffeff0
    &errno: 0xa7e25688
    Runtime error: dereferencing invalid pointer
    ./tccpp.c:1953: at 0xa7beebdf parse_number() (included from ./libtcc.c, ./tcc.c)
    ./tccpp.c:3003: by 0xa7bf0708 next() (included from ./libtcc.c, ./tcc.c)
    ./tccgen.c:4465: by 0xa7bfe348 block() (included from ./libtcc.c, ./tcc.c)
    ./tccgen.c:4440: by 0xa7bfe212 block() (included from ./libtcc.c, ./tcc.c)
    ./tccgen.c:5529: by 0xa7c01929 gen_function() (included from ./libtcc.c, ./tcc.c)
    ./tccgen.c:5767: by 0xa7c02602 decl0() (included from ./libtcc.c, ./tcc.c)

The second mark_invalid goes right after in-memory-compiled program's
_end, and oops, that's not where malloc zone is (starts from brk), and oops
again, mark_invalid covers e.g. errno. Then compiled tcc is crasshing by
bcheck on errno access:

    1776 static void parse_number(const char *p)
    1777 {
    1778     int b, t, shift, frac_bits, s, exp_val, ch;
         ...
    1951             *q = '\0';
    1952             t = toup(ch);
    1953             errno = 0;

The solution here is to use sbrk(0) as approximation for the program
break start instead of &_end:

    - if we are a separately compiled program, __bound_init() runs early,
      and sbrk(0) should be equal or very near to start_brk (in case other
      constructors malloc something), or

    - if we are running from under `tcc -b -run`, sbrk(0) will return
      start of heap portion which is under this program control, and not
      mark as invalid earlier allocated memory.

With this patch `tcc -b -run tcc.c ...` succeeds compiling above
small-test program (diagnostic patch is still applied too):

    $ ./tcc -B. -b -DTCC_TARGET_I386 -DCONFIG_MULTIARCHDIR=\"i386-linux-gnu\"  -run   \
        -DONE_SOURCE ./tcc.c -B. -c x.c

    >>> TCC

    etext:   0x8065477
    edata:   0x8070220
    end:     0x807a95c
    brk:     0x807b000
    stack:  0xaffff0f0
    &errno: 0xa7e25688

    tcc_run() ...

    mark_invalid  0xfff80000 -      (nil)
    mark_invalid   0x8211000 - 0x10211000

    >>> TCC

    etext:  0xa7c22777
    edata:  0xa7c275ac
    end:    0xa7c31da8
    brk:     0x8211000
    stack:  0xafffeff0
    &errno: 0xa7e25688

    (completes ok)

but running `tcc -b -run tcc.c -run tests/tcctest.c` sigsegv's - that's
the plot for the next patch.
2012-12-09 19:05:36 +04:00
Kirill Smelkov
43a11a7ed1 Make tcc work after self-compiling with bounds-check enabled
For vstack Fabrice used the trick to initialize vtop to &vstack[-1], so
that on first push, vtop becomes &vstack[0] and a value is also stored
there - everything works.

Except that when tcc is compiled with bounds-checking enabled, vstack - 1
returns INVALID_POINTER and oops...

Let's workaround it with artificial 1 vstack slot which will not be
used, but only serve as an indicator that pointing to &vstack[-1] is ok.

Now, tcc, after being self-compiled with -b works:

    $ ./tcc -B. -o tccb  -DONE_SOURCE -DCONFIG_MULTIARCHDIR=\"i386-linux-gnu\" tcc.c  -ldl
    $ cd tests
    $ ../tcc -B.. -run tcctest.c >1
    $ ../tccb -B.. -run tcctest.c >2
    $ diff -u 1 2

and note, tcc's compilation speed is not affected:

    $ ./tcc -B. -bench -DONE_SOURCE -DCONFIG_MULTIARCHDIR=\"i386-linux-gnu\" -c tcc.c

    before: 8270 idents, 47221 lines, 1527730 bytes, 0.152 s, 309800 lines/s, 10.0 MB/s
    after:  8271 idents, 47221 lines, 1527733 bytes, 0.152 s, 310107 lines/s, 10.0 MB/s

But note, that `tcc -b -run tcc` is still broken - for example it crashes
on
    $ cat x.c
    double get100 () { return 100.0; }

    $ ./tcc -B. -b -DTCC_TARGET_I386 -DCONFIG_MULTIARCHDIR=\"i386-linux-gnu\"  -run   \
        -DONE_SOURCE ./tcc.c -B. -c x.c
    Runtime error: dereferencing invalid pointer
    ./tccpp.c:1953: at 0xa7beebdf parse_number() (included from ./libtcc.c, ./tcc.c)
    ./tccpp.c:3003: by 0xa7bf0708 next() (included from ./libtcc.c, ./tcc.c)
    ./tccgen.c:4465: by 0xa7bfe348 block() (included from ./libtcc.c, ./tcc.c)
    ./tccgen.c:4440: by 0xa7bfe212 block() (included from ./libtcc.c, ./tcc.c)
    ./tccgen.c:5529: by 0xa7c01929 gen_function() (included from ./libtcc.c, ./tcc.c)
    ./tccgen.c:5767: by 0xa7c02602 decl0() (included from ./libtcc.c, ./tcc.c)

that's because lib/bcheck.c runtime needs more fixes -- see next
patches.
2012-12-09 18:06:09 +04:00
Thomas Preud'homme
c4a18f47a2 Detect ARM CPU version in configure
Instead of guessing the ARM CPU version to compile for from tcc.h, we
now detect it in configure and output the value in config.h
2012-12-04 11:17:51 +01:00
Thomas Preud'homme
05b02a5581 arm-gen.c: Invalid operator test always false
Invalid operator test is always false in gen_opf for arm (found with
cppcheck). This patch fixes the issue.
2012-11-28 22:26:39 +01:00
Thomas Preud'homme
8d90205fd9 Fix OABI calling convention
OABI calling convention was broken since the addition of the hardfloat
calling convention in commit 7f6095bfec.
This commit fixes the breakage.
2012-11-28 22:26:39 +01:00