some linux programs (kernel) really want to have 'extern inline'
functions be visible from other units, i.e. not be static, but also
mark them as always_inline. That's -fgnu89-inline semantics, so it's
fine, but we don't (yet) implement this, so we can't make them static
just so. But we do need this hack on MacOS due to some uses in
system headers (see commit f18f8651).
So, for now conditionalize the hack on Mach-O.
via some heavy-handed hackery in the ASM symbol handling in case
C symbols get a leading underscore (but ASM symbols do not).
But this is now like clang and GCC on Darwin work: asm symbols are
undecorated, C symbols get a _ prepended, so to connect both some
trickery is involved for the ASM symbols that don't have a _ prepended.
They must be included in the C symbol table (because that's what we use
to lookup also ASM labels), but they also must not disturb the normal
C symbol (which don't have the _ prepended), so they need some mangling.
A bit unsatisfying, but well. So, add asm-c-connect-test to the working
ones for Darwin as well.
all except the below work now on MacOS, also as executable test,
not just with -run:
* dlltest - we don't support dylib generation (yet)
* memtest - tccmacho.c contains some leaks
* asm-c-connect-test - some confusion with underscores still
we need to disable or adjust some tests where clang behaves
slightly different from GCC:
* slight difference in __FILE__ behaviour
* difference (to less useful vs GCC) in computed #include
* difference in __builtin_constant_p
* attribute(weak, alias) isn't supported by clang on MacOS (though
it could be, as Mach-O has the capabilities for this)
* the built-in assembler of clang is mediocre
this was all checked with
Apple LLVM version 10.0.1 (clang-1001.0.46.4)
* instead of /usr/include use the current SDK path as system
include directory (/usr/include is empty with current tools)
(this also removes the need to add these paths in individual
Makefiles)
* define _DARWIN_C_SOURCE in tcc.h to get the full set of decls
from system headers (e.g. vsnprintf), similar to _GNU_SOURCE
(and don't define _ANSI_SOURCE in the main Makefile anymore)
* tests/tests2/Makefile: remove the -w flag, it's added when necessary
in the rules generating the .expect files
this is needed for multi-file testcases using stdio.h, as
the __sputc function is implemented as a extern inline
function (with gnu_inline attribute, but we don't support that for now).
Without this change that leads to multiply defined symbols when using
multiple units including stdio.h.
It also has an always_inline attribute, which we can use to guide our
behaviour, as in ISO-C an always_inline can't be defined with ISO
'extern inline' semantics. This is the minimal change and not a full
implementation of GNU inline semantics, which would require thorough
testcases.
If __clang__ would be defined the header would make use of C99 semantics,
which would work for us. It would also do that if _GNUC_ wouldn't be
defined. But we can't do the latter (as the whole MacOSX SDK refuses
to be compiled with anything not defining that). I haven't tested
defining __clang__, but suspect that's going to be problematic.
* alloca needs to be _alloca
* int64_t and uint64_t are also defined in <sys/_types/_int64_t.h>
but as long long, not as long, so adjust out <stddef.h> to agree
on Darwin
* define __APPLE_CC__ so that <TargetConditionals.h> correctly defines
various macros like TARGET_OS_MAC and TARGET_CPU_X86_64
* non-process-shared POSIX semaphores aren't supported on
Darwin, we use the dispatch framework
* dlsym segfaults with RTLD_NEXT from JIT code, so we must not
even try this for -run. So we need to know in __bound_init
if called from -run code, or from normal code, which means passing
this down also from __bt_init and hence from the stub added in
tcc_add_btstub
* Darwin uses different structures for <ctype.h> facilities, this
merely adds a warning about this
* __libc_freeres doesn't exist
* for non -run modus the context (.prog_base member) is constructed
incorrectly (uses symbol zero for trying to get at the load bias,
which doesn't really work that way), on Mach-O this errors out
(and could also error out on ELF). For now deactivate this, which
makes backtraces not be symbolic on MacOS for not -run.
uncovered by the backtrace/boundcheck tests:
* handle STT_SECTION symbols
* call tcc_add_runtime (to get the bcheck.o/bt-exe.o files added)
* add .stab strtab into segments (we should probably add all stab
syms to the output LC_SYMTAB eventually, but right now TCC uses
32 bit stabs, while mach-o uses 32/64bit stabs
* <malloc.h> isn't as portable as <stdlib.h>
* skip 113_btdll.c on Darwin
* replace [...]\+ with [...]\{1,\} in the sed regex (basic REs
have no + even some sed(1) accept it as \+, but bounds _are_ part
of POSIX BREs)
for handling leading underscores when looking up symbols.
Necessary on MacOS, as there C symbols have a '_' prepended.
get_sym_addr (replacing get_elf_sym_addr) gets an argument to
specify if bare/raw/ELF symbols should be looked up or if decorated
C symbols should be looked up. That reflects into tcc_get_symbol.
tcc_add_symbol is _not_ yet changed, but probably should be.
all C/C++/ObjC symbols in symbols tables have a leading underscore
in Mach-O. Within TCC there's some confusion with tcc_add_symbol
(not adding it) and tcc_get_elf_symbol (not expecting it), and
resolve_syms (using dlsym, which doesn't expect it) and -run support.
But this sort of works.
these are resolved non-lazy for now. We only need to generate
the jump stub (using the GOT slot that will be initialized due
to the non-lazy pointer marking, like with data symbols). On
x86-64 we don't even need special marking of these stubs (with
S_SYMBOL_STUBS and associated additional indirect symbol entries),
as that's only used on i386 (where the stubs are self-modifying).
So, this now works:
extern int _printf(const char*, ...);
int _start(void)
{
_printf("hello\n");
return 0;
}
at least data symbols coming from dylibs can be used now, as in the
below. Note in the example that optind is defined in libc (really in
libsystem_c.dylib, reexported from libSystem.B.dylib):
static int loc;
extern int _optind;
int _start(void)
{
_optind = 0;
loc = 42 + _optind;
return loc - 42;
}
if a GOT slot is required (due to codegen, indicated by
presence of some relocation types), then it needs to contain
the address of the wanted symbol, also when it's local and defined,
i.e. not overridable. For simplicity we use a GOT slot for that as
well (other storage would require rewriting relocs and symbols,
as resolving of GOT relocs is hardwired to be based on s1->got).
But that means we need to fill in its indirect symbol mapping slot as
well, for which Mach-O provides a mean to say "not symbol based,
resolved locally". So this fixes this testcase:
static int loc;
int _start(void)
{
loc = 42;
return loc - 42;
}
(where our codegen currently uses a GOT-based access for the write
by accident)
this now sorts the symbols properly (local, global defined, undefined;
the latter two by name), marks the three ranges within LC_DYSYMTAB,
generates a __got section (non-lazy pointers) and slots for
relocations which need them, and the indirect symbol mapping for
them.
This doesn't yet deal with undefined symbols. But it means compared to
last example now this also works, i.e. read access to _global_ data:
% cat simple3.c
int loc = 42;
int _start(void)
{
return loc - 42;
}
this creates a proper LC_SYMTAB, with reasonable entries. It's
not sorted, so not usable for LC_DYSYMTAB. But 'nm -x -no-sort'
allows to see us some useful info.
This also relocates sections and symbols, so now this example
works as well (i.e. read access to static local data):
% cat simple2.c
static int loc = 42;
int main(void)
{
return loc - 42;
}
this does generate a working executable for a very simple
example input, e.g. this:
% cat simple.c
int main(void)
{
return 0;
}
% ./tcc -B. -c simple.c
% ./tcc -nostdlib -B. simple.o -lc
% ./a.out && echo okay
okay
(the -lc is actually not necessary right now, see below). This
has many limitations:
* no symbol table, hence no calls to external functions from
e.g. libc, aka libSystemB
* no proper entry point (should be main, but is hardcoded to first
real .text address)
* libSystemB is hardcoded, no other libs are supported (but again
no external calls anyway)
* generated Mach-O executable is in old format: neither LC_DYLD_INFO
no export tries for symbols are created (no symbol table at all!)
* the __LINKEDIT segment is faked and empty, as dyld doesn't like
it empty even if no symbols point into it
* same with __DATA, dyld wants a non-empty writable segment which
we enforce with useless data
* no relocations, hence no function call stubs (lazy or not) are
generated
* hardcodes some other constants as well
we ignore dylibs for now (can't inspect them yet for meta-info).
Also don't try to load GNU linker scripts, it's simply an unknown file
type (e.g. when mentioning Mach-O object files).
cctools for MacOS 10.14 (at least) unconditionally uses the
__has_include preprocessor directive (i.e. without checking
if defined __has_include
as normally suggested for portable code). So we need to handle
it a little bit. For now we simply say "nope" aka evaluate to 0.
- call TOK_GET() as a function only for tokens with values
- get rid of 'next_nomacro_spc()'
- be sligtly more efficient in next()
This made about 4-5%+ speed in my tests.
Also: tcc.h: reorder tokens
It might have advantages in cases if tcc/libtcc does not
depend on extern files.
Also:
- apply "stray \\ ..." check to macros only. For files it
was already checked. Add positive test.
from e640ed1aeb
Also:
- cleanup -std, -O, -pthread
- tcc.h:win32: use win32-type include paths even for cross
compilers (needed for loading tcc_predefs.h in cases)
- Makefile: simplify OSX .dylib clause