Refactor and remove code (tccdbg, tccmacho, ...)

This commit is contained in:
d0p1 🏳️‍⚧️ 2025-02-07 17:17:17 +01:00
parent 05611e2658
commit f08ef63153
60 changed files with 1887 additions and 8579 deletions

6
.gitignore vendored
View file

@ -15,7 +15,7 @@
.gdb_history .gdb_history
a.out a.out
tcc_g tcc_g
tcc tcc/tcc
tcc_c tcc_c
tcc_p tcc_p
*-tcc *-tcc
@ -76,4 +76,6 @@ stamp-h1
*_old *_old
*.cache *.cache
.deps .deps
build-aux build-aux
configure
.dirstamp

View file

@ -72,7 +72,7 @@ User interface:
- -pthread option (same as -D_REENTRANT -lpthread) (Henry Kroll III) - -pthread option (same as -D_REENTRANT -lpthread) (Henry Kroll III)
- -m32/-m64 to re-exec cross compiler (Henry Kroll III) - -m32/-m64 to re-exec cross compiler (Henry Kroll III)
- -Wl, Mimic all GNU -option forms supported by ld (Kirill Smelkov) - -Wl, Mimic all GNU -option forms supported by ld (Kirill Smelkov)
- new LIBTCCAPI tcc_set_options() (grischka) - new tcc_set_options() (grischka)
Platforms: Platforms:
- Many improvements for x86-64 target (Shinichiro Hamaji, Michael Matz, grischka) - Many improvements for x86-64 target (Shinichiro Hamaji, Michael Matz, grischka)

View file

@ -1,12 +1,3 @@
AM_CFLAGS = AM_CFLAGS =
SUBDIRS = libtcc tcc
noinst_LIBRARIES = libtcc.a
libtcc_a_SOURCES = libtcc.c tccpp.c tccgen.c tccdbg.c tccasm.c tccelf.c i386-gen.c i386-link.c i386-asm.c
libtcc_a_CPPFLAGS = -I$(top_srcdir)
bin_PROGRAMS = tcc
tcc_SOURCES = tcc.c
tcc_LDADD = libtcc.a
tcc_CPPFLAGS = -I$(top_srcdir)

3
compile_flags.txt Normal file
View file

@ -0,0 +1,3 @@
-I.
-DHAVE_CONFIG_H
-Ilibtcc

View file

@ -7,7 +7,10 @@ AC_CONFIG_AUX_DIR([build-aux])
AM_INIT_AUTOMAKE([foreign subdir-objects -Werror -Wall]) AM_INIT_AUTOMAKE([foreign subdir-objects -Werror -Wall])
AC_CONFIG_HEADERS([config.h]) AC_CONFIG_HEADERS([config.h])
AC_CONFIG_FILES([Makefile]) AC_CONFIG_FILES([
Makefile
libtcc/Makefile
tcc/Makefile])
AC_LANG([C]) AC_LANG([C])
AC_PROG_CC AC_PROG_CC

1046
dwarf.h

File diff suppressed because it is too large Load diff

View file

@ -1,105 +0,0 @@
#
# Tiny C Compiler Makefile for libtcc1.a
#
TOP = ..
include $(TOP)/Makefile
VPATH = $(TOPSRC)/lib $(TOPSRC)/win32/lib
T = $(or $(CROSS_TARGET),$(NATIVE_TARGET),unknown)
X = $(if $(CROSS_TARGET),$(CROSS_TARGET)-)
XCFG = $(or $(findstring -win,$T),-unx)
S = $(if $(findstring yes,$(SILENT)),@$(info * $@))
TCC = $(TOP)/$(X)tcc$(EXESUF)
XTCC ?= $(TOP)/$(X)tcc$(EXESUF)
XCC = $(XTCC)
XAR = $(XTCC) -ar
XFLAGS-unx = -B$(TOPSRC)
XFLAGS-win = -B$(TOPSRC)/win32 -I$(TOPSRC)/include
XFLAGS = $(XFLAGS$(XCFG))
BFLAGS = -bt
# in order to use gcc, type: make <target>-libtcc1-usegcc=yes
arm-libtcc1-usegcc ?= no
# This makes bounds checking 40%..60% faster.
#x86_64-libtcc1-usegcc=yes
#i386-libtcc1-usegcc=yes
ifeq "$($(T)-libtcc1-usegcc)" "yes"
XCC = $(CC)
XAR = $(AR)
XFLAGS = $(CFLAGS) -fPIC -fno-omit-frame-pointer -Wno-unused-function -Wno-unused-variable
BFLAGS = $(if $(CONFIG_dwarf),-gdwarf,-gstabs)
endif
I386_O = libtcc1.o alloca.o alloca-bt.o $(COMMON_O)
X86_64_O = libtcc1.o alloca.o alloca-bt.o $(COMMON_O)
ARM_O = libtcc1.o armeabi.o alloca.o armflush.o $(COMMON_O)
ARM64_O = lib-arm64.o $(COMMON_O)
RISCV64_O = lib-arm64.o $(COMMON_O)
COMMON_O = stdatomic.o atomic.o builtin.o
WIN_O = crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o
LIN_O = dsohandle.o
OSX_O =
# backtrace/bcheck/run only for native compiler
Nat = $(if $X,no,)
Cbt = $(Nat)$(subst yes,,$(CONFIG_backtrace))
Cbc = $(Cbt)$(subst yes,,$(CONFIG_bcheck))
$(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 bt-exe.o bt-dll.o bt-log.o bcheck.o
OBJ-i386 = $(I386_O) $(LIN_O)
OBJ-x86_64 = $(X86_64_O) va_list.o $(LIN_O)
OBJ-x86_64-osx = $(X86_64_O) va_list.o $(OSX_O)
OBJ-i386-win32 = $(I386_O) chkstk.o $(WIN_O)
OBJ-x86_64-win32 = $(X86_64_O) chkstk.o $(WIN_O)
OBJ-arm64 = $(ARM64_O) $(LIN_O)
OBJ-arm64-osx = $(ARM64_O) $(OSX_O)
OBJ-arm = $(ARM_O) $(LIN_O)
OBJ-arm-fpa = $(OBJ-arm)
OBJ-arm-fpa-ld = $(OBJ-arm)
OBJ-arm-vfp = $(OBJ-arm)
OBJ-arm-eabi = $(OBJ-arm)
OBJ-arm-eabihf = $(OBJ-arm)
OBJ-arm-wince = $(ARM_O) $(WIN_O)
OBJ-riscv64 = $(RISCV64_O) $(LIN_O)
OBJ-extra = $(filter $(EXTRA_O),$(OBJ-$T))
OBJ-libtcc1 = $(addprefix $(X),$(filter-out $(OBJ-extra),$(OBJ-$T)))
ALL = $(addprefix $(TOP)/,$(X)libtcc1.a $(OBJ-extra))
all: $(ALL)
$(TOP)/$(X)libtcc1.a : $(OBJ-libtcc1) $(TCC)
$S$(XAR) rcs $@ $(OBJ-libtcc1)
$(X)%.o : %.c $(TCC)
$S$(XCC) -c $< -o $@ $(XFLAGS)
$(X)%.o : %.S $(TCC)
$S$(XCC) -c $< -o $@ $(XFLAGS)
$(TOP)/%.o : %.c $(TCC)
$S$(XCC) -c $< -o $@ $(XFLAGS)
$(TOP)/bcheck.o : XFLAGS += $(BFLAGS) -I$(TOP)
# includes tccrun.c, $(TOP) for config.h (tccrun.c prerequisite via $(TCC))
$(TOP)/bt-exe.o : XFLAGS += -I$(TOP)
$(X)crt1w.o : crt1.c
$(X)wincrt1w.o : wincrt1.c
# don't try to make it
$(TCC) : ;
clean :
rm -f *.o $(addprefix $(TOP)/,*libtcc1.a $(EXTRA_O))

116
libtcc.h
View file

@ -1,116 +0,0 @@
#ifndef LIBTCC_H
#define LIBTCC_H
#ifndef LIBTCCAPI
# define LIBTCCAPI
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*****************************/
/* set custom allocator for all allocations (optional), NULL for default. */
typedef void *TCCReallocFunc(void *ptr, unsigned long size);
LIBTCCAPI void tcc_set_realloc(TCCReallocFunc *my_realloc);
/*****************************/
typedef struct TCCState TCCState;
/* create a new TCC compilation context */
LIBTCCAPI TCCState *tcc_new(void);
/* free a TCC compilation context */
LIBTCCAPI void tcc_delete(TCCState *s);
/* set CONFIG_TCCDIR at runtime */
LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path);
/* set error/warning callback (optional) */
typedef void TCCErrorFunc(void *opaque, const char *msg);
LIBTCCAPI void tcc_set_error_func(TCCState *s, void *error_opaque, TCCErrorFunc *error_func);
/* set options as from command line (multiple supported) */
LIBTCCAPI int tcc_set_options(TCCState *s, const char *str);
/*****************************/
/* preprocessor */
/* add include path */
LIBTCCAPI int tcc_add_include_path(TCCState *s, const char *pathname);
/* add in system include path */
LIBTCCAPI int tcc_add_sysinclude_path(TCCState *s, const char *pathname);
/* define preprocessor symbol 'sym'. value can be NULL, sym can be "sym=val" */
LIBTCCAPI void tcc_define_symbol(TCCState *s, const char *sym, const char *value);
/* undefine preprocess symbol 'sym' */
LIBTCCAPI void tcc_undefine_symbol(TCCState *s, const char *sym);
/*****************************/
/* compiling */
/* add a file (C file, dll, object, library, ld script). Return -1 if error. */
LIBTCCAPI int tcc_add_file(TCCState *s, const char *filename);
/* compile a string containing a C source. Return -1 if error. */
LIBTCCAPI int tcc_compile_string(TCCState *s, const char *buf);
/* Tip: to have more specific errors/warnings from tcc_compile_string(),
you can prefix the string with "#line <num> \"<filename>\"\n" */
/*****************************/
/* linking commands */
/* set output type. MUST BE CALLED before any compilation */
LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type);
#define TCC_OUTPUT_MEMORY 1 /* output will be run in memory */
#define TCC_OUTPUT_EXE 2 /* executable file */
#define TCC_OUTPUT_DLL 4 /* dynamic library */
#define TCC_OUTPUT_OBJ 3 /* object file */
#define TCC_OUTPUT_PREPROCESS 5 /* only preprocess */
/* equivalent to -Lpath option */
LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname);
/* the library name is the same as the argument of the '-l' option */
LIBTCCAPI int tcc_add_library(TCCState *s, const char *libraryname);
/* add a symbol to the compiled program */
LIBTCCAPI int tcc_add_symbol(TCCState *s, const char *name, const void *val);
/* output an executable, library or object file. DO NOT call
tcc_relocate() before. */
LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename);
/* link and run main() function and return its value. DO NOT call
tcc_relocate() before. */
LIBTCCAPI int tcc_run(TCCState *s, int argc, char **argv);
/* do all relocations (needed before using tcc_get_symbol()) */
LIBTCCAPI int tcc_relocate(TCCState *s1);
/* return symbol value or NULL if not found */
LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name);
/* list all (global) symbols and their values via 'symbol_cb()' */
LIBTCCAPI void tcc_list_symbols(TCCState *s, void *ctx,
void (*symbol_cb)(void *ctx, const char *name, const void *val));
/* experimental/advanced section (see libtcc_test_mt.c for an example) */
/* catch runtime exceptions (optionally limit backtraces at top_func),
when using tcc_set_options("-bt") and when not using tcc_run() */
LIBTCCAPI void *_tcc_setjmp(TCCState *s1, void *jmp_buf, void *top_func, void *longjmp);
#define tcc_setjmp(s1,jb,f) setjmp(_tcc_setjmp(s1, jb, f, longjmp))
/* custom error printer for runtime exceptions. Returning 0 stops backtrace */
typedef int TCCBtFunc(void *udata, void *pc, const char *file, int line, const char* func, const char *msg);
LIBTCCAPI void tcc_set_backtrace_func(TCCState *s1, void* userdata, TCCBtFunc*);
#ifdef __cplusplus
}
#endif
#endif

6
libtcc/Makefile.am Normal file
View file

@ -0,0 +1,6 @@
noinst_LIBRARIES = libtcc.a
libtcc_a_SOURCES = libtcc.c tccpp.c tccgen.c \
tccasm.c tccelf.c \
i386/gen.c i386/link.c \
i386/asm.c tcccoff.c
libtcc_a_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/libtcc

View file

@ -2,7 +2,8 @@
/* COFF.H */ /* COFF.H */
/* COFF data structures and related definitions used by the linker */ /* COFF data structures and related definitions used by the linker */
/**************************************************************************/ /**************************************************************************/
#ifndef COFF_H
# define COFF_H 1
# include <stdint.h> # include <stdint.h>
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
@ -389,3 +390,5 @@ union auxent
#define _DORIGIN "_dorigin" #define _DORIGIN "_dorigin"
#define _SORIGIN "_sorigin" #define _SORIGIN "_sorigin"
#endif /* COFF_H */

View file

View file

@ -141,9 +141,6 @@ static const uint8_t reg_to_size[9] = {
[OP_REG8] = 0, [OP_REG8] = 0,
[OP_REG16] = 1, [OP_REG16] = 1,
[OP_REG32] = 2, [OP_REG32] = 2,
#ifdef TCC_TARGET_X86_64
[OP_REG64] = 3,
#endif
*/ */
0, 0, 1, 0, 2, 0, 0, 0, 3 0, 0, 1, 0, 2, 0, 0, 0, 3
}; };
@ -204,7 +201,7 @@ static const ASMInstr asm_instrs[] = {
#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) { TOK_ASM_ ## name, O(opcode), T(opcode, instr_type, group), 2, { op0, op1 }}, #define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) { TOK_ASM_ ## name, O(opcode), T(opcode, instr_type, group), 2, { op0, op1 }},
#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) { TOK_ASM_ ## name, O(opcode), T(opcode, instr_type, group), 3, { op0, op1, op2 }}, #define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) { TOK_ASM_ ## name, O(opcode), T(opcode, instr_type, group), 3, { op0, op1, op2 }},
#include "i386-asm.h" #include "asm.h"
/* last operation */ /* last operation */
{ 0, }, { 0, },
}; };
@ -216,7 +213,7 @@ static const uint16_t op0_codes[] = {
#define DEF_ASM_OP1(name, opcode, group, instr_type, op0) #define DEF_ASM_OP1(name, opcode, group, instr_type, op0)
#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) #define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1)
#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) #define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2)
#include "i386-asm.h" #include "asm.h"
}; };
static inline int get_reg_shift(TCCState *s1) static inline int get_reg_shift(TCCState *s1)
@ -1293,11 +1290,6 @@ ST_FUNC void subst_asm_operand(CString *add_str,
size = 1; size = 1;
else if ((sv->type.t & VT_BTYPE) == VT_SHORT) else if ((sv->type.t & VT_BTYPE) == VT_SHORT)
size = 2; size = 2;
#ifdef TCC_TARGET_X86_64
else if ((sv->type.t & VT_BTYPE) == VT_LLONG ||
(sv->type.t & VT_BTYPE) == VT_PTR)
size = 8;
#endif
else else
size = 4; size = 4;
if (size == 1 && reg >= 4) if (size == 1 && reg >= 4)

View file

@ -99,13 +99,6 @@ ST_DATA const int reg_classes[NB_REGS] = {
static unsigned long func_sub_sp_offset; static unsigned long func_sub_sp_offset;
static int func_ret_sub; static int func_ret_sub;
#ifdef CONFIG_TCC_BCHECK
static addr_t func_bound_offset;
static unsigned long func_bound_ind;
ST_DATA int func_bound_add_epilog;
static void gen_bounds_prolog(void);
static void gen_bounds_epilog(void);
#endif
/* XXX: make it faster ? */ /* XXX: make it faster ? */
ST_FUNC void g(int c) ST_FUNC void g(int c)
@ -335,17 +328,6 @@ static void gadd_sp(int val)
} }
} }
#if defined CONFIG_TCC_BCHECK || defined TCC_TARGET_PE
static void gen_static_call(int v)
{
Sym *sym;
sym = external_helper_sym(v);
oad(0xe8, -4);
greloc(cur_text_section, sym, ind-4, R_386_PC32);
}
#endif
/* 'is_jmp' is '1' if it is a jump */ /* 'is_jmp' is '1' if it is a jump */
static void gcall_or_jmp(int is_jmp) static void gcall_or_jmp(int is_jmp)
{ {
@ -401,11 +383,6 @@ ST_FUNC void gfunc_call(int nb_args)
int size, align, r, args_size, i, func_call; int size, align, r, args_size, i, func_call;
Sym *func_sym; Sym *func_sym;
#ifdef CONFIG_TCC_BCHECK
if (tcc_state->do_bounds_check)
gbound_args(nb_args);
#endif
args_size = 0; args_size = 0;
for(i = 0;i < nb_args; i++) { for(i = 0;i < nb_args; i++) {
if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) { if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
@ -591,10 +568,6 @@ ST_FUNC void gfunc_prolog(Sym *func_sym)
func_ret_sub = 4; func_ret_sub = 4;
#endif #endif
#ifdef CONFIG_TCC_BCHECK
if (tcc_state->do_bounds_check)
gen_bounds_prolog();
#endif
} }
/* generate function epilog */ /* generate function epilog */
@ -602,11 +575,6 @@ ST_FUNC void gfunc_epilog(void)
{ {
addr_t v, saved_ind; addr_t v, saved_ind;
#ifdef CONFIG_TCC_BCHECK
if (tcc_state->do_bounds_check)
gen_bounds_epilog();
#endif
/* align local size to word & save local variables */ /* align local size to word & save local variables */
v = (-loc + 3) & -4; v = (-loc + 3) & -4;
@ -1043,55 +1011,6 @@ ST_FUNC void ggoto(void)
vtop--; vtop--;
} }
/* bound check support functions */
#ifdef CONFIG_TCC_BCHECK
static void gen_bounds_prolog(void)
{
/* leave some room for bound checking code */
func_bound_offset = lbounds_section->data_offset;
func_bound_ind = ind;
func_bound_add_epilog = 0;
oad(0xb8, 0); /* lbound section pointer */
oad(0xb8, 0); /* call to function */
}
static void gen_bounds_epilog(void)
{
addr_t saved_ind;
addr_t *bounds_ptr;
Sym *sym_data;
int offset_modified = func_bound_offset != lbounds_section->data_offset;
if (!offset_modified && !func_bound_add_epilog)
return;
/* add end of table info */
bounds_ptr = section_ptr_add(lbounds_section, sizeof(addr_t));
*bounds_ptr = 0;
sym_data = get_sym_ref(&char_pointer_type, lbounds_section,
func_bound_offset, PTR_SIZE);
/* generate bound local allocation */
if (offset_modified) {
saved_ind = ind;
ind = func_bound_ind;
greloc(cur_text_section, sym_data, ind + 1, R_386_32);
ind = ind + 5;
gen_static_call(TOK___bound_local_new);
ind = saved_ind;
}
/* generate bound check local freeing */
o(0x5250); /* save returned value, if any */
greloc(cur_text_section, sym_data, ind + 1, R_386_32);
oad(0xb8, 0); /* mov %eax, xxx */
gen_static_call(TOK___bound_local_delete);
o(0x585a); /* restore returned value, if any */
}
#endif
/* Save the stack pointer onto the stack */ /* Save the stack pointer onto the stack */
ST_FUNC void gen_vla_sp_save(int addr) { ST_FUNC void gen_vla_sp_save(int addr) {
/* mov %esp,addr(%ebp)*/ /* mov %esp,addr(%ebp)*/
@ -1109,9 +1028,6 @@ ST_FUNC void gen_vla_sp_restore(int addr) {
ST_FUNC void gen_vla_alloc(CType *type, int align) { ST_FUNC void gen_vla_alloc(CType *type, int align) {
int use_call = 0; int use_call = 0;
#if defined(CONFIG_TCC_BCHECK)
use_call = tcc_state->do_bounds_check;
#endif
#ifdef TCC_TARGET_PE /* alloca does more than just adjust %rsp on Windows */ #ifdef TCC_TARGET_PE /* alloca does more than just adjust %rsp on Windows */
use_call = 1; use_call = 1;
#endif #endif

View file

@ -99,11 +99,7 @@ ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_
int modrm; int modrm;
unsigned plt_offset, relofs; unsigned plt_offset, relofs;
/* on i386 if we build a DLL, we add a %ebx offset */ modrm = 0x25;
if (s1->output_type & TCC_OUTPUT_DYN)
modrm = 0xa3;
else
modrm = 0x25;
/* empty PLT: create PLT0 entry that pushes the library identifier /* empty PLT: create PLT0 entry that pushes the library identifier
(GOT + PTR_SIZE) and jumps to ld.so resolution routine (GOT + PTR_SIZE) and jumps to ld.so resolution routine
@ -148,7 +144,7 @@ ST_FUNC void relocate_plt(TCCState *s1)
p = s1->plt->data; p = s1->plt->data;
p_end = p + s1->plt->data_offset; p_end = p + s1->plt->data_offset;
if (!(s1->output_type & TCC_OUTPUT_DYN) && p < p_end) { if (p < p_end) {
add32le(p + 2, s1->got->sh_addr); add32le(p + 2, s1->got->sh_addr);
add32le(p + 8, s1->got->sh_addr); add32le(p + 8, s1->got->sh_addr);
p += 16; p += 16;
@ -179,31 +175,9 @@ ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
switch (type) { switch (type) {
case R_386_32: case R_386_32:
if (s1->output_type & TCC_OUTPUT_DYN) {
esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index;
qrel->r_offset = rel->r_offset;
if (esym_index) {
qrel->r_info = ELFW(R_INFO)(esym_index, R_386_32);
qrel++;
return;
} else {
qrel->r_info = ELFW(R_INFO)(0, R_386_RELATIVE);
qrel++;
}
}
add32le(ptr, val); add32le(ptr, val);
return; return;
case R_386_PC32: case R_386_PC32:
if (s1->output_type == TCC_OUTPUT_DLL) {
/* DLL relocation */
esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index;
if (esym_index) {
qrel->r_offset = rel->r_offset;
qrel->r_info = ELFW(R_INFO)(esym_index, R_386_PC32);
qrel++;
return;
}
}
add32le(ptr, val - addr); add32le(ptr, val - addr);
return; return;
case R_386_PLT32: case R_386_PLT32:

View file

@ -266,7 +266,7 @@
#define DEF_ASM_OP1(name, opcode, group, instr_type, op0) #define DEF_ASM_OP1(name, opcode, group, instr_type, op0)
#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) #define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1)
#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) #define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2)
#include "i386-asm.h" #include "asm.h"
#define ALT(x) #define ALT(x)
#define DEF_ASM_OP0(name, opcode) #define DEF_ASM_OP0(name, opcode)
@ -274,4 +274,4 @@
#define DEF_ASM_OP1(name, opcode, group, instr_type, op0) DEF_ASM(name) #define DEF_ASM_OP1(name, opcode, group, instr_type, op0) DEF_ASM(name)
#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) DEF_ASM(name) #define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) DEF_ASM(name)
#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) DEF_ASM(name) #define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) DEF_ASM(name)
#include "i386-asm.h" #include "asm.h"

View file

@ -19,6 +19,7 @@
*/ */
#include "tcc.h" #include "tcc.h"
#include "utils/string.h"
/********************************************************/ /********************************************************/
/* global variables */ /* global variables */
@ -78,44 +79,6 @@ PUB_FUNC void tcc_exit_state(TCCState *s1)
POST_SEM(&tcc_compile_sem); POST_SEM(&tcc_compile_sem);
} }
/********************************************************/
/* copy a string and truncate it. */
ST_FUNC char *pstrcpy(char *buf, size_t buf_size, const char *s)
{
char *q, *q_end;
int c;
if (buf_size > 0) {
q = buf;
q_end = buf + buf_size - 1;
while (q < q_end) {
c = *s++;
if (c == '\0')
break;
*q++ = c;
}
*q = '\0';
}
return buf;
}
/* strcat and truncate. */
ST_FUNC char *pstrcat(char *buf, size_t buf_size, const char *s)
{
size_t len;
len = strlen(buf);
if (len < buf_size)
pstrcpy(buf + len, buf_size - len, s);
return buf;
}
ST_FUNC char *pstrncpy(char *out, const char *in, size_t num)
{
memcpy(out, in, num);
out[num] = '\0';
return out;
}
/* extract the basename of a file */ /* extract the basename of a file */
PUB_FUNC char *tcc_basename(const char *name) PUB_FUNC char *tcc_basename(const char *name)
{ {
@ -180,7 +143,7 @@ ST_FUNC void libc_free(void *ptr)
/* global so that every tcc_alloc()/tcc_free() call doesn't need to be changed */ /* global so that every tcc_alloc()/tcc_free() call doesn't need to be changed */
static void *(*reallocator)(void*, unsigned long) = default_reallocator; static void *(*reallocator)(void*, unsigned long) = default_reallocator;
LIBTCCAPI void tcc_set_realloc(TCCReallocFunc *realloc) void tcc_set_realloc(TCCReallocFunc *realloc)
{ {
reallocator = realloc ? realloc : default_reallocator; reallocator = realloc ? realloc : default_reallocator;
} }
@ -574,7 +537,7 @@ static void error1(int mode, const char *fmt, va_list ap)
} }
} }
LIBTCCAPI void tcc_set_error_func(TCCState *s, void *error_opaque, TCCErrorFunc *error_func) void tcc_set_error_func(TCCState *s, void *error_opaque, TCCErrorFunc *error_func)
{ {
s->error_opaque = error_opaque; s->error_opaque = error_opaque;
s->error_func = error_func; s->error_func = error_func;
@ -720,13 +683,13 @@ static int tcc_compile(TCCState *s1, int filetype, const char *str, int fd)
return s1->nb_errors != 0 ? -1 : 0; return s1->nb_errors != 0 ? -1 : 0;
} }
LIBTCCAPI int tcc_compile_string(TCCState *s, const char *str) int tcc_compile_string(TCCState *s, const char *str)
{ {
return tcc_compile(s, s->filetype, str, -1); return tcc_compile(s, s->filetype, str, -1);
} }
/* define a preprocessor symbol. value can be NULL, sym can be "sym=val" */ /* define a preprocessor symbol. value can be NULL, sym can be "sym=val" */
LIBTCCAPI void tcc_define_symbol(TCCState *s1, const char *sym, const char *value) void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
{ {
const char *eq; const char *eq;
if (NULL == (eq = strchr(sym, '='))) if (NULL == (eq = strchr(sym, '=')))
@ -737,13 +700,13 @@ LIBTCCAPI void tcc_define_symbol(TCCState *s1, const char *sym, const char *valu
} }
/* undefine a preprocessor symbol */ /* undefine a preprocessor symbol */
LIBTCCAPI void tcc_undefine_symbol(TCCState *s1, const char *sym) void tcc_undefine_symbol(TCCState *s1, const char *sym)
{ {
cstr_printf(&s1->cmdline_defs, "#undef %s\n", sym); cstr_printf(&s1->cmdline_defs, "#undef %s\n", sym);
} }
LIBTCCAPI TCCState *tcc_new(void) TCCState *tcc_new(void)
{ {
TCCState *s; TCCState *s;
@ -779,7 +742,7 @@ LIBTCCAPI TCCState *tcc_new(void)
return s; return s;
} }
LIBTCCAPI void tcc_delete(TCCState *s1) void tcc_delete(TCCState *s1)
{ {
/* free sections */ /* free sections */
tccelf_delete(s1); tccelf_delete(s1);
@ -808,7 +771,6 @@ LIBTCCAPI void tcc_delete(TCCState *s1)
cstr_free(&s1->cmdline_defs); cstr_free(&s1->cmdline_defs);
cstr_free(&s1->cmdline_incl); cstr_free(&s1->cmdline_incl);
cstr_free(&s1->linker_arg); cstr_free(&s1->linker_arg);
tcc_free(s1->dState);
/* free loaded dlls array */ /* free loaded dlls array */
dynarray_reset(&s1->loaded_dlls, &s1->nb_loaded_dlls); dynarray_reset(&s1->loaded_dlls, &s1->nb_loaded_dlls);
tcc_free(s1); tcc_free(s1);
@ -817,12 +779,8 @@ LIBTCCAPI void tcc_delete(TCCState *s1)
#endif #endif
} }
LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type) int tcc_set_output_type(TCCState *s, int output_type)
{ {
#ifdef CONFIG_TCC_PIE
if (output_type == TCC_OUTPUT_EXE)
output_type |= TCC_OUTPUT_DYN;
#endif
s->output_type = output_type; s->output_type = output_type;
if (!s->nostdinc) { if (!s->nostdinc) {
@ -832,7 +790,6 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
} }
if (output_type == TCC_OUTPUT_PREPROCESS) { if (output_type == TCC_OUTPUT_PREPROCESS) {
s->do_debug = 0;
return 0; return 0;
} }
@ -854,13 +811,13 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
return 0; return 0;
} }
LIBTCCAPI int tcc_add_include_path(TCCState *s, const char *pathname) int tcc_add_include_path(TCCState *s, const char *pathname)
{ {
tcc_split_path(s, &s->include_paths, &s->nb_include_paths, pathname); tcc_split_path(s, &s->include_paths, &s->nb_include_paths, pathname);
return 0; return 0;
} }
LIBTCCAPI int tcc_add_sysinclude_path(TCCState *s, const char *pathname) int tcc_add_sysinclude_path(TCCState *s, const char *pathname)
{ {
tcc_split_path(s, &s->sysinclude_paths, &s->nb_sysinclude_paths, pathname); tcc_split_path(s, &s->sysinclude_paths, &s->nb_sysinclude_paths, pathname);
return 0; return 0;
@ -932,45 +889,10 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
ret = tcc_load_archive(s1, fd, !(flags & AFF_WHOLE_ARCHIVE)); ret = tcc_load_archive(s1, fd, !(flags & AFF_WHOLE_ARCHIVE));
break; break;
#ifdef TCC_TARGET_PE case AFF_BINTYPE_COFF:
default: ret = coff_load_file(s1, fd, filename);
ret = pe_load_file(s1, fd, filename); break;
goto check_success;
#elif defined TCC_TARGET_MACHO
case AFF_BINTYPE_DYN:
case_dyn_or_tbd:
if (s1->output_type == TCC_OUTPUT_MEMORY) {
#ifdef TCC_IS_NATIVE
void* dl;
const char* soname = filename;
if (obj_type != AFF_BINTYPE_DYN)
soname = macho_tbd_soname(filename);
dl = dlopen(soname, RTLD_GLOBAL | RTLD_LAZY);
if (dl)
tcc_add_dllref(s1, soname, 0)->handle = dl, ret = 0;
if (filename != soname)
tcc_free((void *)soname);
#endif
} else if (obj_type == AFF_BINTYPE_DYN) {
ret = macho_load_dll(s1, fd, filename, (flags & AFF_REFERENCED_DLL) != 0);
} else {
ret = macho_load_tbd(s1, fd, filename, (flags & AFF_REFERENCED_DLL) != 0);
}
goto check_success;
default:
{
const char *ext = tcc_fileextension(filename);
if (!strcmp(ext, ".tbd"))
goto case_dyn_or_tbd;
if (!strcmp(ext, ".dylib")) {
obj_type = AFF_BINTYPE_DYN;
goto case_dyn_or_tbd;
}
goto check_success;
}
#else /* unix */
case AFF_BINTYPE_DYN: case AFF_BINTYPE_DYN:
if (s1->output_type == TCC_OUTPUT_MEMORY) { if (s1->output_type == TCC_OUTPUT_MEMORY) {
} else } else
@ -980,20 +902,9 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
default: default:
/* as GNU ld, consider it is an ld script if not recognized */ /* as GNU ld, consider it is an ld script if not recognized */
ret = tcc_load_ldscript(s1, fd); ret = tcc_load_ldscript(s1, fd);
goto check_success;
#endif /* pe / macos / unix */
check_success:
if (ret < 0) if (ret < 0)
tcc_error_noabort("%s: unrecognized file type", filename); tcc_error_noabort("%s: unrecognized file type", filename);
break; break;
#ifdef TCC_TARGET_COFF
case AFF_BINTYPE_C67:
ret = tcc_load_coff(s1, fd);
break;
#endif
} }
close(fd); close(fd);
} else { } else {
@ -1030,12 +941,12 @@ static int guess_filetype(const char *filename)
return filetype; return filetype;
} }
LIBTCCAPI int tcc_add_file(TCCState *s, const char *filename) int tcc_add_file(TCCState *s, const char *filename)
{ {
return tcc_add_file_internal(s, filename, s->filetype | AFF_PRINT_ERROR); return tcc_add_file_internal(s, filename, s->filetype | AFF_PRINT_ERROR);
} }
LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname) int tcc_add_library_path(TCCState *s, const char *pathname)
{ {
tcc_split_path(s, &s->library_paths, &s->nb_library_paths, pathname); tcc_split_path(s, &s->library_paths, &s->nb_library_paths, pathname);
return 0; return 0;
@ -1074,7 +985,7 @@ ST_FUNC int tcc_add_support(TCCState *s1, const char *filename)
return tcc_add_dll(s1, filename, AFF_PRINT_ERROR); return tcc_add_dll(s1, filename, AFF_PRINT_ERROR);
} }
#if !defined TCC_TARGET_PE && !defined TCC_TARGET_MACHO #if !defined TCC_TARGET_PE
ST_FUNC int tcc_add_crt(TCCState *s1, const char *filename) ST_FUNC int tcc_add_crt(TCCState *s1, const char *filename)
{ {
return tcc_add_library_internal(s1, "%s/%s", return tcc_add_library_internal(s1, "%s/%s",
@ -1083,7 +994,7 @@ ST_FUNC int tcc_add_crt(TCCState *s1, const char *filename)
#endif #endif
/* the library name is the same as the argument of the '-l' option */ /* the library name is the same as the argument of the '-l' option */
LIBTCCAPI int tcc_add_library(TCCState *s, const char *libraryname) int tcc_add_library(TCCState *s, const char *libraryname)
{ {
static const char * const libs[] = { "%s/lib%s.a", NULL }; static const char * const libs[] = { "%s/lib%s.a", NULL };
const char * const *pp = libs; const char * const *pp = libs;
@ -1106,7 +1017,7 @@ ST_FUNC void tcc_add_pragma_libs(TCCState *s1)
tcc_add_library(s1, s1->pragma_libs[i]); tcc_add_library(s1, s1->pragma_libs[i]);
} }
LIBTCCAPI int tcc_add_symbol(TCCState *s1, const char *name, const void *val) int tcc_add_symbol(TCCState *s1, const char *name, const void *val)
{ {
char buf[256]; char buf[256];
if (s1->leading_underscore) { if (s1->leading_underscore) {
@ -1118,7 +1029,7 @@ LIBTCCAPI int tcc_add_symbol(TCCState *s1, const char *name, const void *val)
return 0; return 0;
} }
LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path) void tcc_set_lib_path(TCCState *s, const char *path)
{ {
tcc_free(s->tcc_lib_path); tcc_free(s->tcc_lib_path);
s->tcc_lib_path = tcc_strdup(path); s->tcc_lib_path = tcc_strdup(path);
@ -1393,13 +1304,6 @@ static const TCCOption tcc_options[] = {
{ "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG }, { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
{ "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG }, { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG },
{ "bench", TCC_OPTION_bench, 0 }, { "bench", TCC_OPTION_bench, 0 },
#ifdef CONFIG_TCC_BACKTRACE
{ "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
#endif
#ifdef CONFIG_TCC_BCHECK
{ "b", TCC_OPTION_b, 0 },
#endif
{ "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
{ "c", TCC_OPTION_c, 0 }, { "c", TCC_OPTION_c, 0 },
{ "dumpmachine", TCC_OPTION_dumpmachine, 0}, { "dumpmachine", TCC_OPTION_dumpmachine, 0},
{ "dumpversion", TCC_OPTION_dumpversion, 0}, { "dumpversion", TCC_OPTION_dumpversion, 0},
@ -1435,6 +1339,7 @@ static const TCCOption tcc_options[] = {
{ "ar", TCC_OPTION_ar, 0}, { "ar", TCC_OPTION_ar, 0},
/* ignored (silently, except after -Wunsupported) */ /* ignored (silently, except after -Wunsupported) */
{ "arch", 0, TCC_OPTION_HAS_ARG}, { "arch", 0, TCC_OPTION_HAS_ARG},
{ "g", 0, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP},
{ "C", 0, 0 }, { "C", 0, 0 },
{ "-param", 0, TCC_OPTION_HAS_ARG }, { "-param", 0, TCC_OPTION_HAS_ARG },
{ "pedantic", 0, 0 }, { "pedantic", 0, 0 },
@ -1470,7 +1375,6 @@ static const FlagDef options_f[] = {
{ offsetof(TCCState, leading_underscore), 0, "leading-underscore" }, { offsetof(TCCState, leading_underscore), 0, "leading-underscore" },
{ offsetof(TCCState, ms_extensions), 0, "ms-extensions" }, { offsetof(TCCState, ms_extensions), 0, "ms-extensions" },
{ offsetof(TCCState, dollars_in_identifiers), 0, "dollars-in-identifiers" }, { offsetof(TCCState, dollars_in_identifiers), 0, "dollars-in-identifiers" },
{ offsetof(TCCState, test_coverage), 0, "test-coverage" },
{ offsetof(TCCState, reverse_funcargs), 0, "reverse-funcargs" }, { offsetof(TCCState, reverse_funcargs), 0, "reverse-funcargs" },
{ offsetof(TCCState, gnu89_inline), 0, "gnu89-inline" }, { offsetof(TCCState, gnu89_inline), 0, "gnu89-inline" },
{ offsetof(TCCState, unwind_tables), 0, "asynchronous-unwind-tables" }, { offsetof(TCCState, unwind_tables), 0, "asynchronous-unwind-tables" },
@ -1675,32 +1579,6 @@ dorun:
case TCC_OPTION_bench: case TCC_OPTION_bench:
s->do_bench = 1; s->do_bench = 1;
break; break;
#ifdef CONFIG_TCC_BACKTRACE
case TCC_OPTION_bt:
s->rt_num_callers = atoi(optarg); /* zero = default (6) */
goto enable_backtrace;
enable_backtrace:
s->do_backtrace = 1;
s->do_debug = s->do_debug ? s->do_debug : 1;
s->dwarf = CONFIG_DWARF_VERSION;
break;
#ifdef CONFIG_TCC_BCHECK
case TCC_OPTION_b:
s->do_bounds_check = 1;
goto enable_backtrace;
#endif
#endif
case TCC_OPTION_g:
s->do_debug = 2;
s->dwarf = CONFIG_DWARF_VERSION;
if (strstart("dwarf", &optarg)) {
s->dwarf = (*optarg) ? (0 - atoi(optarg)) : DEFAULT_DWARF_VERSION;
} else if (isnum(*optarg)) {
x = *optarg - '0';
/* -g0 = no info, -g1 = lines/functions only, -g2 = full info */
s->do_debug = x > 2 ? 2 : x == 0 && s->do_backtrace ? 1 : x;
}
break;
case TCC_OPTION_c: case TCC_OPTION_c:
x = TCC_OUTPUT_OBJ; x = TCC_OUTPUT_OBJ;
set_output_type: set_output_type:
@ -1713,8 +1591,6 @@ dorun:
s->dflag = 3; s->dflag = 3;
else if (*optarg == 'M') else if (*optarg == 'M')
s->dflag = 7; s->dflag = 7;
else if (*optarg == 't')
s->dflag = 16;
else if (isnum(*optarg)) else if (isnum(*optarg))
s->g_debug |= atoi(optarg); s->g_debug |= atoi(optarg);
else else
@ -1727,9 +1603,6 @@ dorun:
if (strcmp(optarg, "=c11") == 0 || strcmp(optarg, "=gnu11") == 0) if (strcmp(optarg, "=c11") == 0 || strcmp(optarg, "=gnu11") == 0)
s->cversion = 201112; s->cversion = 201112;
break; break;
case TCC_OPTION_shared:
x = TCC_OUTPUT_DLL;
goto set_output_type;
case TCC_OPTION_soname: case TCC_OPTION_soname:
s->soname = tcc_strdup(optarg); s->soname = tcc_strdup(optarg);
break; break;
@ -1885,7 +1758,7 @@ unsupported_option:
return OPT_HELP; return OPT_HELP;
} }
LIBTCCAPI int tcc_set_options(TCCState *s, const char *r) int tcc_set_options(TCCState *s, const char *r)
{ {
char **argv = NULL; char **argv = NULL;
int argc = 0, ret; int argc = 0, ret;
@ -1913,15 +1786,6 @@ PUB_FUNC void tcc_print_stats(TCCState *s1, unsigned total_time)
); );
#ifdef MEM_DEBUG #ifdef MEM_DEBUG
fprintf(stderr, "# memory usage"); fprintf(stderr, "# memory usage");
#ifdef TCC_IS_NATIVE
if (s1->run_size) {
Section *s = s1->symtab;
unsigned ms = s->data_offset + s->link->data_offset + s->hash->data_offset;
unsigned rs = s1->run_size;
fprintf(stderr, ": %d to run, %d symbols, %d other,",
rs, ms, mem_cur_size - rs - ms);
}
#endif
fprintf(stderr, " %d max (bytes)\n", mem_max_size); fprintf(stderr, " %d max (bytes)\n", mem_max_size);
#endif #endif
} }

179
libtcc/libtcc.h Normal file
View file

@ -0,0 +1,179 @@
#ifndef LIBTCC_H
# define LIBTCC_H 1
# ifdef __cplusplus
extern "C" {
# endif /* __cplusplus */
typedef void *TCCReallocFunc(void *ptr, unsigned long size);
/**
* @brief set custom allocator for all allocations (optional), NULL for default.
*/
void tcc_set_realloc(TCCReallocFunc *my_realloc);
typedef struct TCCState TCCState;
/**
* @brief create a new TCC compilation context.
*/
TCCState *tcc_new(void);
/**
* @brief free a TCC compilation context.
*/
void tcc_delete(TCCState *s);
/**
* @brief set CONFIG_TCCDIR at runtime.
*/
void tcc_set_lib_path(TCCState *s, const char *path);
typedef void TCCErrorFunc(void *opaque, const char *msg);
/**
* @brief set error/warning callback (optional).
*/
void tcc_set_error_func(TCCState *s, void *error_opaque, TCCErrorFunc *error_func);
/**
* @brief set options as from command line (multiple supported)
*/
int tcc_set_options(TCCState *s, const char *str);
/**
* @defgroup preprocessor Preprocessor
* @{
*/
/**
* @brief add include path
*/
int tcc_add_include_path(TCCState *s, const char *pathname);
/**
* @brief add in system include path
*/
int tcc_add_sysinclude_path(TCCState *s, const char *pathname);
/**
* @brief define preprocessor symbol 'sym'. value can be NULL, sym can be "sym=val"
*/
void tcc_define_symbol(TCCState *s, const char *sym, const char *value);
/**
* @brief undefine preprocess symbol 'sym'
*/
void tcc_undefine_symbol(TCCState *s, const char *sym);
/**
* @}
*/
/**
* @defgroup compiling Compiling
* @{
*/
/**
* @brief add a file (C file, object, library, ld script). Return -1 if error.
*/
int tcc_add_file(TCCState *s, const char *filename);
/**
* @brief compile a string containing a C source. Return -1 if error.
*
* Tip: to have more specific errors/warnings from tcc_compile_string(),
* you can prefix the string with "#line <num> \"<filename>\"\n"
*/
int tcc_compile_string(TCCState *s, const char *buf);
/**
* @}
*/
/**
* @defgroup linking Linking commands
* @{
*/
# define TCC_OUTPUT_MEMORY 1 /** output will be run in memory */
# define TCC_OUTPUT_EXE 2 /** executable file */
# define TCC_OUTPUT_OBJ 3 /** object file */
# define TCC_OUTPUT_PREPROCESS 5 /** only preprocess */
/**
* @brief set output type. MUST BE CALLED before any compilation.
*/
int tcc_set_output_type(TCCState *s, int output_type);
/**
* @brief equivalent to -Lpath option.
*/
int tcc_add_library_path(TCCState *s, const char *pathname);
/**
* @brief the library name is the same as the argument of the '-l' option.
*/
int tcc_add_library(TCCState *s, const char *libraryname);
/**
* @brief add a symbol to the compiled program.
*/
int tcc_add_symbol(TCCState *s, const char *name, const void *val);
/**
* @brief output an executable, library or object file.
*
* DO NOT call tcc_relocate() before.
*/
int tcc_output_file(TCCState *s, const char *filename);
/**
* @brief do all relocations (needed before using tcc_get_symbol()).
*/
int tcc_relocate(TCCState *s1);
/**
* @brief return symbol value or NULL if not found.
*/
void *tcc_get_symbol(TCCState *s, const char *name);
typedef void (TCCSymbolFunc)(void *ctx, const char *name, const void *val);
/**
* @brief list all (global) symbols and their values via 'symbol_cb()'.
*/
void tcc_list_symbols(TCCState *s, void *ctx, TCCSymbolFunc *symbol_cb);
/**
* @}
*/
/**
* experimental/advanced section (see libtcc_test_mt.c for an example).
* @defgroup experimental Experimental/Advanced
* @{
*/
/**
* @brief catch runtime exceptions (optionally limit backtraces at top_func), when using tcc_set_options("-bt").
*/
void *_tcc_setjmp(TCCState *s1, void *jmp_buf, void *top_func, void *longjmp);
# define tcc_setjmp(s1,jb,f) setjmp(_tcc_setjmp(s1, jb, f, longjmp))
typedef int TCCBtFunc(void *udata, void *pc, const char *file, int line, const char* func, const char *msg);
/**
* @brief custom error printer for runtime exceptions. Returning 0 stops backtrace.
*/
void tcc_set_backtrace_func(TCCState *s1, void* userdata, TCCBtFunc*);
/**
* @}
*/
# ifdef __cplusplus
}
# endif /* __cplusplus */
#endif /* !TCC_H */

35
libtcc/object/archive.h Normal file
View file

@ -0,0 +1,35 @@
#ifndef LIBTCC_OBJECT_ARCHIVE_H
# define LIBTCC_OBJECT_ARCHIVE_H 1
/**
* @defgroup object_archive UNIX Archive
* @ingroup object
* @{
*/
# define ARCHIVE_MAGIC "!<arch>\n"
# define ARCHIVE_MAGSZ 8
# define ARCHIVE_FILMAG "`\n"
typedef struct ArchiveFileHeader {
char name[16];
char last_mod[12];
char uid[6];
char gid[6];
char mode[8];
char size[10];
char fmag[2];
} ArchiveFileHeader;
typedef struct ArchiveEntry {
} ArchiveEntry;
typedef struct Archive {
char *filename;
} Archive;
/**
* @}
*/
#endif /* !LIBTCC_OBJECT_AR_H */

69
libtcc/object/coff.h Normal file
View file

@ -0,0 +1,69 @@
#ifndef LIBTCC_OBJECT_COFF_H
# define LIBTCC_OBJECT_COFF_H 1
# include <stdint.h>
/**
* @defgroup object_coff COFF Object
* @ingroup object
* @{
*/
# define COFF_MAGIC 0x14c
typedef struct COFFFileHeader {
uint16_t magic;
uint16_t nscns;
int32_t timdat;
int32_t nsyms;
uint16_t opthdr;
uint16_t flags;
} COFFFileHeader;
# define COFF_FILHSZ sizeof(COFFFileHeader)
# define COFF_F_RELFLG 0x0001
# define COFF_F_EXEC 0x0002
# define COFF_F_LNNO 0x0004
# define COFF_F_LSYMS 0x0008
# define COFF_F_LITTLE 0x0100
# define COFF_F_BIG 0x0200
# define COFF_F_SYMMERGE 0x1000
typedef struct AOutHeader {
int16_t magic;
int16_t vstamp;
int32_t tsize;
int32_t dsize;
int32_t bsize;
int32_t entry;
int32_t text_start;
int32_t data_start;
} AOutHeader;
# define AOUT_HSZ sizeof(AOutHeader)
# define AOUT_OMAGIC 0404
# define AOUT_NMAGIC 0410
# define AOUT_ZMAGIC 0413
# define AOUT_STMAGIC 0401
# define AOUT_SHMAGIC 0443
typedef struct COFFSectionHeader {
int8_t name[8];
int32_t paddr;
int32_t vaddr;
int32_t size;
int32_t scnptr;
int32_t relptr;
int32_t lnnoptr;
uint16_t nreloc;
uint16_t nlnno;
int32_t flags;
} COFFSectionHeader;
/**
* @}
*/
#endif /* !LIBTCC_COFF_H */

2
libtcc/option.c Normal file
View file

@ -0,0 +1,2 @@
#include "tcc.h"

6
libtcc/option.h Normal file
View file

@ -0,0 +1,6 @@
#ifndef LIBTCC_OPTION_H
# define LIBTCC_OPTION_H 1
int tcc_parse_args(void *s, int *argc, char ***argv, int optind);
#endif /* LIBTCC_OPTION_H */

View file

@ -69,7 +69,7 @@ extern long double strtold (const char *__nptr, char **__endptr);
# define strtoull _strtoui64 # define strtoull _strtoui64
# endif # endif
# ifdef LIBTCC_AS_DLL # ifdef LIBTCC_AS_DLL
# define LIBTCCAPI __declspec(dllexport) # define __declspec(dllexport)
# define PUB_FUNC LIBTCCAPI # define PUB_FUNC LIBTCCAPI
# endif # endif
# ifdef _MSC_VER # ifdef _MSC_VER
@ -138,29 +138,8 @@ extern long double strtold (const char *__nptr, char **__endptr);
/* assembler debug */ /* assembler debug */
/* #define ASM_DEBUG */ /* #define ASM_DEBUG */
/* target selection */
/* #define TCC_TARGET_I386 *//* i386 code generator */
/* #define TCC_TARGET_X86_64 *//* x86-64 code generator */
/* #define TCC_TARGET_ARM *//* ARMv4 code generator */
/* #define TCC_TARGET_ARM64 *//* ARMv8 code generator */
/* #define TCC_TARGET_C67 *//* TMS320C67xx code generator */
/* #define TCC_TARGET_RISCV64 *//* risc-v code generator */
/* default target is I386 */
# define TCC_TARGET_I386 # define TCC_TARGET_I386
#if defined CONFIG_TCC_BACKTRACE && CONFIG_TCC_BACKTRACE==0
# undef CONFIG_TCC_BACKTRACE
#else
# define CONFIG_TCC_BACKTRACE 1 /* enable builtin stack backtraces */
#endif
#if defined CONFIG_TCC_BCHECK && CONFIG_TCC_BCHECK==0
# undef CONFIG_TCC_BCHECK
#else
# define CONFIG_TCC_BCHECK 1 /* enable bound checking code */
#endif
#ifdef CONFIG_TCC_PIE #ifdef CONFIG_TCC_PIE
# define CONFIG_TCC_PIC 1 # define CONFIG_TCC_PIC 1
#endif #endif
@ -231,14 +210,6 @@ extern long double strtold (const char *__nptr, char **__endptr);
# define CONFIG_TCC_ELFINTERP "/lib/ld.so" # define CONFIG_TCC_ELFINTERP "/lib/ld.so"
# elif defined(TCC_TARGET_PE) # elif defined(TCC_TARGET_PE)
# define CONFIG_TCC_ELFINTERP "-" # define CONFIG_TCC_ELFINTERP "-"
# elif defined TCC_TARGET_ARM64
# define CONFIG_TCC_ELFINTERP "/lib/ld-linux-aarch64.so.1"
# elif defined(TCC_TARGET_X86_64)
# define CONFIG_TCC_ELFINTERP "/lib64/ld-linux-x86-64.so.2"
# elif defined(TCC_TARGET_RISCV64)
# define CONFIG_TCC_ELFINTERP "/lib/ld-linux-riscv64-lp64d.so.1"
# elif defined(TCC_ARM_EABI)
# define DEFAULT_ELFINTERP(s) default_elfinterp(s)
# else # else
# define CONFIG_TCC_ELFINTERP "/lib/ld-linux.so.2" # define CONFIG_TCC_ELFINTERP "/lib/ld-linux.so.2"
# endif # endif
@ -268,8 +239,7 @@ extern long double strtold (const char *__nptr, char **__endptr);
#include "libtcc.h" #include "libtcc.h"
#include "elf.h" #include "elf.h"
#include "stab.h" #include "coff.h"
#include "dwarf.h"
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -290,8 +260,8 @@ extern long double strtold (const char *__nptr, char **__endptr);
/* include the target specific definitions */ /* include the target specific definitions */
#define TARGET_DEFS_ONLY #define TARGET_DEFS_ONLY
# include "i386-gen.c" # include "i386/gen.c"
# include "i386-link.c" # include "i386/link.c"
#undef TARGET_DEFS_ONLY #undef TARGET_DEFS_ONLY
# define ELFCLASSW ELFCLASS32 # define ELFCLASSW ELFCLASS32
@ -606,9 +576,6 @@ struct sym_attr {
unsigned plt_offset; unsigned plt_offset;
int plt_sym; int plt_sym;
int dyn_index; int dyn_index;
#ifdef TCC_TARGET_ARM
unsigned char plt_thumb_stub:1;
#endif
}; };
struct TCCState { struct TCCState {
@ -653,16 +620,6 @@ struct TCCState {
unsigned char include_sys_deps; /* option -MD */ unsigned char include_sys_deps; /* option -MD */
unsigned char gen_phony_deps; /* option -MP */ unsigned char gen_phony_deps; /* option -MP */
/* compile with debug symbol (and use them if error during execution) */
unsigned char do_debug;
unsigned char dwarf;
unsigned char do_backtrace;
#ifdef CONFIG_TCC_BCHECK
/* compile with built-in memory and bounds checker */
unsigned char do_bounds_check;
#endif
unsigned char test_coverage; /* generate test coverage code */
/* use GNU C extensions */ /* use GNU C extensions */
unsigned char gnu_ext; unsigned char gnu_ext;
/* use TinyCC extensions */ /* use TinyCC extensions */
@ -671,19 +628,11 @@ struct TCCState {
unsigned char dflag; /* -dX value */ unsigned char dflag; /* -dX value */
unsigned char Pflag; /* -P switch (LINE_MACRO_OUTPUT_FORMAT) */ unsigned char Pflag; /* -P switch (LINE_MACRO_OUTPUT_FORMAT) */
#ifdef TCC_TARGET_X86_64
unsigned char nosse; /* For -mno-sse support. */
#endif
#ifdef TCC_TARGET_ARM
unsigned char float_abi; /* float ABI of the generated code*/
#endif
unsigned char has_text_addr; unsigned char has_text_addr;
addr_t text_addr; /* address of text section */ addr_t text_addr; /* address of text section */
unsigned section_align; /* section alignment */ unsigned section_align; /* section alignment */
#ifdef TCC_TARGET_I386
int seg_size; /* 32. Can be 16 with i386 assembler (.code16) */ int seg_size; /* 32. Can be 16 with i386 assembler (.code16) */
#endif
char *tcc_lib_path; /* CONFIG_TCCDIR or -B option */ char *tcc_lib_path; /* CONFIG_TCCDIR or -B option */
char *soname; /* as specified on the command line (-soname) */ char *soname; /* as specified on the command line (-soname) */
@ -697,8 +646,6 @@ struct TCCState {
int output_type; int output_type;
/* output format, see TCC_OUTPUT_FORMAT_xxx */ /* output format, see TCC_OUTPUT_FORMAT_xxx */
int output_format; int output_format;
/* nth test to run with -dt -run */
int run_test;
/* array of all loaded dlls (including those referenced by loaded dlls) */ /* array of all loaded dlls (including those referenced by loaded dlls) */
DLLReference **loaded_dlls; DLLReference **loaded_dlls;
@ -772,11 +719,6 @@ struct TCCState {
Section *text_section, *data_section, *rodata_section, *bss_section; Section *text_section, *data_section, *rodata_section, *bss_section;
Section *common_section; Section *common_section;
Section *cur_text_section; /* current section where function code is generated */ Section *cur_text_section; /* current section where function code is generated */
#ifdef CONFIG_TCC_BCHECK
/* bound check related sections */
Section *bounds_section; /* contains global data bound description */
Section *lbounds_section; /* contains local data bound description */
#endif
/* symbol section */ /* symbol section */
union { Section *symtab_section, *symtab; }; /* historical alias */ union { Section *symtab_section, *symtab; }; /* historical alias */
/* temporary dynamic symbol sections (for dll loading) */ /* temporary dynamic symbol sections (for dll loading) */
@ -789,19 +731,6 @@ struct TCCState {
Section *eh_frame_section; Section *eh_frame_section;
Section *eh_frame_hdr_section; Section *eh_frame_hdr_section;
unsigned long eh_start; unsigned long eh_start;
/* debug sections */
Section *stab_section;
Section *dwarf_info_section;
Section *dwarf_abbrev_section;
Section *dwarf_line_section;
Section *dwarf_aranges_section;
Section *dwarf_str_section;
Section *dwarf_line_str_section;
int dwlo, dwhi; /* dwarf section range */
/* test coverage */
Section *tcov_section;
/* debug state */
struct _tccdbg *dState;
/* Is there a new undefined sym since last new_undef_sym() */ /* Is there a new undefined sym since last new_undef_sym() */
int new_undef_sym; int new_undef_sym;
@ -812,11 +741,6 @@ struct TCCState {
ElfW_Rel *qrel; ElfW_Rel *qrel;
#define qrel s1->qrel #define qrel s1->qrel
#ifdef TCC_TARGET_RISCV64
struct pcrel_hi { addr_t addr, val; } last_hi;
#define last_hi s1->last_hi
#endif
#ifdef TCC_TARGET_PE #ifdef TCC_TARGET_PE
/* PE info */ /* PE info */
int pe_subsystem; int pe_subsystem;
@ -824,17 +748,6 @@ struct TCCState {
unsigned pe_file_align; unsigned pe_file_align;
unsigned pe_stack_size; unsigned pe_stack_size;
addr_t pe_imagebase; addr_t pe_imagebase;
# ifdef TCC_TARGET_X86_64
Section *uw_pdata;
int uw_sym;
unsigned uw_offs;
# endif
#endif
#if defined TCC_TARGET_MACHO
char *install_name;
uint32_t compatibility_version;
uint32_t current_version;
#endif #endif
#ifndef ELF_OBJ_ONLY #ifndef ELF_OBJ_ONLY
@ -847,24 +760,6 @@ struct TCCState {
Section *verneed_section; Section *verneed_section;
#endif #endif
#ifdef TCC_IS_NATIVE
const char *run_main; /* entry for tcc_run() */
void *run_ptr; /* runtime_memory */
unsigned run_size; /* size of runtime_memory */
#ifdef _WIN64
void *run_function_table; /* unwind data */
#endif
struct TCCState *next;
struct rt_context *rc; /* pointer to backtrace info block */
void *run_lj, *run_jb; /* sj/lj for tcc_setjmp()/tcc_run() */
TCCBtFunc *bt_func;
void *bt_data;
#endif
#ifdef CONFIG_TCC_BACKTRACE
int rt_num_callers;
#endif
/* benchmark info */ /* benchmark info */
int total_idents; int total_idents;
int total_lines; int total_lines;
@ -1079,9 +974,6 @@ ST_DATA void** stk_data;
ST_DATA int nb_stk_data; ST_DATA int nb_stk_data;
/* public functions currently used by the tcc main function */ /* public functions currently used by the tcc main function */
ST_FUNC char *pstrcpy(char *buf, size_t buf_size, const char *s);
ST_FUNC char *pstrcat(char *buf, size_t buf_size, const char *s);
ST_FUNC char *pstrncpy(char *out, const char *in, size_t num);
PUB_FUNC char *tcc_basename(const char *name); PUB_FUNC char *tcc_basename(const char *name);
PUB_FUNC char *tcc_fileextension (const char *name); PUB_FUNC char *tcc_fileextension (const char *name);
@ -1153,10 +1045,10 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
#define AFF_TYPE_LIB 8 #define AFF_TYPE_LIB 8
#define AFF_TYPE_MASK (15 | AFF_TYPE_BIN) #define AFF_TYPE_MASK (15 | AFF_TYPE_BIN)
/* values from tcc_object_type(...) */ /* values from tcc_object_type(...) */
#define AFF_BINTYPE_REL 1 #define AFF_BINTYPE_REL 1
#define AFF_BINTYPE_DYN 2 #define AFF_BINTYPE_DYN 2
#define AFF_BINTYPE_AR 3 #define AFF_BINTYPE_AR 3
#define AFF_BINTYPE_C67 4 #define AFF_BINTYPE_COFF 4
/* return value of tcc_add_file_internal(): 0, -1, or FILE_NOT_FOUND */ /* return value of tcc_add_file_internal(): 0, -1, or FILE_NOT_FOUND */
#define FILE_NOT_FOUND -2 #define FILE_NOT_FOUND -2
@ -1166,12 +1058,7 @@ ST_FUNC int tcc_add_crt(TCCState *s, const char *filename);
#endif #endif
ST_FUNC int tcc_add_dll(TCCState *s, const char *filename, int flags); ST_FUNC int tcc_add_dll(TCCState *s, const char *filename, int flags);
ST_FUNC int tcc_add_support(TCCState *s1, const char *filename); ST_FUNC int tcc_add_support(TCCState *s1, const char *filename);
#ifdef CONFIG_TCC_BCHECK
ST_FUNC void tcc_add_bcheck(TCCState *s1);
#endif
#ifdef CONFIG_TCC_BACKTRACE
ST_FUNC void tcc_add_btstub(TCCState *s1);
#endif
ST_FUNC void tcc_add_pragma_libs(TCCState *s1); ST_FUNC void tcc_add_pragma_libs(TCCState *s1);
PUB_FUNC int tcc_add_library_err(TCCState *s, const char *f); PUB_FUNC int tcc_add_library_err(TCCState *s, const char *f);
PUB_FUNC void tcc_print_stats(TCCState *s, unsigned total_time); PUB_FUNC void tcc_print_stats(TCCState *s, unsigned total_time);
@ -1353,9 +1240,6 @@ ST_FUNC void vpop(void);
#if PTR_SIZE == 4 #if PTR_SIZE == 4
ST_FUNC void lexpand(void); ST_FUNC void lexpand(void);
#endif #endif
#ifdef TCC_TARGET_ARM
ST_FUNC int get_reg_ex(int rc, int rc2);
#endif
ST_FUNC void save_reg(int r); ST_FUNC void save_reg(int r);
ST_FUNC void save_reg_upstack(int r, int n); ST_FUNC void save_reg_upstack(int r, int n);
ST_FUNC int get_reg(int rc); ST_FUNC int get_reg(int rc);
@ -1374,23 +1258,12 @@ ST_FUNC void indir(void);
ST_FUNC void unary(void); ST_FUNC void unary(void);
ST_FUNC void gexpr(void); ST_FUNC void gexpr(void);
ST_FUNC int expr_const(void); ST_FUNC int expr_const(void);
#if defined CONFIG_TCC_BCHECK || defined TCC_TARGET_C67
ST_FUNC Sym *get_sym_ref(CType *type, Section *sec, unsigned long offset, unsigned long size);
#endif
#if defined TCC_TARGET_X86_64 && !defined TCC_TARGET_PE
ST_FUNC int classify_x86_64_va_arg(CType *ty);
#endif
#ifdef CONFIG_TCC_BCHECK
ST_FUNC void gbound_args(int nb_args);
ST_DATA int func_bound_add_epilog;
#endif
/* ------------ tccelf.c ------------ */ /* ------------ tccelf.c ------------ */
#define TCC_OUTPUT_FORMAT_ELF 0 /* default output format: ELF */ #define TCC_OUTPUT_FORMAT_ELF 0 /* default output format: ELF */
#define TCC_OUTPUT_FORMAT_BINARY 1 /* binary image output */ #define TCC_OUTPUT_FORMAT_BINARY 1 /* binary image output */
#define TCC_OUTPUT_FORMAT_COFF 2 /* COFF */ #define TCC_OUTPUT_FORMAT_COFF 2 /* COFF */
#define TCC_OUTPUT_DYN TCC_OUTPUT_DLL
#define ARMAG "!<arch>\n" /* For COFF and a.out archives */ #define ARMAG "!<arch>\n" /* For COFF and a.out archives */
@ -1455,9 +1328,11 @@ ST_FUNC void tccelf_add_crtend(TCCState *s1);
ST_FUNC void tcc_add_runtime(TCCState *s1); ST_FUNC void tcc_add_runtime(TCCState *s1);
#endif #endif
int coff_load_file(TCCState *s1, int fd, const char *fname);
/* ------------ xxx-link.c ------------ */ /* ------------ xxx-link.c ------------ */
#if !defined ELF_OBJ_ONLY || defined TCC_TARGET_MACHO #if !defined ELF_OBJ_ONLY
ST_FUNC int code_reloc (int reloc_type); ST_FUNC int code_reloc (int reloc_type);
ST_FUNC int gotplt_entry_type (int reloc_type); ST_FUNC int gotplt_entry_type (int reloc_type);
/* Whether to generate a GOT/PLT entry and when. NO_GOTPLT_ENTRY is first so /* Whether to generate a GOT/PLT entry and when. NO_GOTPLT_ENTRY is first so
@ -1470,13 +1345,11 @@ enum gotplt_entry {
}; };
#define NEED_RELOC_TYPE #define NEED_RELOC_TYPE
#if !defined TCC_TARGET_MACHO || defined TCC_IS_NATIVE
ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr); ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr);
ST_FUNC void relocate_plt(TCCState *s1); ST_FUNC void relocate_plt(TCCState *s1);
ST_FUNC void build_got_entries(TCCState *s1, int got_sym); /* in tccelf.c */ ST_FUNC void build_got_entries(TCCState *s1, int got_sym); /* in tccelf.c */
#define NEED_BUILD_GOT #define NEED_BUILD_GOT
#endif
#endif #endif
ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val); ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val);
@ -1504,9 +1377,7 @@ ST_FUNC void gen_cvt_ftoi(int t);
ST_FUNC void gen_cvt_itof(int t); ST_FUNC void gen_cvt_itof(int t);
ST_FUNC void gen_cvt_ftof(int t); ST_FUNC void gen_cvt_ftof(int t);
ST_FUNC void ggoto(void); ST_FUNC void ggoto(void);
#ifndef TCC_TARGET_C67
ST_FUNC void o(unsigned int c); ST_FUNC void o(unsigned int c);
#endif
ST_FUNC void gen_vla_sp_save(int addr); ST_FUNC void gen_vla_sp_save(int addr);
ST_FUNC void gen_vla_sp_restore(int addr); ST_FUNC void gen_vla_sp_restore(int addr);
ST_FUNC void gen_vla_alloc(CType *type, int align); ST_FUNC void gen_vla_alloc(CType *type, int align);
@ -1584,17 +1455,15 @@ dwarf_read_sleb128(unsigned char **ln, unsigned char *end)
/* ------------ i386-gen.c ------------ */ /* ------------ i386-gen.c ------------ */
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 || defined TCC_TARGET_ARM
ST_FUNC void g(int c); ST_FUNC void g(int c);
ST_FUNC void gen_le16(int c); ST_FUNC void gen_le16(int c);
ST_FUNC void gen_le32(int c); ST_FUNC void gen_le32(int c);
#endif
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
ST_FUNC void gen_addr32(int r, Sym *sym, int c); ST_FUNC void gen_addr32(int r, Sym *sym, int c);
ST_FUNC void gen_addrpc32(int r, Sym *sym, int c); ST_FUNC void gen_addrpc32(int r, Sym *sym, int c);
ST_FUNC void gen_cvt_csti(int t); ST_FUNC void gen_cvt_csti(int t);
ST_FUNC void gen_increment_tcov (SValue *sv); ST_FUNC void gen_increment_tcov (SValue *sv);
#endif
@ -1626,47 +1495,8 @@ ST_FUNC void asm_clobber(uint8_t *clobber_regs, const char *str);
#define ST_ASM_SET 0x04 #define ST_ASM_SET 0x04
/* ------------ tcctools.c ----------------- */
#if 0 /* included in tcc.c */
ST_FUNC int tcc_tool_ar(TCCState *s, int argc, char **argv);
ST_FUNC int tcc_tool_cross(TCCState *s, char **argv, int option);
ST_FUNC int gen_makedeps(TCCState *s, const char *target, const char *filename);
#endif
/* ------------ tccdbg.c ------------ */ /* ------------ tccdbg.c ------------ */
ST_FUNC void tcc_debug_new(TCCState *s);
ST_FUNC void tcc_debug_start(TCCState *s1);
ST_FUNC void tcc_debug_end(TCCState *s1);
ST_FUNC void tcc_debug_bincl(TCCState *s1);
ST_FUNC void tcc_debug_eincl(TCCState *s1);
ST_FUNC void tcc_debug_newfile(TCCState *s1);
ST_FUNC void tcc_debug_line(TCCState *s1);
ST_FUNC void tcc_add_debug_info(TCCState *s1, int param, Sym *s, Sym *e);
ST_FUNC void tcc_debug_funcstart(TCCState *s1, Sym *sym);
ST_FUNC void tcc_debug_prolog_epilog(TCCState *s1, int value);
ST_FUNC void tcc_debug_funcend(TCCState *s1, int size);
ST_FUNC void tcc_debug_extern_sym(TCCState *s1, Sym *sym, int sh_num, int sym_bind, int sym_type);
ST_FUNC void tcc_debug_typedef(TCCState *s1, Sym *sym);
ST_FUNC void tcc_debug_stabn(TCCState *s1, int type, int value);
ST_FUNC void tcc_debug_fix_anon(TCCState *s1, CType *t);
#if !(defined ELF_OBJ_ONLY || defined TCC_TARGET_ARM || defined TARGETOS_BSD)
ST_FUNC void tcc_eh_frame_start(TCCState *s1);
ST_FUNC void tcc_eh_frame_end(TCCState *s1);
ST_FUNC void tcc_eh_frame_hdr(TCCState *s1, int final);
#define TCC_EH_FRAME 1
#endif
ST_FUNC void tcc_tcov_start(TCCState *s1);
ST_FUNC void tcc_tcov_end(TCCState *s1);
ST_FUNC void tcc_tcov_check_line(TCCState *s1, int start);
ST_FUNC void tcc_tcov_block_end(TCCState *s1, int line);
ST_FUNC void tcc_tcov_block_begin(TCCState *s1);
ST_FUNC void tcc_tcov_reset_ind(TCCState *s1);
#define stab_section s1->stab_section #define stab_section s1->stab_section
#define stabstr_section stab_section->link #define stabstr_section stab_section->link
#define tcov_section s1->tcov_section #define tcov_section s1->tcov_section
@ -1679,12 +1509,6 @@ ST_FUNC void tcc_tcov_reset_ind(TCCState *s1);
#define dwarf_str_section s1->dwarf_str_section #define dwarf_str_section s1->dwarf_str_section
#define dwarf_line_str_section s1->dwarf_line_str_section #define dwarf_line_str_section s1->dwarf_line_str_section
/* default dwarf version for "-gdwarf" */
#ifdef TCC_TARGET_MACHO
# define DEFAULT_DWARF_VERSION 2
#else
# define DEFAULT_DWARF_VERSION 5
#endif
/* default dwarf version for "-g". use 0 to emit stab debug infos */ /* default dwarf version for "-g". use 0 to emit stab debug infos */
#ifndef CONFIG_DWARF_VERSION #ifndef CONFIG_DWARF_VERSION
@ -1693,8 +1517,6 @@ ST_FUNC void tcc_tcov_reset_ind(TCCState *s1);
#if defined TCC_TARGET_PE #if defined TCC_TARGET_PE
# define R_DATA_32DW 'Z' /* fake code to avoid DLL relocs */ # define R_DATA_32DW 'Z' /* fake code to avoid DLL relocs */
#elif defined TCC_TARGET_X86_64
# define R_DATA_32DW R_X86_64_32
#else #else
# define R_DATA_32DW R_DATA_32 # define R_DATA_32DW R_DATA_32
#endif #endif

View file

@ -20,6 +20,7 @@
#define USING_GLOBALS #define USING_GLOBALS
#include "tcc.h" #include "tcc.h"
#include "utils/string.h"
#ifdef CONFIG_TCC_ASM #ifdef CONFIG_TCC_ASM
static Section *last_text_section; /* to handle .previous asm directive */ static Section *last_text_section; /* to handle .previous asm directive */
@ -958,7 +959,6 @@ static int tcc_assemble_internal(TCCState *s1, int do_preprocess, int global)
next(); next();
if (tok == TOK_EOF) if (tok == TOK_EOF)
break; break;
tcc_debug_line(s1);
parse_flags |= PARSE_FLAG_LINEFEED; /* XXX: suppress that hack */ parse_flags |= PARSE_FLAG_LINEFEED; /* XXX: suppress that hack */
redo: redo:
if (tok == '#') { if (tok == '#') {
@ -1009,14 +1009,12 @@ static int tcc_assemble_internal(TCCState *s1, int do_preprocess, int global)
ST_FUNC int tcc_assemble(TCCState *s1, int do_preprocess) ST_FUNC int tcc_assemble(TCCState *s1, int do_preprocess)
{ {
int ret; int ret;
tcc_debug_start(s1);
/* default section is text */ /* default section is text */
cur_text_section = text_section; cur_text_section = text_section;
ind = cur_text_section->data_offset; ind = cur_text_section->data_offset;
nocode_wanted = 0; nocode_wanted = 0;
ret = tcc_assemble_internal(s1, do_preprocess, 1); ret = tcc_assemble_internal(s1, do_preprocess, 1);
cur_text_section->data_offset = ind; cur_text_section->data_offset = ind;
tcc_debug_end(s1);
return ret; return ret;
} }

View file

@ -15,14 +15,29 @@ coff_load_lib(TCCState *s1, int fd)
return (0); return (0);
} }
static int
coff_merge_or_create(void)
{
return (0);
}
static int
coff_resolve_symbols(void)
{
return (0);
}
int int
coff_load_obj(TCCState *s1, int fd) coff_load_obj(TCCState *s1, int fd)
{ {
FILHDR hdr; FILHDR hdr;
SCNHDR *scns; SCNHDR *scns;
SYMENT *syments; SYMENT *syments;
RELOC *relocs;
Section *s;
uint16_t i; uint16_t i;
int32_t j; int32_t j;
int k;
char buff[9]; char buff[9];
if (!read_mem(fd, 0, &hdr, FILHSZ)) if (!read_mem(fd, 0, &hdr, FILHSZ))
@ -31,8 +46,6 @@ coff_load_obj(TCCState *s1, int fd)
if (hdr.f_magic != F_MACH_I386 || hdr.f_flags & F_EXEC) if (hdr.f_magic != F_MACH_I386 || hdr.f_flags & F_EXEC)
return (tcc_error_noabort("invalid coff object file")); return (tcc_error_noabort("invalid coff object file"));
/* load symtab */
/* read sections */ /* read sections */
scns = tcc_malloc(SCNHSZ * hdr.f_nscns); scns = tcc_malloc(SCNHSZ * hdr.f_nscns);
if (!read_mem(fd, FILHSZ, scns, SCNHSZ * hdr.f_nscns)) if (!read_mem(fd, FILHSZ, scns, SCNHSZ * hdr.f_nscns))
@ -46,6 +59,17 @@ coff_load_obj(TCCState *s1, int fd)
memset(buff, 0, 9); memset(buff, 0, 9);
memcpy(buff, scns[i].s_name, 8); memcpy(buff, scns[i].s_name, 8);
printf("sec: %s\n", buff); printf("sec: %s\n", buff);
for (k = 1; k < s1->nb_sections; k++)
{
if (strcmp(s1->sections[k]->name, buff) != 0)
{
continue;
}
}
} }
/* load symtab */ /* load symtab */
@ -54,7 +78,7 @@ coff_load_obj(TCCState *s1, int fd)
for (j = 0; j < hdr.f_nsyms; j++) for (j = 0; j < hdr.f_nsyms; j++)
{ {
memset(buff, 0, 9); memset(buff, 0, 9);
memcpy(buff, syments[i].n_name, 8); memcpy(buff, syments[j].n_name, 8);
printf("sym: %s\n", buff); printf("sym: %s\n", buff);
} }

951
libtcc/tcccoff.c_old.c Normal file
View file

@ -0,0 +1,951 @@
/*
* COFF file handling for TCC
*
* Copyright (c) 2003, 2004 TK
* Copyright (c) 2004 Fabrice Bellard
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "tcc.h"
/* XXX: this file uses tcc_error() to the effect of exit(1) */
#undef _tcc_error
#define MAXNSCNS 255 /* MAXIMUM NUMBER OF SECTIONS */
#define MAX_STR_TABLE 1000000
AOUTHDR o_filehdr; /* OPTIONAL (A.OUT) FILE HEADER */
SCNHDR section_header[MAXNSCNS];
#define MAX_FUNCS 1000
#define MAX_FUNC_NAME_LENGTH 128
int nFuncs;
char Func[MAX_FUNCS][MAX_FUNC_NAME_LENGTH];
char AssociatedFile[MAX_FUNCS][MAX_FUNC_NAME_LENGTH];
int LineNoFilePtr[MAX_FUNCS];
int EndAddress[MAX_FUNCS];
int LastLineNo[MAX_FUNCS];
int FuncEntries[MAX_FUNCS];
int OutputTheSection(Section * sect);
short int GetCoffFlags(const char *s);
void SortSymbolTable(TCCState *s1);
Section *FindSection(TCCState * s1, const char *sname);
int C67_main_entry_point;
int FindCoffSymbolIndex(TCCState * s1, const char *func_name);
int nb_syms;
typedef struct {
long tag;
long size;
long fileptr;
long nextsym;
short int dummy;
} AUXFUNC;
typedef struct {
long regmask;
unsigned short lineno;
unsigned short nentries;
int localframe;
int nextentry;
short int dummy;
} AUXBF;
typedef struct {
long dummy;
unsigned short lineno;
unsigned short dummy1;
int dummy2;
int dummy3;
unsigned short dummy4;
} AUXEF;
ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f)
{
Section *tcc_sect;
SCNHDR *coff_sec;
int file_pointer;
char *Coff_str_table, *pCoff_str_table;
int CoffTextSectionNo, coff_nb_syms;
FILHDR file_hdr; /* FILE HEADER STRUCTURE */
Section *stext, *sdata, *sbss;
int i, NSectionsToOutput = 0;
Coff_str_table = pCoff_str_table = NULL;
stext = FindSection(s1, ".text");
sdata = FindSection(s1, ".data");
sbss = FindSection(s1, ".bss");
nb_syms = symtab_section->data_offset / sizeof(Elf32_Sym);
coff_nb_syms = FindCoffSymbolIndex(s1, "XXXXXXXXXX1");
file_hdr.f_magic = COFF_C67_MAGIC; /* magic number */
file_hdr.f_timdat = 0; /* time & date stamp */
file_hdr.f_opthdr = sizeof(AOUTHDR); /* sizeof(optional hdr) */
file_hdr.f_flags = 0x1143; /* flags (copied from what code composer does) */
file_hdr.f_TargetID = 0x99; /* for C6x = 0x0099 */
o_filehdr.magic = 0x0108; /* see magic.h */
o_filehdr.vstamp = 0x0190; /* version stamp */
o_filehdr.tsize = stext->data_offset; /* text size in bytes, padded to FW bdry */
o_filehdr.dsize = sdata->data_offset; /* initialized data " " */
o_filehdr.bsize = sbss->data_offset; /* uninitialized data " " */
o_filehdr.entrypt = C67_main_entry_point; /* entry pt. */
o_filehdr.text_start = stext->sh_addr; /* base of text used for this file */
o_filehdr.data_start = sdata->sh_addr; /* base of data used for this file */
// create all the section headers
file_pointer = FILHSZ + sizeof(AOUTHDR);
CoffTextSectionNo = -1;
for (i = 1; i < s1->nb_sections; i++) {
coff_sec = &section_header[i];
tcc_sect = s1->sections[i];
if (OutputTheSection(tcc_sect)) {
NSectionsToOutput++;
if (CoffTextSectionNo == -1 && tcc_sect == stext)
CoffTextSectionNo = NSectionsToOutput; // rem which coff sect number the .text sect is
strcpy(coff_sec->s_name, tcc_sect->name); /* section name */
coff_sec->s_paddr = tcc_sect->sh_addr; /* physical address */
coff_sec->s_vaddr = tcc_sect->sh_addr; /* virtual address */
coff_sec->s_size = tcc_sect->data_offset; /* section size */
coff_sec->s_scnptr = 0; /* file ptr to raw data for section */
coff_sec->s_relptr = 0; /* file ptr to relocation */
coff_sec->s_lnnoptr = 0; /* file ptr to line numbers */
coff_sec->s_nreloc = 0; /* number of relocation entries */
coff_sec->s_flags = GetCoffFlags(coff_sec->s_name); /* flags */
coff_sec->s_reserved = 0; /* reserved byte */
coff_sec->s_page = 0; /* memory page id */
file_pointer += sizeof(SCNHDR);
}
}
file_hdr.f_nscns = NSectionsToOutput; /* number of sections */
// now loop through and determine file pointer locations
// for the raw data
for (i = 1; i < s1->nb_sections; i++) {
coff_sec = &section_header[i];
tcc_sect = s1->sections[i];
if (OutputTheSection(tcc_sect)) {
// put raw data
coff_sec->s_scnptr = file_pointer; /* file ptr to raw data for section */
file_pointer += coff_sec->s_size;
}
}
// now loop through and determine file pointer locations
// for the relocation data
for (i = 1; i < s1->nb_sections; i++) {
coff_sec = &section_header[i];
tcc_sect = s1->sections[i];
if (OutputTheSection(tcc_sect)) {
// put relocations data
if (coff_sec->s_nreloc > 0) {
coff_sec->s_relptr = file_pointer; /* file ptr to relocation */
file_pointer += coff_sec->s_nreloc * sizeof(struct reloc);
}
}
}
// now loop through and determine file pointer locations
// for the line number data
for (i = 1; i < s1->nb_sections; i++) {
coff_sec = &section_header[i];
tcc_sect = s1->sections[i];
coff_sec->s_nlnno = 0;
coff_sec->s_lnnoptr = 0;
if (s1->do_debug && tcc_sect == stext) {
// count how many line nos data
// also find association between source file name and function
// so we can sort the symbol table
Stab_Sym *sym, *sym_end;
char func_name[MAX_FUNC_NAME_LENGTH],
last_func_name[MAX_FUNC_NAME_LENGTH];
unsigned long func_addr, last_pc, pc;
const char *incl_files[INCLUDE_STACK_SIZE];
int incl_index, len, last_line_num;
const char *str, *p;
coff_sec->s_lnnoptr = file_pointer; /* file ptr to linno */
func_name[0] = '\0';
func_addr = 0;
incl_index = 0;
last_func_name[0] = '\0';
last_pc = 0xffffffff;
last_line_num = 1;
sym = (Stab_Sym *) stab_section->data + 1;
sym_end =
(Stab_Sym *) (stab_section->data +
stab_section->data_offset);
nFuncs = 0;
while (sym < sym_end) {
switch (sym->n_type) {
/* function start or end */
case N_FUN:
if (sym->n_strx == 0) {
// end of function
coff_sec->s_nlnno++;
file_pointer += LINESZ;
pc = sym->n_value + func_addr;
func_name[0] = '\0';
func_addr = 0;
EndAddress[nFuncs] = pc;
FuncEntries[nFuncs] =
(file_pointer -
LineNoFilePtr[nFuncs]) / LINESZ - 1;
LastLineNo[nFuncs++] = last_line_num + 1;
} else {
// beginning of function
LineNoFilePtr[nFuncs] = file_pointer;
coff_sec->s_nlnno++;
file_pointer += LINESZ;
str =
(const char *) stabstr_section->data +
sym->n_strx;
p = strchr(str, ':');
if (!p) {
pstrcpy(func_name, sizeof(func_name), str);
pstrcpy(Func[nFuncs], sizeof(func_name), str);
} else {
len = p - str;
if (len > sizeof(func_name) - 1)
len = sizeof(func_name) - 1;
memcpy(func_name, str, len);
memcpy(Func[nFuncs], str, len);
func_name[len] = '\0';
}
// save the file that it came in so we can sort later
pstrcpy(AssociatedFile[nFuncs], sizeof(func_name),
incl_files[incl_index - 1]);
func_addr = sym->n_value;
}
break;
/* line number info */
case N_SLINE:
pc = sym->n_value + func_addr;
last_pc = pc;
last_line_num = sym->n_desc;
/* XXX: slow! */
strcpy(last_func_name, func_name);
coff_sec->s_nlnno++;
file_pointer += LINESZ;
break;
/* include files */
case N_BINCL:
str =
(const char *) stabstr_section->data + sym->n_strx;
add_incl:
if (incl_index < INCLUDE_STACK_SIZE) {
incl_files[incl_index++] = str;
}
break;
case N_EINCL:
if (incl_index > 1)
incl_index--;
break;
case N_SO:
if (sym->n_strx == 0) {
incl_index = 0; /* end of translation unit */
} else {
str =
(const char *) stabstr_section->data +
sym->n_strx;
/* do not add path */
len = strlen(str);
if (len > 0 && str[len - 1] != '/')
goto add_incl;
}
break;
}
sym++;
}
}
}
file_hdr.f_symptr = file_pointer; /* file pointer to symtab */
if (s1->do_debug)
file_hdr.f_nsyms = coff_nb_syms; /* number of symtab entries */
else
file_hdr.f_nsyms = 0;
file_pointer += file_hdr.f_nsyms * SYMNMLEN;
// OK now we are all set to write the file
fwrite(&file_hdr, FILHSZ, 1, f);
fwrite(&o_filehdr, sizeof(o_filehdr), 1, f);
// write section headers
for (i = 1; i < s1->nb_sections; i++) {
coff_sec = &section_header[i];
tcc_sect = s1->sections[i];
if (OutputTheSection(tcc_sect)) {
fwrite(coff_sec, sizeof(SCNHDR), 1, f);
}
}
// write raw data
for (i = 1; i < s1->nb_sections; i++) {
coff_sec = &section_header[i];
tcc_sect = s1->sections[i];
if (OutputTheSection(tcc_sect)) {
fwrite(tcc_sect->data, tcc_sect->data_offset, 1, f);
}
}
// write relocation data
for (i = 1; i < s1->nb_sections; i++) {
coff_sec = &section_header[i];
tcc_sect = s1->sections[i];
if (OutputTheSection(tcc_sect)) {
// put relocations data
if (coff_sec->s_nreloc > 0) {
fwrite(tcc_sect->reloc,
coff_sec->s_nreloc * sizeof(struct reloc), 1, f);
}
}
}
// group the symbols in order of filename, func1, func2, etc
// finally global symbols
if (s1->do_debug)
SortSymbolTable(s1);
// write line no data
for (i = 1; i < s1->nb_sections; i++) {
coff_sec = &section_header[i];
tcc_sect = s1->sections[i];
if (s1->do_debug && tcc_sect == stext) {
// count how many line nos data
Stab_Sym *sym, *sym_end;
char func_name[128], last_func_name[128];
unsigned long func_addr, last_pc, pc;
const char *incl_files[INCLUDE_STACK_SIZE];
int incl_index, len, last_line_num;
const char *str, *p;
LINENO CoffLineNo;
func_name[0] = '\0';
func_addr = 0;
incl_index = 0;
last_func_name[0] = '\0';
last_pc = 0;
last_line_num = 1;
sym = (Stab_Sym *) stab_section->data + 1;
sym_end =
(Stab_Sym *) (stab_section->data +
stab_section->data_offset);
while (sym < sym_end) {
switch (sym->n_type) {
/* function start or end */
case N_FUN:
if (sym->n_strx == 0) {
// end of function
CoffLineNo.l_addr.l_paddr = last_pc;
CoffLineNo.l_lnno = last_line_num + 1;
fwrite(&CoffLineNo, 6, 1, f);
pc = sym->n_value + func_addr;
func_name[0] = '\0';
func_addr = 0;
} else {
// beginning of function
str =
(const char *) stabstr_section->data +
sym->n_strx;
p = strchr(str, ':');
if (!p) {
pstrcpy(func_name, sizeof(func_name), str);
} else {
len = p - str;
if (len > sizeof(func_name) - 1)
len = sizeof(func_name) - 1;
memcpy(func_name, str, len);
func_name[len] = '\0';
}
func_addr = sym->n_value;
last_pc = func_addr;
last_line_num = -1;
// output a function begin
CoffLineNo.l_addr.l_symndx =
FindCoffSymbolIndex(s1, func_name);
CoffLineNo.l_lnno = 0;
fwrite(&CoffLineNo, 6, 1, f);
}
break;
/* line number info */
case N_SLINE:
pc = sym->n_value + func_addr;
/* XXX: slow! */
strcpy(last_func_name, func_name);
// output a line reference
CoffLineNo.l_addr.l_paddr = last_pc;
if (last_line_num == -1) {
CoffLineNo.l_lnno = sym->n_desc;
} else {
CoffLineNo.l_lnno = last_line_num + 1;
}
fwrite(&CoffLineNo, 6, 1, f);
last_pc = pc;
last_line_num = sym->n_desc;
break;
/* include files */
case N_BINCL:
str =
(const char *) stabstr_section->data + sym->n_strx;
add_incl2:
if (incl_index < INCLUDE_STACK_SIZE) {
incl_files[incl_index++] = str;
}
break;
case N_EINCL:
if (incl_index > 1)
incl_index--;
break;
case N_SO:
if (sym->n_strx == 0) {
incl_index = 0; /* end of translation unit */
} else {
str =
(const char *) stabstr_section->data +
sym->n_strx;
/* do not add path */
len = strlen(str);
if (len > 0 && str[len - 1] != '/')
goto add_incl2;
}
break;
}
sym++;
}
}
}
// write symbol table
if (s1->do_debug) {
int k;
struct syment csym;
AUXFUNC auxfunc;
AUXBF auxbf;
AUXEF auxef;
int i;
Elf32_Sym *p;
const char *name;
int nstr;
int n = 0;
Coff_str_table = (char *) tcc_malloc(MAX_STR_TABLE);
pCoff_str_table = Coff_str_table;
nstr = 0;
p = (Elf32_Sym *) symtab_section->data;
for (i = 0; i < nb_syms; i++) {
name = symtab_section->link->data + p->st_name;
for (k = 0; k < 8; k++)
csym._n._n_name[k] = 0;
if (strlen(name) <= 8) {
strcpy(csym._n._n_name, name);
} else {
if (pCoff_str_table - Coff_str_table + strlen(name) >
MAX_STR_TABLE - 1)
tcc_error("String table too large");
csym._n._n_n._n_zeroes = 0;
csym._n._n_n._n_offset =
pCoff_str_table - Coff_str_table + 4;
strcpy(pCoff_str_table, name);
pCoff_str_table += strlen(name) + 1; // skip over null
nstr++;
}
if (p->st_info == 4) {
// put a filename symbol
csym.n_value = 33; // ?????
csym.n_scnum = N_DEBUG;
csym.n_type = 0;
csym.n_sclass = C_FILE;
csym.n_numaux = 0;
fwrite(&csym, 18, 1, f);
n++;
} else if (p->st_info == 0x12) {
// find the function data
for (k = 0; k < nFuncs; k++) {
if (strcmp(name, Func[k]) == 0)
break;
}
if (k >= nFuncs) {
tcc_error("debug info can't find function: %s", name);
}
// put a Function Name
csym.n_value = p->st_value; // physical address
csym.n_scnum = CoffTextSectionNo;
csym.n_type = MKTYPE(T_INT, DT_FCN, 0, 0, 0, 0, 0);
csym.n_sclass = C_EXT;
csym.n_numaux = 1;
fwrite(&csym, 18, 1, f);
// now put aux info
auxfunc.tag = 0;
auxfunc.size = EndAddress[k] - p->st_value;
auxfunc.fileptr = LineNoFilePtr[k];
auxfunc.nextsym = n + 6; // tktk
auxfunc.dummy = 0;
fwrite(&auxfunc, 18, 1, f);
// put a .bf
strcpy(csym._n._n_name, ".bf");
csym.n_value = p->st_value; // physical address
csym.n_scnum = CoffTextSectionNo;
csym.n_type = 0;
csym.n_sclass = C_FCN;
csym.n_numaux = 1;
fwrite(&csym, 18, 1, f);
// now put aux info
auxbf.regmask = 0;
auxbf.lineno = 0;
auxbf.nentries = FuncEntries[k];
auxbf.localframe = 0;
auxbf.nextentry = n + 6;
auxbf.dummy = 0;
fwrite(&auxbf, 18, 1, f);
// put a .ef
strcpy(csym._n._n_name, ".ef");
csym.n_value = EndAddress[k]; // physical address
csym.n_scnum = CoffTextSectionNo;
csym.n_type = 0;
csym.n_sclass = C_FCN;
csym.n_numaux = 1;
fwrite(&csym, 18, 1, f);
// now put aux info
auxef.dummy = 0;
auxef.lineno = LastLineNo[k];
auxef.dummy1 = 0;
auxef.dummy2 = 0;
auxef.dummy3 = 0;
auxef.dummy4 = 0;
fwrite(&auxef, 18, 1, f);
n += 6;
} else {
// try an put some type info
if ((p->st_other & VT_BTYPE) == VT_DOUBLE) {
csym.n_type = T_DOUBLE; // int
csym.n_sclass = C_EXT;
} else if ((p->st_other & VT_BTYPE) == VT_FLOAT) {
csym.n_type = T_FLOAT;
csym.n_sclass = C_EXT;
} else if ((p->st_other & VT_BTYPE) == VT_INT) {
csym.n_type = T_INT; // int
csym.n_sclass = C_EXT;
} else if ((p->st_other & VT_BTYPE) == VT_SHORT) {
csym.n_type = T_SHORT;
csym.n_sclass = C_EXT;
} else if ((p->st_other & VT_BTYPE) == VT_BYTE) {
csym.n_type = T_CHAR;
csym.n_sclass = C_EXT;
} else {
csym.n_type = T_INT; // just mark as a label
csym.n_sclass = C_LABEL;
}
csym.n_value = p->st_value;
csym.n_scnum = 2;
csym.n_numaux = 1;
fwrite(&csym, 18, 1, f);
auxfunc.tag = 0;
auxfunc.size = 0x20;
auxfunc.fileptr = 0;
auxfunc.nextsym = 0;
auxfunc.dummy = 0;
fwrite(&auxfunc, 18, 1, f);
n++;
n++;
}
p++;
}
}
if (s1->do_debug) {
// write string table
// first write the size
i = pCoff_str_table - Coff_str_table;
fwrite(&i, 4, 1, f);
// then write the strings
fwrite(Coff_str_table, i, 1, f);
tcc_free(Coff_str_table);
}
return 0;
}
// group the symbols in order of filename, func1, func2, etc
// finally global symbols
void SortSymbolTable(TCCState *s1)
{
int i, j, k, n = 0;
Elf32_Sym *p, *p2, *NewTable;
char *name, *name2;
NewTable = (Elf32_Sym *) tcc_malloc(nb_syms * sizeof(Elf32_Sym));
p = (Elf32_Sym *) symtab_section->data;
// find a file symbol, copy it over
// then scan the whole symbol list and copy any function
// symbols that match the file association
for (i = 0; i < nb_syms; i++) {
if (p->st_info == 4) {
name = (char *) symtab_section->link->data + p->st_name;
// this is a file symbol, copy it over
NewTable[n++] = *p;
p2 = (Elf32_Sym *) symtab_section->data;
for (j = 0; j < nb_syms; j++) {
if (p2->st_info == 0x12) {
// this is a func symbol
name2 =
(char *) symtab_section->link->data + p2->st_name;
// find the function data index
for (k = 0; k < nFuncs; k++) {
if (strcmp(name2, Func[k]) == 0)
break;
}
if (k >= nFuncs) {
tcc_error("debug (sort) info can't find function: %s", name2);
}
if (strcmp(AssociatedFile[k], name) == 0) {
// yes they match copy it over
NewTable[n++] = *p2;
}
}
p2++;
}
}
p++;
}
// now all the filename and func symbols should have been copied over
// copy all the rest over (all except file and funcs)
p = (Elf32_Sym *) symtab_section->data;
for (i = 0; i < nb_syms; i++) {
if (p->st_info != 4 && p->st_info != 0x12) {
NewTable[n++] = *p;
}
p++;
}
if (n != nb_syms)
tcc_error("Internal Compiler error, debug info");
// copy it all back
p = (Elf32_Sym *) symtab_section->data;
for (i = 0; i < nb_syms; i++) {
*p++ = NewTable[i];
}
tcc_free(NewTable);
}
int FindCoffSymbolIndex(TCCState *s1, const char *func_name)
{
int i, n = 0;
Elf32_Sym *p;
char *name;
p = (Elf32_Sym *) symtab_section->data;
for (i = 0; i < nb_syms; i++) {
name = (char *) symtab_section->link->data + p->st_name;
if (p->st_info == 4) {
// put a filename symbol
n++;
} else if (p->st_info == 0x12) {
if (strcmp(func_name, name) == 0)
return n;
n += 6;
// put a Function Name
// now put aux info
// put a .bf
// now put aux info
// put a .ef
// now put aux info
} else {
n += 2;
}
p++;
}
return n; // total number of symbols
}
int OutputTheSection(Section * sect)
{
const char *s = sect->name;
if (!strcmp(s, ".text"))
return 1;
else if (!strcmp(s, ".data"))
return 1;
else
return 0;
}
short int GetCoffFlags(const char *s)
{
if (!strcmp(s, ".text"))
return STYP_TEXT | STYP_DATA | STYP_ALIGN | 0x400;
else if (!strcmp(s, ".data"))
return STYP_DATA;
else if (!strcmp(s, ".bss"))
return STYP_BSS;
else if (!strcmp(s, ".stack"))
return STYP_BSS | STYP_ALIGN | 0x200;
else if (!strcmp(s, ".cinit"))
return STYP_COPY | STYP_DATA | STYP_ALIGN | 0x200;
else
return 0;
}
Section *FindSection(TCCState * s1, const char *sname)
{
Section *s;
int i;
for (i = 1; i < s1->nb_sections; i++) {
s = s1->sections[i];
if (!strcmp(sname, s->name))
return s;
}
tcc_error("could not find section %s", sname);
return 0;
}
ST_FUNC int tcc_load_coff(TCCState * s1, int fd)
{
// tktk TokenSym *ts;
FILE *f;
unsigned int str_size;
char *Coff_str_table, *name;
int i, k;
struct syment csym;
char name2[9];
FILHDR file_hdr; /* FILE HEADER STRUCTURE */
f = fdopen(fd, "rb");
if (!f) {
tcc_error("Unable to open .out file for input");
}
if (fread(&file_hdr, FILHSZ, 1, f) != 1)
tcc_error("error reading .out file for input");
if (fread(&o_filehdr, sizeof(o_filehdr), 1, f) != 1)
tcc_error("error reading .out file for input");
// first read the string table
if (fseek(f, file_hdr.f_symptr + file_hdr.f_nsyms * SYMESZ, SEEK_SET))
tcc_error("error reading .out file for input");
if (fread(&str_size, sizeof(int), 1, f) != 1)
tcc_error("error reading .out file for input");
Coff_str_table = (char *) tcc_malloc(str_size);
if (fread(Coff_str_table, str_size - 4, 1, f) != 1)
tcc_error("error reading .out file for input");
// read/process all the symbols
// seek back to symbols
if (fseek(f, file_hdr.f_symptr, SEEK_SET))
tcc_error("error reading .out file for input");
for (i = 0; i < file_hdr.f_nsyms; i++) {
if (fread(&csym, SYMESZ, 1, f) != 1)
tcc_error("error reading .out file for input");
if (csym._n._n_n._n_zeroes == 0) {
name = Coff_str_table + csym._n._n_n._n_offset - 4;
} else {
name = csym._n._n_name;
if (name[7] != 0) {
for (k = 0; k < 8; k++)
name2[k] = name[k];
name2[8] = 0;
name = name2;
}
}
// if (strcmp("_DAC_Buffer",name)==0) // tktk
// name[0]=0;
if (((csym.n_type & 0x30) == 0x20 && csym.n_sclass == 0x2) || ((csym.n_type & 0x30) == 0x30 && csym.n_sclass == 0x2) || (csym.n_type == 0x4 && csym.n_sclass == 0x2) || (csym.n_type == 0x8 && csym.n_sclass == 0x2) || // structures
(csym.n_type == 0x18 && csym.n_sclass == 0x2) || // pointer to structure
(csym.n_type == 0x7 && csym.n_sclass == 0x2) || // doubles
(csym.n_type == 0x6 && csym.n_sclass == 0x2)) // floats
{
// strip off any leading underscore (except for other main routine)
if (name[0] == '_' && strcmp(name, "_main") != 0)
name++;
tcc_add_symbol(s1, name, (void*)(uintptr_t)csym.n_value);
}
// skip any aux records
if (csym.n_numaux == 1) {
if (fread(&csym, SYMESZ, 1, f) != 1)
tcc_error("error reading .out file for input");
i++;
}
}
return 0;
}

View file

@ -19,6 +19,7 @@
*/ */
#include "tcc.h" #include "tcc.h"
#include "utils/string.h"
/* Define this to get some debug output during relocation processing. */ /* Define this to get some debug output during relocation processing. */
#undef DEBUG_RELOC #undef DEBUG_RELOC
@ -84,26 +85,6 @@ ST_FUNC void tccelf_new(TCCState *s)
".dynhashtab", SHF_PRIVATE); ".dynhashtab", SHF_PRIVATE);
get_sym_attr(s, 0, 1); get_sym_attr(s, 0, 1);
if (s->do_debug) {
/* add debug sections */
tcc_debug_new(s);
}
#if TCC_EH_FRAME
if (s->output_format != TCC_OUTPUT_FORMAT_ELF)
s->unwind_tables = 0;
tcc_eh_frame_start(s);
#endif
#ifdef CONFIG_TCC_BCHECK
if (s->do_bounds_check) {
/* if bound checking, then add corresponding sections */
/* (make ro after relocation done with GNU_RELRO) */
bounds_section = new_section(s, ".bounds", SHT_PROGBITS, shf_RELRO);
lbounds_section = new_section(s, ".lbounds", SHT_PROGBITS, shf_RELRO);
}
#endif
#ifdef TCC_TARGET_PE #ifdef TCC_TARGET_PE
/* to make sure that -ltcc1 -Wl,-e,_start will grab the startup code /* to make sure that -ltcc1 -Wl,-e,_start will grab the startup code
from libtcc1.a (unless _start defined) */ from libtcc1.a (unless _start defined) */
@ -158,10 +139,6 @@ ST_FUNC void tccelf_begin_file(TCCState *s1)
} }
/* disable symbol hashing during compilation */ /* disable symbol hashing during compilation */
s = s1->symtab, s->reloc = s->hash, s->hash = NULL; s = s1->symtab, s->reloc = s->hash, s->hash = NULL;
#if defined TCC_TARGET_X86_64 && defined TCC_TARGET_PE
s1->uw_sym = 0;
s1->uw_offs = 0;
#endif
} }
static void update_relocs(TCCState *s1, Section *s, int *old_to_new_syms, int first_sym); static void update_relocs(TCCState *s1, Section *s, int *old_to_new_syms, int first_sym);
@ -520,7 +497,7 @@ ST_FUNC addr_t get_sym_addr(TCCState *s1, const char *name, int err, int forc)
} }
/* return elf symbol value */ /* return elf symbol value */
LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name) void *tcc_get_symbol(TCCState *s, const char *name)
{ {
addr_t addr = get_sym_addr(s, name, 0, 1); addr_t addr = get_sym_addr(s, name, 0, 1);
return addr == -1 ? NULL : (void*)(uintptr_t)addr; return addr == -1 ? NULL : (void*)(uintptr_t)addr;
@ -551,7 +528,7 @@ ST_FUNC void list_elf_symbols(TCCState *s, void *ctx,
} }
/* list elf symbol names and values */ /* list elf symbol names and values */
LIBTCCAPI void tcc_list_symbols(TCCState *s, void *ctx, void tcc_list_symbols(TCCState *s, void *ctx,
void (*symbol_cb)(void *ctx, const char *name, const void *val)) void (*symbol_cb)(void *ctx, const char *name, const void *val))
{ {
list_elf_symbols(s, ctx, symbol_cb); list_elf_symbols(s, ctx, symbol_cb);
@ -1056,25 +1033,6 @@ ST_FUNC void relocate_syms(TCCState *s1, Section *symtab, int do_resolve)
name = (char *) s1->symtab->link->data + sym->st_name; name = (char *) s1->symtab->link->data + sym->st_name;
/* Use ld.so to resolve symbol for us (for tcc -run) */ /* Use ld.so to resolve symbol for us (for tcc -run) */
if (do_resolve) { if (do_resolve) {
#if defined TCC_IS_NATIVE && !defined TCC_TARGET_PE
/* dlsym() needs the undecorated name. */
void *addr = dlsym(RTLD_DEFAULT, &name[s1->leading_underscore]);
#if TARGETOS_OpenBSD || TARGETOS_FreeBSD || TARGETOS_NetBSD || TARGETOS_ANDROID
if (addr == NULL) {
int i;
for (i = 0; i < s1->nb_loaded_dlls; i++)
if ((addr = dlsym(s1->loaded_dlls[i]->handle, name)))
break;
}
#endif
if (addr) {
sym->st_value = (addr_t) addr;
#ifdef DEBUG_RELOC
printf ("relocate_sym: %s -> 0x%lx\n", name, sym->st_value);
#endif
goto found;
}
#endif
/* if dynamic symbol exist, it will be used in relocate_section */ /* 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))
goto found; goto found;
@ -1107,7 +1065,6 @@ static void relocate_section(TCCState *s1, Section *s, Section *sr)
int type, sym_index; int type, sym_index;
unsigned char *ptr; unsigned char *ptr;
addr_t tgt, addr; addr_t tgt, addr;
int is_dwarf = s->sh_num >= s1->dwlo && s->sh_num < s1->dwhi;
qrel = (ElfW_Rel *)sr->data; qrel = (ElfW_Rel *)sr->data;
for_each_elem(sr, 0, rel, ElfW_Rel) { for_each_elem(sr, 0, rel, ElfW_Rel) {
@ -1119,12 +1076,6 @@ static void relocate_section(TCCState *s1, Section *s, Section *sr)
#if SHT_RELX == SHT_RELA #if SHT_RELX == SHT_RELA
tgt += rel->r_addend; tgt += rel->r_addend;
#endif #endif
if (is_dwarf && type == R_DATA_32DW
&& sym->st_shndx >= s1->dwlo && sym->st_shndx < s1->dwhi) {
/* dwarf section relocation to each other */
add32le(ptr, tgt - s1->sections[sym->st_shndx]->sh_addr);
continue;
}
addr = s->sh_addr + rel->r_offset; addr = s->sh_addr + rel->r_offset;
relocate(s1, rel, type, ptr, addr, tgt); relocate(s1, rel, type, ptr, addr, tgt);
} }
@ -1132,17 +1083,6 @@ static void relocate_section(TCCState *s1, Section *s, Section *sr)
/* if the relocation is allocated, we change its symbol table */ /* if the relocation is allocated, we change its symbol table */
if (sr->sh_flags & SHF_ALLOC) { if (sr->sh_flags & SHF_ALLOC) {
sr->link = s1->dynsym; sr->link = s1->dynsym;
if (s1->output_type & TCC_OUTPUT_DYN) {
size_t r = (uint8_t*)qrel - sr->data;
if (sizeof ((Stab_Sym*)0)->n_value < PTR_SIZE
&& 0 == strcmp(s->name, ".stab"))
r = 0; /* cannot apply 64bit relocation to 32bit value */
sr->data_offset = sr->sh_size = r;
#ifdef CONFIG_TCC_PIE
if (r && (s->sh_flags & SHF_EXECINSTR))
tcc_warning("%d relocations to %s", (unsigned)(r / sizeof *qrel), s->name);
#endif
}
} }
#endif #endif
} }
@ -1158,11 +1098,9 @@ ST_FUNC void relocate_sections(TCCState *s1)
if (sr->sh_type != SHT_RELX) if (sr->sh_type != SHT_RELX)
continue; continue;
s = s1->sections[sr->sh_info]; s = s1->sections[sr->sh_info];
#ifndef TCC_TARGET_MACHO
if (s != s1->got if (s != s1->got
|| s1->static_link || s1->static_link
|| s1->output_type == TCC_OUTPUT_MEMORY) || s1->output_type == TCC_OUTPUT_MEMORY)
#endif
{ {
relocate_section(s1, s, sr); relocate_section(s1, s, sr);
} }
@ -1183,15 +1121,13 @@ ST_FUNC void relocate_sections(TCCState *s1)
static int prepare_dynamic_rel(TCCState *s1, Section *sr) static int prepare_dynamic_rel(TCCState *s1, Section *sr)
{ {
int count = 0; int count = 0;
#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64) || \
defined(TCC_TARGET_ARM) || defined(TCC_TARGET_ARM64) || \
defined(TCC_TARGET_RISCV64)
ElfW_Rel *rel; ElfW_Rel *rel;
for_each_elem(sr, 0, rel, ElfW_Rel) { for_each_elem(sr, 0, rel, ElfW_Rel) {
int sym_index = ELFW(R_SYM)(rel->r_info); int sym_index = ELFW(R_SYM)(rel->r_info);
int type = ELFW(R_TYPE)(rel->r_info); int type = ELFW(R_TYPE)(rel->r_info);
switch(type) { switch(type) {
#if defined(TCC_TARGET_I386)
case R_386_32: case R_386_32:
if (!get_sym_attr(s1, sym_index, 0)->dyn_index if (!get_sym_attr(s1, sym_index, 0)->dyn_index
&& ((ElfW(Sym)*)symtab_section->data + sym_index)->st_shndx == SHN_UNDEF) { && ((ElfW(Sym)*)symtab_section->data + sym_index)->st_shndx == SHN_UNDEF) {
@ -1199,42 +1135,9 @@ static int prepare_dynamic_rel(TCCState *s1, Section *sr)
rel->r_info = ELFW(R_INFO)(sym_index, R_386_RELATIVE); rel->r_info = ELFW(R_INFO)(sym_index, R_386_RELATIVE);
break; break;
} }
#elif defined(TCC_TARGET_X86_64)
case R_X86_64_32:
case R_X86_64_32S:
case R_X86_64_64:
#elif defined(TCC_TARGET_ARM)
case R_ARM_ABS32:
case R_ARM_TARGET1:
#elif defined(TCC_TARGET_ARM64)
case R_AARCH64_ABS32:
case R_AARCH64_ABS64:
#elif defined(TCC_TARGET_RISCV64)
case R_RISCV_32:
case R_RISCV_64:
#endif
count++; count++;
break; break;
#if defined(TCC_TARGET_I386)
case R_386_PC32: case R_386_PC32:
#elif defined(TCC_TARGET_X86_64)
case R_X86_64_PC32:
{
ElfW(Sym) *sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
/* Hidden defined symbols can and must be resolved locally.
We're misusing a PLT32 reloc for this, as that's always
resolved to its address even in shared libs. */
if (sym->st_shndx != SHN_UNDEF &&
ELFW(ST_VISIBILITY)(sym->st_other) == STV_HIDDEN) {
rel->r_info = ELFW(R_INFO)(sym_index, R_X86_64_PLT32);
break;
}
}
#elif defined(TCC_TARGET_ARM64)
case R_AARCH64_PREL32:
#endif
if (s1->output_type != TCC_OUTPUT_DLL)
break;
if (get_sym_attr(s1, sym_index, 0)->dyn_index) if (get_sym_attr(s1, sym_index, 0)->dyn_index)
count++; count++;
break; break;
@ -1242,7 +1145,7 @@ static int prepare_dynamic_rel(TCCState *s1, Section *sr)
break; break;
} }
} }
#endif
return count; return count;
} }
#endif #endif
@ -1399,9 +1302,7 @@ redo:
if (sym->st_shndx == SHN_UNDEF) { if (sym->st_shndx == SHN_UNDEF) {
ElfW(Sym) *esym; ElfW(Sym) *esym;
int dynindex; int dynindex;
if (!PCRELATIVE_DLLPLT
&& (s1->output_type & TCC_OUTPUT_DYN))
continue;
/* Relocations for UNDEF symbols would normally need /* Relocations for UNDEF symbols would normally need
to be transferred into the executable or shared object. to be transferred into the executable or shared object.
If that were done AUTO_GOTPLT_ENTRY wouldn't exist. If that were done AUTO_GOTPLT_ENTRY wouldn't exist.
@ -1425,28 +1326,14 @@ redo:
} else if (sym->st_shndx == SHN_ABS) { } else if (sym->st_shndx == SHN_ABS) {
if (sym->st_value == 0) /* from tcc_add_btstub() */ if (sym->st_value == 0) /* from tcc_add_btstub() */
continue; continue;
#ifndef TCC_TARGET_ARM
if (PTR_SIZE != 8) if (PTR_SIZE != 8)
continue; continue;
#endif
/* from tcc_add_symbol(): on 64 bit platforms these /* from tcc_add_symbol(): on 64 bit platforms these
need to go through .got */ need to go through .got */
} else } else
continue; continue;
} }
#ifdef TCC_TARGET_X86_64
if ((type == R_X86_64_PLT32 || type == R_X86_64_PC32) &&
sym->st_shndx != SHN_UNDEF &&
(ELFW(ST_VISIBILITY)(sym->st_other) != STV_DEFAULT ||
ELFW(ST_BIND)(sym->st_info) == STB_LOCAL ||
s1->output_type & TCC_OUTPUT_EXE)) {
if (pass != 0)
continue;
rel->r_info = ELFW(R_INFO)(sym_index, R_X86_64_PC32);
continue;
}
#endif
reloc_type = code_reloc(type); reloc_type = code_reloc(type);
if (reloc_type == -1) { if (reloc_type == -1) {
tcc_error_noabort ("Unknown relocation type: %d", type); tcc_error_noabort ("Unknown relocation type: %d", type);
@ -1523,15 +1410,6 @@ ST_FUNC void add_array (TCCState *s1, const char *sec, int c)
section_ptr_add(s, PTR_SIZE); section_ptr_add(s, PTR_SIZE);
} }
#ifdef CONFIG_TCC_BCHECK
ST_FUNC void tcc_add_bcheck(TCCState *s1)
{
if (0 == s1->do_bounds_check)
return;
section_ptr_add(bounds_section, sizeof(addr_t));
}
#endif
/* set symbol to STB_LOCAL and resolve. The point is to not export it as /* set symbol to STB_LOCAL and resolve. The point is to not export it as
a dynamic symbol to allow so's to have one each with a different value. */ a dynamic symbol to allow so's to have one each with a different value. */
static void set_local_sym(TCCState *s1, const char *name, Section *s, int offset) static void set_local_sym(TCCState *s1, const char *name, Section *s, int offset)
@ -1548,209 +1426,23 @@ static void set_local_sym(TCCState *s1, const char *name, Section *s, int offset
/* avoid generating debug/test_coverage code for stub functions */ /* avoid generating debug/test_coverage code for stub functions */
static void tcc_compile_string_no_debug(TCCState *s, const char *str) static void tcc_compile_string_no_debug(TCCState *s, const char *str)
{ {
int save_do_debug = s->do_debug;
int save_test_coverage = s->test_coverage;
s->do_debug = 0;
s->test_coverage = 0;
tcc_compile_string(s, str); tcc_compile_string(s, str);
s->do_debug = save_do_debug;
s->test_coverage = save_test_coverage;
} }
#ifdef CONFIG_TCC_BACKTRACE
static void put_ptr(TCCState *s1, Section *s, int offs)
{
int c;
c = set_global_sym(s1, NULL, s, offs);
s = data_section;
put_elf_reloc (s1->symtab, s, s->data_offset, R_DATA_PTR, c);
section_ptr_add(s, PTR_SIZE);
}
ST_FUNC void tcc_add_btstub(TCCState *s1) #if !defined TCC_TARGET_PE
{
Section *s;
int n, o, *p;
CString cstr;
const char *__rt_info = &"___rt_info"[!s1->leading_underscore];
s = data_section;
/* Align to PTR_SIZE */
section_ptr_add(s, -s->data_offset & (PTR_SIZE - 1));
o = s->data_offset;
/* create a struct rt_context (see tccrun.c) */
if (s1->dwarf) {
put_ptr(s1, dwarf_line_section, 0);
put_ptr(s1, dwarf_line_section, -1);
if (s1->dwarf >= 5)
put_ptr(s1, dwarf_line_str_section, 0);
else
put_ptr(s1, dwarf_str_section, 0);
}
else
{
put_ptr(s1, stab_section, 0);
put_ptr(s1, stab_section, -1);
put_ptr(s1, stab_section->link, 0);
}
/* skip esym_start/esym_end/elf_str (not loaded) */
section_ptr_add(s, 3 * PTR_SIZE);
if (s1->output_type == TCC_OUTPUT_MEMORY && 0 == s1->dwarf) {
put_ptr(s1, text_section, 0);
} else {
/* prog_base : local nameless symbol with offset 0 at SHN_ABS */
put_ptr(s1, NULL, 0);
#if defined TCC_TARGET_MACHO
/* adjust for __PAGEZERO */
if (s1->dwarf == 0 && s1->output_type == TCC_OUTPUT_EXE)
write64le(data_section->data + data_section->data_offset - PTR_SIZE,
(uint64_t)1 << 32);
#endif
}
n = 3 * PTR_SIZE;
#ifdef CONFIG_TCC_BCHECK
if (s1->do_bounds_check) {
put_ptr(s1, bounds_section, 0);
n -= PTR_SIZE;
}
#endif
section_ptr_add(s, n);
p = section_ptr_add(s, 2 * sizeof (int));
p[0] = s1->rt_num_callers;
p[1] = s1->dwarf;
// if (s->data_offset - o != 10*PTR_SIZE + 2*sizeof (int)) exit(99);
if (s1->output_type == TCC_OUTPUT_MEMORY) {
set_global_sym(s1, __rt_info, s, o);
return;
}
cstr_new(&cstr);
cstr_printf(&cstr,
"extern void __bt_init(),__bt_exit(),__bt_init_dll();"
"static void *__rt_info[];"
"__attribute__((constructor)) static void __bt_init_rt(){");
#ifdef TCC_TARGET_PE
if (s1->output_type == TCC_OUTPUT_DLL)
#ifdef CONFIG_TCC_BCHECK
cstr_printf(&cstr, "__bt_init_dll(%d);", s1->do_bounds_check);
#else
cstr_printf(&cstr, "__bt_init_dll(0);");
#endif
#endif
cstr_printf(&cstr, "__bt_init(__rt_info,%d);}",
s1->output_type != TCC_OUTPUT_DLL);
/* In case dlcose is called by application */
cstr_printf(&cstr,
"__attribute__((destructor)) static void __bt_exit_rt(){"
"__bt_exit(__rt_info);}");
tcc_compile_string_no_debug(s1, cstr.data);
cstr_free(&cstr);
set_local_sym(s1, __rt_info, s, o);
}
#endif /* def CONFIG_TCC_BACKTRACE */
static void tcc_tcov_add_file(TCCState *s1, const char *filename)
{
CString cstr;
void *ptr;
char wd[1024];
if (tcov_section == NULL)
return;
section_ptr_add(tcov_section, 1);
write32le (tcov_section->data, tcov_section->data_offset);
cstr_new (&cstr);
if (filename[0] == '/')
cstr_printf (&cstr, "%s.tcov", filename);
else {
getcwd (wd, sizeof(wd));
cstr_printf (&cstr, "%s/%s.tcov", wd, filename);
}
ptr = section_ptr_add(tcov_section, cstr.size + 1);
strcpy((char *)ptr, cstr.data);
unlink((char *)ptr);
#ifdef _WIN32
normalize_slashes((char *)ptr);
#endif
cstr_free (&cstr);
cstr_new(&cstr);
cstr_printf(&cstr,
"extern char *__tcov_data[];"
"extern void __store_test_coverage ();"
"__attribute__((destructor)) static void __tcov_exit() {"
"__store_test_coverage(__tcov_data);"
"}");
tcc_compile_string_no_debug(s1, cstr.data);
cstr_free(&cstr);
set_local_sym(s1, &"___tcov_data"[!s1->leading_underscore], tcov_section, 0);
}
#if !defined TCC_TARGET_PE && !defined TCC_TARGET_MACHO
/* add libc crt1/crti objects */ /* add libc crt1/crti objects */
ST_FUNC void tccelf_add_crtbegin(TCCState *s1) ST_FUNC void tccelf_add_crtbegin(TCCState *s1)
{ {
#if TARGETOS_OpenBSD tcc_add_crt(s1, "crt1.o");
if (s1->output_type != TCC_OUTPUT_DLL)
tcc_add_crt(s1, "crt0.o");
if (s1->output_type == TCC_OUTPUT_DLL)
tcc_add_crt(s1, "crtbeginS.o");
else
tcc_add_crt(s1, "crtbegin.o");
#elif TARGETOS_FreeBSD || TARGETOS_NetBSD
if (s1->output_type != TCC_OUTPUT_DLL)
#if TARGETOS_FreeBSD
tcc_add_crt(s1, "crt1.o");
#else
tcc_add_crt(s1, "crt0.o");
#endif
tcc_add_crt(s1, "crti.o"); tcc_add_crt(s1, "crti.o");
if (s1->static_link)
tcc_add_crt(s1, "crtbeginT.o");
else if (s1->output_type == TCC_OUTPUT_DLL)
tcc_add_crt(s1, "crtbeginS.o");
else
tcc_add_crt(s1, "crtbegin.o");
#elif TARGETOS_ANDROID
if (s1->output_type == TCC_OUTPUT_DLL)
tcc_add_crt(s1, "crtbegin_so.o");
else
tcc_add_crt(s1, "crtbegin_dynamic.o");
#else
if (s1->output_type != TCC_OUTPUT_DLL)
tcc_add_crt(s1, "crt1.o");
tcc_add_crt(s1, "crti.o");
#endif
} }
ST_FUNC void tccelf_add_crtend(TCCState *s1) ST_FUNC void tccelf_add_crtend(TCCState *s1)
{ {
#if TARGETOS_OpenBSD
if (s1->output_type == TCC_OUTPUT_DLL)
tcc_add_crt(s1, "crtendS.o");
else
tcc_add_crt(s1, "crtend.o");
#elif TARGETOS_FreeBSD || TARGETOS_NetBSD
if (s1->output_type == TCC_OUTPUT_DLL)
tcc_add_crt(s1, "crtendS.o");
else
tcc_add_crt(s1, "crtend.o");
tcc_add_crt(s1, "crtn.o"); tcc_add_crt(s1, "crtn.o");
#elif TARGETOS_ANDROID
if (s1->output_type == TCC_OUTPUT_DLL)
tcc_add_crt(s1, "crtend_so.o");
else
tcc_add_crt(s1, "crtend_android.o");
#else
tcc_add_crt(s1, "crtn.o");
#endif
} }
#endif /* !defined TCC_TARGET_PE && !defined TCC_TARGET_MACHO */ #endif /* !defined TCC_TARGET_PE */
#ifndef TCC_TARGET_PE #ifndef TCC_TARGET_PE
/* add tcc runtime libraries */ /* add tcc runtime libraries */
@ -1758,34 +1450,12 @@ ST_FUNC void tcc_add_runtime(TCCState *s1)
{ {
s1->filetype = 0; s1->filetype = 0;
#ifdef CONFIG_TCC_BCHECK
tcc_add_bcheck(s1);
#endif
tcc_add_pragma_libs(s1); tcc_add_pragma_libs(s1);
/* add libc */ /* add libc */
if (!s1->nostdlib) { if (!s1->nostdlib) {
int lpthread = s1->option_pthread; int lpthread = s1->option_pthread;
#ifdef CONFIG_TCC_BCHECK
if (s1->do_bounds_check && s1->output_type != TCC_OUTPUT_DLL) {
tcc_add_support(s1, "bcheck.o");
# if !(TARGETOS_OpenBSD || TARGETOS_NetBSD)
tcc_add_library(s1, "dl");
# endif
lpthread = 1;
}
#endif
#ifdef CONFIG_TCC_BACKTRACE
if (s1->do_backtrace) {
if (s1->output_type & TCC_OUTPUT_EXE)
tcc_add_support(s1, "bt-exe.o");
if (s1->output_type != TCC_OUTPUT_DLL)
tcc_add_support(s1, "bt-log.o");
tcc_add_btstub(s1);
lpthread = 1;
}
#endif
if (lpthread) if (lpthread)
tcc_add_library(s1, "pthread"); tcc_add_library(s1, "pthread");
tcc_add_library(s1, "c"); tcc_add_library(s1, "c");
@ -1797,15 +1467,11 @@ ST_FUNC void tcc_add_runtime(TCCState *s1)
tcc_add_dll(s1, TCC_LIBGCC, AFF_PRINT_ERROR); tcc_add_dll(s1, TCC_LIBGCC, AFF_PRINT_ERROR);
} }
#endif #endif
#if defined TCC_TARGET_ARM && TARGETOS_FreeBSD
tcc_add_library(s1, "gcc_s"); // unwind code
#endif
if (TCC_LIBTCC1[0]) if (TCC_LIBTCC1[0])
tcc_add_support(s1, TCC_LIBTCC1); tcc_add_support(s1, TCC_LIBTCC1);
#ifndef TCC_TARGET_MACHO
if (s1->output_type != TCC_OUTPUT_MEMORY) if (s1->output_type != TCC_OUTPUT_MEMORY)
tccelf_add_crtend(s1); tccelf_add_crtend(s1);
#endif
} }
} }
#endif /* ndef TCC_TARGET_PE */ #endif /* ndef TCC_TARGET_PE */
@ -1822,13 +1488,7 @@ static void tcc_add_linker_symbols(TCCState *s1)
set_global_sym(s1, "_etext", text_section, -1); set_global_sym(s1, "_etext", text_section, -1);
set_global_sym(s1, "_edata", data_section, -1); set_global_sym(s1, "_edata", data_section, -1);
set_global_sym(s1, "_end", bss_section, -1); set_global_sym(s1, "_end", bss_section, -1);
#if TARGETOS_OpenBSD
set_global_sym(s1, "__executable_start", NULL, ELF_START_ADDR);
#endif
#ifdef TCC_TARGET_RISCV64
/* XXX should be .sdata+0x800, not .data+0x800 */
set_global_sym(s1, "__global_pointer$", data_section, 0x800);
#endif
/* horrible new standard ldscript defines */ /* horrible new standard ldscript defines */
add_init_array_defines(s1, ".preinit_array"); add_init_array_defines(s1, ".preinit_array");
add_init_array_defines(s1, ".init_array"); add_init_array_defines(s1, ".init_array");
@ -2097,33 +1757,10 @@ static int set_sec_sizes(TCCState *s1)
if (s->sh_type == SHT_RELX && !(s->sh_flags & SHF_ALLOC)) { if (s->sh_type == SHT_RELX && !(s->sh_flags & SHF_ALLOC)) {
/* when generating a DLL, we include relocations but /* when generating a DLL, we include relocations but
we may patch them */ we may patch them */
if ((file_type & TCC_OUTPUT_DYN) } else if ((s->sh_flags & SHF_ALLOC)) {
&& (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)) {
int count = prepare_dynamic_rel(s1, s);
if (count) {
/* allocate the section */
s->sh_flags |= SHF_ALLOC;
s->sh_size = count * sizeof(ElfW_Rel);
if (s1->sections[s->sh_info]->sh_flags & SHF_EXECINSTR)
textrel += count;
}
}
} else if ((s->sh_flags & SHF_ALLOC)
#ifdef TCC_TARGET_ARM
|| s->sh_type == SHT_ARM_ATTRIBUTES
#endif
|| s1->do_debug) {
s->sh_size = s->data_offset; s->sh_size = s->data_offset;
} }
#ifdef TCC_TARGET_ARM
/* XXX: Suppress stack unwinding section. */
if (s->sh_type == SHT_ARM_EXIDX) {
s->sh_flags = 0;
s->sh_size = 0;
}
#endif
} }
return textrel; return textrel;
} }
@ -2313,8 +1950,6 @@ static int layout_sections(TCCState *s1, int *sec_order, struct dyn_inf *d)
s_align = s1->section_align; s_align = s1->section_align;
addr = ELF_START_ADDR; addr = ELF_START_ADDR;
if (s1->output_type & TCC_OUTPUT_DYN)
addr = 0;
if (s1->has_text_addr) { if (s1->has_text_addr) {
addr = s1->text_addr; addr = s1->text_addr;
@ -2509,8 +2144,6 @@ static void fill_dynamic(TCCState *s1, struct dyn_inf *dyninf)
if (s && s->data_offset) { if (s && s->data_offset) {
put_dt(dynamic, DT_FINI, s->sh_addr); put_dt(dynamic, DT_FINI, s->sh_addr);
} }
if (s1->do_debug)
put_dt(dynamic, DT_DEBUG, 0);
put_dt(dynamic, DT_NULL, 0); put_dt(dynamic, DT_NULL, 0);
} }
@ -2574,26 +2207,10 @@ static int tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr)
ehdr.e_ident[5] = ELFDATA2LSB; ehdr.e_ident[5] = ELFDATA2LSB;
ehdr.e_ident[6] = EV_CURRENT; ehdr.e_ident[6] = EV_CURRENT;
#if TARGETOS_FreeBSD || TARGETOS_FreeBSD_kernel
ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
#elif defined TCC_TARGET_ARM && defined TCC_ARM_EABI
ehdr.e_flags = EF_ARM_EABI_VER5;
ehdr.e_flags |= s1->float_abi == ARM_HARD_FLOAT
? EF_ARM_VFP_FLOAT : EF_ARM_SOFT_FLOAT;
#elif defined TCC_TARGET_ARM
ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
#elif defined TCC_TARGET_RISCV64
/* XXX should be configurable */
ehdr.e_flags = EF_RISCV_FLOAT_ABI_DOUBLE;
#endif
if (file_type == TCC_OUTPUT_OBJ) { if (file_type == TCC_OUTPUT_OBJ) {
ehdr.e_type = ET_REL; ehdr.e_type = ET_REL;
} else { } else {
if (file_type & TCC_OUTPUT_DYN) ehdr.e_type = ET_EXEC;
ehdr.e_type = ET_DYN;
else
ehdr.e_type = ET_EXEC;
if (s1->elf_entryname) if (s1->elf_entryname)
ehdr.e_entry = get_sym_addr(s1, s1->elf_entryname, 1, 0); ehdr.e_entry = get_sym_addr(s1, s1->elf_entryname, 1, 0);
else else
@ -2752,63 +2369,6 @@ static void reorder_sections(TCCState *s1, int *sec_order)
tcc_free(backmap); tcc_free(backmap);
} }
#ifdef TCC_TARGET_ARM
static void create_arm_attribute_section(TCCState *s1)
{
// Needed for DLL support.
static const unsigned char arm_attr[] = {
0x41, // 'A'
0x2c, 0x00, 0x00, 0x00, // size 0x2c
'a', 'e', 'a', 'b', 'i', 0x00, // "aeabi"
0x01, 0x22, 0x00, 0x00, 0x00, // 'File Attributes', size 0x22
0x05, 0x36, 0x00, // 'CPU_name', "6"
0x06, 0x06, // 'CPU_arch', 'v6'
0x08, 0x01, // 'ARM_ISA_use', 'Yes'
0x09, 0x01, // 'THUMB_ISA_use', 'Thumb-1'
0x0a, 0x02, // 'FP_arch', 'VFPv2'
0x12, 0x04, // 'ABI_PCS_wchar_t', 4
0x14, 0x01, // 'ABI_FP_denormal', 'Needed'
0x15, 0x01, // 'ABI_FP_exceptions', 'Needed'
0x17, 0x03, // 'ABI_FP_number_model', 'IEEE 754'
0x18, 0x01, // 'ABI_align_needed', '8-byte'
0x19, 0x01, // 'ABI_align_preserved', '8-byte, except leaf SP'
0x1a, 0x02, // 'ABI_enum_size', 'int'
0x1c, 0x01, // 'ABI_VFP_args', 'VFP registers'
0x22, 0x01 // 'CPU_unaligned_access', 'v6'
};
Section *attr = new_section(s1, ".ARM.attributes", SHT_ARM_ATTRIBUTES, 0);
unsigned char *ptr = section_ptr_add(attr, sizeof(arm_attr));
attr->sh_addralign = 1;
memcpy(ptr, arm_attr, sizeof(arm_attr));
if (s1->float_abi != ARM_HARD_FLOAT) {
ptr[26] = 0x00; // 'FP_arch', 'No'
ptr[41] = 0x1e; // 'ABI_optimization_goals'
ptr[42] = 0x06; // 'Aggressive Debug'
}
}
#endif
#if TARGETOS_OpenBSD || TARGETOS_NetBSD
static Section *create_bsd_note_section(TCCState *s1,
const char *name,
const char *value)
{
Section *s = find_section (s1, name);
if (s->data_offset == 0) {
char *ptr = section_ptr_add(s, sizeof(ElfW(Nhdr)) + 8 + 4);
ElfW(Nhdr) *note = (ElfW(Nhdr) *) ptr;
s->sh_type = SHT_NOTE;
note->n_namesz = 8;
note->n_descsz = 4;
note->n_type = ELF_NOTE_OS_GNU;
strcpy (ptr + sizeof(ElfW(Nhdr)), value);
}
return s;
}
#endif
static void alloc_sec_names(TCCState *s1, int is_obj); static void alloc_sec_names(TCCState *s1, int is_obj);
/* Output an elf, coff or binary file */ /* Output an elf, coff or binary file */
@ -2827,21 +2387,6 @@ static int elf_output_file(TCCState *s1, const char *filename)
sec_order = NULL; sec_order = NULL;
dyninf.roinf = &dyninf._roinf; dyninf.roinf = &dyninf._roinf;
#ifdef TCC_TARGET_ARM
create_arm_attribute_section (s1);
#endif
#if TARGETOS_OpenBSD
dyninf.note = create_bsd_note_section (s1, ".note.openbsd.ident", "OpenBSD");
#endif
#if TARGETOS_NetBSD
dyninf.note = create_bsd_note_section (s1, ".note.netbsd.ident", "NetBSD");
#endif
#if TARGETOS_FreeBSD || TARGETOS_NetBSD
dyninf.roinf = NULL;
#endif
/* if linking, also link in runtime libraries (libc, libgcc, etc.) */ /* if linking, also link in runtime libraries (libc, libgcc, etc.) */
tcc_add_runtime(s1); tcc_add_runtime(s1);
resolve_common_syms(s1); resolve_common_syms(s1);
@ -2876,7 +2421,6 @@ static int elf_output_file(TCCState *s1, const char *filename)
got_sym = build_got(s1); got_sym = build_got(s1);
if (file_type & TCC_OUTPUT_EXE) { if (file_type & TCC_OUTPUT_EXE) {
bind_exe_dynsyms(s1, file_type & TCC_OUTPUT_DYN);
if (s1->nb_errors) if (s1->nb_errors)
goto the_end; goto the_end;
} }
@ -2887,10 +2431,6 @@ static int elf_output_file(TCCState *s1, const char *filename)
/* shared library case: simply export all global symbols */ /* shared library case: simply export all global symbols */
export_global_syms(s1); export_global_syms(s1);
} }
#if TCC_EH_FRAME
/* fill with initial data */
tcc_eh_frame_hdr(s1, 0);
#endif
dyninf.gnu_hash = create_gnu_hash(s1); dyninf.gnu_hash = create_gnu_hash(s1);
} else { } else {
build_got_entries(s1, 0); build_got_entries(s1, 0);
@ -2912,16 +2452,6 @@ static int elf_output_file(TCCState *s1, const char *filename)
put_elf_str(dynstr, s1->rpath)); put_elf_str(dynstr, s1->rpath));
dt_flags_1 = DF_1_NOW; dt_flags_1 = DF_1_NOW;
if (file_type & TCC_OUTPUT_DYN) {
if (s1->soname)
put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
/* XXX: currently, since we do not handle PIC code, we
must relocate the readonly segments */
if (textrel)
put_dt(dynamic, DT_TEXTREL, 0);
if (file_type & TCC_OUTPUT_EXE)
dt_flags_1 = DF_1_NOW | DF_1_PIE;
}
put_dt(dynamic, DT_FLAGS, DF_BIND_NOW); put_dt(dynamic, DT_FLAGS, DF_BIND_NOW);
put_dt(dynamic, DT_FLAGS_1, dt_flags_1); put_dt(dynamic, DT_FLAGS_1, dt_flags_1);
if (s1->symbolic) if (s1->symbolic)
@ -2946,8 +2476,7 @@ static int elf_output_file(TCCState *s1, const char *filename)
if (dynamic) { if (dynamic) {
/* put in GOT the dynamic section address and relocate PLT */ /* put in GOT the dynamic section address and relocate PLT */
write32le(s1->got->data, dynamic->sh_addr); write32le(s1->got->data, dynamic->sh_addr);
if (file_type == TCC_OUTPUT_EXE if (file_type == TCC_OUTPUT_EXE)
|| (RELOCATE_DLLPLT && (file_type & TCC_OUTPUT_DYN)))
relocate_plt(s1); relocate_plt(s1);
/* relocate symbols in .dynsym now that final addresses are known */ /* relocate symbols in .dynsym now that final addresses are known */
relocate_syms(s1, s1->dynsym, 2); relocate_syms(s1, s1->dynsym, 2);
@ -2974,10 +2503,7 @@ static int elf_output_file(TCCState *s1, const char *filename)
update_gnu_hash(s1, dyninf.gnu_hash); update_gnu_hash(s1, dyninf.gnu_hash);
reorder_sections(s1, sec_order); reorder_sections(s1, sec_order);
#if TCC_EH_FRAME
/* fill with final data */
tcc_eh_frame_hdr(s1, 1);
#endif
/* Create the ELF file with name 'filename' */ /* Create the ELF file with name 'filename' */
ret = tcc_write_elf_file(s1, filename, dyninf.phnum, dyninf.phdr); ret = tcc_write_elf_file(s1, filename, dyninf.phnum, dyninf.phdr);
the_end: the_end:
@ -3027,16 +2553,12 @@ static int elf_output_obj(TCCState *s1, const char *filename)
return ret; return ret;
} }
LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename) int tcc_output_file(TCCState *s, const char *filename)
{ {
if (s->test_coverage)
tcc_tcov_add_file(s, filename);
if (s->output_type == TCC_OUTPUT_OBJ) if (s->output_type == TCC_OUTPUT_OBJ)
return elf_output_obj(s, filename); return elf_output_obj(s, filename);
#ifdef TCC_TARGET_PE #ifdef TCC_TARGET_PE
return pe_output_file(s, filename); return pe_output_file(s, filename);
#elif defined TCC_TARGET_MACHO
return macho_output_file(s, filename);
#else #else
return elf_output_file(s, filename); return elf_output_file(s, filename);
#endif #endif
@ -3082,10 +2604,8 @@ ST_FUNC int tcc_object_type(int fd, ElfW(Ehdr) *h)
} else if (size >= 8) { } else if (size >= 8) {
if (0 == memcmp(h, ARMAG, 8)) if (0 == memcmp(h, ARMAG, 8))
return AFF_BINTYPE_AR; return AFF_BINTYPE_AR;
#ifdef TCC_TARGET_COFF else if (((FILHDR *)h)->f_magic == F_MACH_I386)
if (((struct filehdr*)h)->f_magic == COFF_C67_MAGIC) return (AFF_BINTYPE_COFF);
return AFF_BINTYPE_C67;
#endif
} }
return 0; return 0;
} }
@ -3167,7 +2687,7 @@ invalid:
sh_name = strsec + sh->sh_name; sh_name = strsec + sh->sh_name;
if (0 == strncmp(sh_name, ".debug_", 7) if (0 == strncmp(sh_name, ".debug_", 7)
|| 0 == strncmp(sh_name, ".stab", 5)) { || 0 == strncmp(sh_name, ".stab", 5)) {
if (!s1->do_debug || seencompressed) if (seencompressed)
continue; continue;
} else } else
if (sh->sh_type != SHT_PROGBITS && if (sh->sh_type != SHT_PROGBITS &&
@ -3202,12 +2722,6 @@ invalid:
sm_table[i].link_once = 1; sm_table[i].link_once = 1;
goto next; goto next;
} }
if (stab_section) {
if (s == stab_section)
stab_index = i;
if (s == stab_section->link)
stabstr_index = i;
}
goto found; goto found;
} }
/* not found: create new section */ /* not found: create new section */
@ -3335,12 +2849,6 @@ invalid:
sym_index = old_to_new_syms[sym_index]; sym_index = old_to_new_syms[sym_index];
/* ignore link_once in rel section. */ /* ignore link_once in rel section. */
if (!sym_index && !sm_table[sh->sh_info].link_once if (!sym_index && !sm_table[sh->sh_info].link_once
#ifdef TCC_TARGET_ARM
&& type != R_ARM_V4BX
#elif defined TCC_TARGET_RISCV64
&& type != R_RISCV_ALIGN
&& type != R_RISCV_RELAX
#endif
) { ) {
invalid_reloc: invalid_reloc:
tcc_error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x", tcc_error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
@ -3350,18 +2858,6 @@ invalid:
rel->r_info = ELFW(R_INFO)(sym_index, type); rel->r_info = ELFW(R_INFO)(sym_index, type);
/* offset the relocation offset */ /* offset the relocation offset */
rel->r_offset += offseti; rel->r_offset += offseti;
#ifdef TCC_TARGET_ARM
/* Jumps and branches from a Thumb code to a PLT entry need
special handling since PLT entries are ARM code.
Unconditional bl instructions referencing PLT entries are
handled by converting these instructions into blx
instructions. Other case of instructions referencing a PLT
entry require to add a Thumb stub before the PLT entry to
switch to ARM mode. We set bit plt_thumb_stub of the
attribute of a symbol to indicate such a case. */
if (type == R_ARM_THM_JUMP24)
get_sym_attr(s1, sym_index, 1)->plt_thumb_stub = 1;
#endif
} }
break; break;
default: default:

View file

@ -20,6 +20,7 @@
#define USING_GLOBALS #define USING_GLOBALS
#include "tcc.h" #include "tcc.h"
#include "utils/string.h"
/********************************************************/ /********************************************************/
/* global variables */ /* global variables */
@ -43,7 +44,6 @@ static int nb_sym_pools;
static Sym *all_cleanups, *pending_gotos; static Sym *all_cleanups, *pending_gotos;
static int local_scope; static int local_scope;
ST_DATA char debug_modes;
ST_DATA SValue *vtop; ST_DATA SValue *vtop;
static SValue _vstack[1 + VSTACK_SIZE]; static SValue _vstack[1 + VSTACK_SIZE];
@ -176,8 +176,6 @@ static int gind()
{ {
int t = ind; int t = ind;
CODE_ON(); CODE_ON();
if (debug_modes)
tcc_tcov_block_begin(tcc_state);
return t; return t;
} }
@ -233,13 +231,6 @@ static int R_RET(int t)
{ {
if (!is_float(t)) if (!is_float(t))
return REG_IRET; return REG_IRET;
#ifdef TCC_TARGET_X86_64
if ((t & VT_BTYPE) == VT_LDOUBLE)
return TREG_ST0;
#elif defined TCC_TARGET_RISCV64
if ((t & VT_BTYPE) == VT_LDOUBLE)
return REG_IRET;
#endif
return REG_FRET; return REG_FRET;
} }
@ -250,14 +241,6 @@ static int R2_RET(int t)
#if PTR_SIZE == 4 #if PTR_SIZE == 4
if (t == VT_LLONG) if (t == VT_LLONG)
return REG_IRE2; return REG_IRE2;
#elif defined TCC_TARGET_X86_64
if (t == VT_QLONG)
return REG_IRE2;
if (t == VT_QFLOAT)
return REG_FRE2;
#elif defined TCC_TARGET_RISCV64
if (t == VT_LDOUBLE)
return REG_IRE2;
#endif #endif
return VT_CONST; return VT_CONST;
} }
@ -282,15 +265,6 @@ static int RC_TYPE(int t)
{ {
if (!is_float(t)) if (!is_float(t))
return RC_INT; return RC_INT;
#ifdef TCC_TARGET_X86_64
if ((t & VT_BTYPE) == VT_LDOUBLE)
return RC_ST0;
if ((t & VT_BTYPE) == VT_QFLOAT)
return RC_FRET;
#elif defined TCC_TARGET_RISCV64
if ((t & VT_BTYPE) == VT_LDOUBLE)
return RC_INT;
#endif
return RC_FLOAT; return RC_FLOAT;
} }
@ -323,10 +297,7 @@ ST_FUNC int ieee_finite(double d)
} }
/* compiling intel long double natively */ /* compiling intel long double natively */
#if (defined __i386__ || defined __x86_64__) \
&& (defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64)
# define TCC_IS_NATIVE_387 # define TCC_IS_NATIVE_387
#endif
ST_FUNC void test_lvalue(void) ST_FUNC void test_lvalue(void)
{ {
@ -386,13 +357,7 @@ ST_FUNC int tccgen_compile(TCCState *s1)
func_ind = -1; func_ind = -1;
anon_sym = SYM_FIRST_ANOM; anon_sym = SYM_FIRST_ANOM;
nocode_wanted = DATA_ONLY_WANTED; /* no code outside of functions */ nocode_wanted = DATA_ONLY_WANTED; /* no code outside of functions */
debug_modes = (s1->do_debug ? 1 : 0) | s1->test_coverage << 1;
tcc_debug_start(s1);
tcc_tcov_start (s1);
#ifdef TCC_TARGET_ARM
arm_init(s1);
#endif
#ifdef INC_DEBUG #ifdef INC_DEBUG
printf("%s: **** new file\n", file->filename); printf("%s: **** new file\n", file->filename);
#endif #endif
@ -402,17 +367,12 @@ ST_FUNC int tccgen_compile(TCCState *s1)
gen_inline_functions(s1); gen_inline_functions(s1);
check_vstack(); check_vstack();
/* end of translation unit info */ /* end of translation unit info */
#if TCC_EH_FRAME
tcc_eh_frame_end(s1);
#endif
tcc_debug_end(s1);
tcc_tcov_end(s1);
return 0; return 0;
} }
ST_FUNC void tccgen_finish(TCCState *s1) ST_FUNC void tccgen_finish(TCCState *s1)
{ {
tcc_debug_end(s1); /* just in case of errors: free memory */
free_inline_functions(s1); free_inline_functions(s1);
sym_pop(&global_stack, NULL, 0); sym_pop(&global_stack, NULL, 0);
sym_pop(&local_stack, NULL, 0); sym_pop(&local_stack, NULL, 0);
@ -546,9 +506,6 @@ ST_FUNC void put_extern_sym2(Sym *sym, int sh_num,
info = ELFW(ST_INFO)(sym_bind, sym_type); info = ELFW(ST_INFO)(sym_bind, sym_type);
sym->c = put_elf_sym(symtab_section, value, size, info, other, sh_num, name); sym->c = put_elf_sym(symtab_section, value, size, info, other, sh_num, name);
if (debug_modes)
tcc_debug_extern_sym(tcc_state, sym, sh_num, sym_bind, sym_type);
} else { } else {
esym = elfsym(sym); esym = elfsym(sym);
esym->st_value = value; esym->st_value = value;
@ -882,13 +839,10 @@ ST_FUNC void vpop(void)
{ {
int v; int v;
v = vtop->r & VT_VALMASK; v = vtop->r & VT_VALMASK;
#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
/* for x86, we need to pop the FP stack */ /* for x86, we need to pop the FP stack */
if (v == TREG_ST0) { if (v == TREG_ST0) {
o(0xd8dd); /* fstp %st(0) */ o(0xd8dd); /* fstp %st(0) */
} else } else if (v == VT_CMP) {
#endif
if (v == VT_CMP) {
/* need to put correct jump if && or || without test */ /* need to put correct jump if && or || without test */
gsym(vtop->jtrue); gsym(vtop->jtrue);
gsym(vtop->jfalse); gsym(vtop->jfalse);
@ -1375,12 +1329,10 @@ ST_FUNC void save_reg_upstack(int r, int n)
sv.r = VT_LOCAL | VT_LVAL; sv.r = VT_LOCAL | VT_LVAL;
sv.c.i = l; sv.c.i = l;
store(p->r & VT_VALMASK, &sv); store(p->r & VT_VALMASK, &sv);
#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
/* x86 specific: need to pop fp register ST0 if saved */ /* x86 specific: need to pop fp register ST0 if saved */
if (r == TREG_ST0) { if (r == TREG_ST0) {
o(0xd8dd); /* fstp %st(0) */ o(0xd8dd); /* fstp %st(0) */
} }
#endif
/* special long long case */ /* special long long case */
if (p->r2 < VT_CONST && USING_TWO_WORDS(bt)) { if (p->r2 < VT_CONST && USING_TWO_WORDS(bt)) {
sv.c.i += PTR_SIZE; sv.c.i += PTR_SIZE;
@ -1404,31 +1356,6 @@ ST_FUNC void save_reg_upstack(int r, int n)
} }
} }
#ifdef TCC_TARGET_ARM
/* find a register of class 'rc2' with at most one reference on stack.
* If none, call get_reg(rc) */
ST_FUNC int get_reg_ex(int rc, int rc2)
{
int r;
SValue *p;
for(r=0;r<NB_REGS;r++) {
if (reg_classes[r] & rc2) {
int n;
n=0;
for(p = vstack; p <= vtop; p++) {
if ((p->r & VT_VALMASK) == r ||
p->r2 == r)
n++;
}
if (n <= 1)
return r;
}
}
return get_reg(rc);
}
#endif
/* find a free register of class 'rc'. If none, save one register */ /* find a free register of class 'rc'. If none, save one register */
ST_FUNC int get_reg(int rc) ST_FUNC int get_reg(int rc)
{ {
@ -1536,155 +1463,9 @@ ST_FUNC void gaddrof(void)
vtop->r = (vtop->r & ~VT_VALMASK) | VT_LOCAL | VT_LVAL; vtop->r = (vtop->r & ~VT_VALMASK) | VT_LOCAL | VT_LVAL;
} }
#ifdef CONFIG_TCC_BCHECK
/* generate a bounded pointer addition */
static void gen_bounded_ptr_add(void)
{
int save = (vtop[-1].r & VT_VALMASK) == VT_LOCAL;
if (save) {
vpushv(&vtop[-1]);
vrott(3);
}
vpush_helper_func(TOK___bound_ptr_add);
vrott(3);
gfunc_call(2);
vtop -= save;
vpushi(0);
/* returned pointer is in REG_IRET */
vtop->r = REG_IRET | VT_BOUNDED;
if (nocode_wanted)
return;
/* relocation offset of the bounding function call point */
vtop->c.i = (cur_text_section->reloc->data_offset - sizeof(ElfW_Rel));
}
/* patch pointer addition in vtop so that pointer dereferencing is
also tested */
static void gen_bounded_ptr_deref(void)
{
addr_t func;
int size, align;
ElfW_Rel *rel;
Sym *sym;
if (nocode_wanted)
return;
size = type_size(&vtop->type, &align);
switch(size) {
case 1: func = TOK___bound_ptr_indir1; break;
case 2: func = TOK___bound_ptr_indir2; break;
case 4: func = TOK___bound_ptr_indir4; break;
case 8: func = TOK___bound_ptr_indir8; break;
case 12: func = TOK___bound_ptr_indir12; break;
case 16: func = TOK___bound_ptr_indir16; break;
default:
/* may happen with struct member access */
return;
}
sym = external_helper_sym(func);
if (!sym->c)
put_extern_sym(sym, NULL, 0, 0);
/* patch relocation */
/* XXX: find a better solution ? */
rel = (ElfW_Rel *)(cur_text_section->reloc->data + vtop->c.i);
rel->r_info = ELFW(R_INFO)(sym->c, ELFW(R_TYPE)(rel->r_info));
}
/* generate lvalue bound code */
static void gbound(void)
{
CType type1;
vtop->r &= ~VT_MUSTBOUND;
/* if lvalue, then use checking code before dereferencing */
if (vtop->r & VT_LVAL) {
/* if not VT_BOUNDED value, then make one */
if (!(vtop->r & VT_BOUNDED)) {
/* must save type because we must set it to int to get pointer */
type1 = vtop->type;
vtop->type.t = VT_PTR;
gaddrof();
vpushi(0);
gen_bounded_ptr_add();
vtop->r |= VT_LVAL;
vtop->type = type1;
}
/* then check for dereferencing */
gen_bounded_ptr_deref();
}
}
/* we need to call __bound_ptr_add before we start to load function
args into registers */
ST_FUNC void gbound_args(int nb_args)
{
int i, v;
SValue *sv;
for (i = 1; i <= nb_args; ++i)
if (vtop[1 - i].r & VT_MUSTBOUND) {
vrotb(i);
gbound();
vrott(i);
}
sv = vtop - nb_args;
if (sv->r & VT_SYM) {
v = sv->sym->v;
if (v == TOK_setjmp
|| v == TOK__setjmp
#ifndef TCC_TARGET_PE
|| v == TOK_sigsetjmp
|| v == TOK___sigsetjmp
#endif
) {
vpush_helper_func(TOK___bound_setjmp);
vpushv(sv + 1);
gfunc_call(1);
func_bound_add_epilog = 1;
}
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
if (v == TOK_alloca)
func_bound_add_epilog = 1;
#endif
#if TARGETOS_NetBSD
if (v == TOK_longjmp) /* undo rename to __longjmp14 */
sv->sym->asm_label = TOK___bound_longjmp;
#endif
}
}
/* Add bounds for local symbols from S to E (via ->prev) */
static void add_local_bounds(Sym *s, Sym *e)
{
for (; s != e; s = s->prev) {
if (!s->v || (s->r & VT_VALMASK) != VT_LOCAL)
continue;
/* Add arrays/structs/unions because we always take address */
if ((s->type.t & VT_ARRAY)
|| (s->type.t & VT_BTYPE) == VT_STRUCT
|| s->a.addrtaken) {
/* add local bound info */
int align, size = type_size(&s->type, &align);
addr_t *bounds_ptr = section_ptr_add(lbounds_section,
2 * sizeof(addr_t));
bounds_ptr[0] = s->c;
bounds_ptr[1] = size;
}
}
}
#endif
/* Wrapper around sym_pop, that potentially also registers local bounds. */ /* Wrapper around sym_pop, that potentially also registers local bounds. */
static void pop_local_syms(Sym *b, int keep) static void pop_local_syms(Sym *b, int keep)
{ {
#ifdef CONFIG_TCC_BCHECK
if (tcc_state->do_bounds_check && !keep && (local_scope || !func_var))
add_local_bounds(local_stack, b);
#endif
if (debug_modes)
tcc_add_debug_info (tcc_state, !local_scope, local_stack, b);
sym_pop(&local_stack, b, keep); sym_pop(&local_stack, b, keep);
} }
@ -1846,18 +1627,9 @@ ST_FUNC int gv(int rc)
init_putv(&p, &vtop->type, offset); init_putv(&p, &vtop->type, offset);
vtop->r |= VT_LVAL; vtop->r |= VT_LVAL;
} }
#ifdef CONFIG_TCC_BCHECK
if (vtop->r & VT_MUSTBOUND)
gbound();
#endif
bt = vtop->type.t & VT_BTYPE; bt = vtop->type.t & VT_BTYPE;
#ifdef TCC_TARGET_RISCV64
/* XXX mega hack */
if (bt == VT_LDOUBLE && rc == RC_FLOAT)
rc = RC_INT;
#endif
rc2 = RC2_TYPE(bt, rc); rc2 = RC2_TYPE(bt, rc);
/* need to reload if: /* need to reload if:
@ -1932,11 +1704,6 @@ ST_FUNC int gv(int rc)
} }
} }
vtop->r = r; vtop->r = r;
#ifdef TCC_TARGET_C67
/* uses register pairs for doubles */
if (bt == VT_DOUBLE)
vtop->r2 = r+1;
#endif
} }
return r; return r;
} }
@ -2066,10 +1833,6 @@ static void gen_opl(int op)
case TOK_UMOD: case TOK_UMOD:
func = TOK___umoddi3; func = TOK___umoddi3;
gen_mod_func: gen_mod_func:
#ifdef TCC_ARM_EABI
reg_iret = TREG_R2;
reg_lret = TREG_R3;
#endif
gen_func: gen_func:
/* call generic long long function */ /* call generic long long function */
vpush_helper_func(func); vpush_helper_func(func);
@ -2445,38 +2208,8 @@ static void gen_opic(int op)
} }
} }
#if defined TCC_TARGET_X86_64 || defined TCC_TARGET_I386 #define gen_negf gen_opf
# define gen_negf gen_opf
#elif defined TCC_TARGET_ARM
void gen_negf(int op)
{
/* arm will detect 0-x and replace by vneg */
vpushi(0), vswap(), gen_op('-');
}
#else
/* XXX: implement in gen_opf() for other backends too */
void gen_negf(int op)
{
/* In IEEE negate(x) isn't subtract(0,x). Without NaNs it's
subtract(-0, x), but with them it's really a sign flip
operation. We implement this with bit manipulation and have
to do some type reinterpretation for this, which TCC can do
only via memory. */
int align, size, bt;
size = type_size(&vtop->type, &align);
bt = vtop->type.t & VT_BTYPE;
save_reg(gv(RC_TYPE(bt)));
vdup();
incr_bf_adr(size - 1);
vdup();
vpushi(0x80); /* flip sign */
gen_op('^');
vstore();
vpop();
}
#endif
/* generate a floating point operation with constant propagation */ /* generate a floating point operation with constant propagation */
static void gen_opif(int op) static void gen_opif(int op)
@ -3037,21 +2770,7 @@ op_err:
type1 = vtop[-1].type; type1 = vtop[-1].type;
vpush_type_size(pointed_type(&vtop[-1].type), &align); vpush_type_size(pointed_type(&vtop[-1].type), &align);
gen_op('*'); gen_op('*');
#ifdef CONFIG_TCC_BCHECK gen_opic(op);
if (tcc_state->do_bounds_check && !CONST_WANTED) {
/* if bounded pointers, we generate a special code to
test bounds */
if (op == '-') {
vpushi(0);
vswap();
gen_op('-');
}
gen_bounded_ptr_add();
} else
#endif
{
gen_opic(op);
}
type1.t &= ~(VT_ARRAY|VT_VLA); type1.t &= ~(VT_ARRAY|VT_VLA);
/* put again type if gen_opic() swaped operands */ /* put again type if gen_opic() swaped operands */
vtop->type = type1; vtop->type = type1;
@ -3107,9 +2826,6 @@ op_err:
gv(is_float(vtop->type.t & VT_BTYPE) ? RC_FLOAT : RC_INT); gv(is_float(vtop->type.t & VT_BTYPE) ? RC_FLOAT : RC_INT);
} }
#if defined TCC_TARGET_ARM64 || defined TCC_TARGET_RISCV64 || defined TCC_TARGET_ARM
#define gen_cvt_itof1 gen_cvt_itof
#else
/* generic itof for unsigned long long case */ /* generic itof for unsigned long long case */
static void gen_cvt_itof1(int t) static void gen_cvt_itof1(int t)
{ {
@ -3132,11 +2848,7 @@ static void gen_cvt_itof1(int t)
gen_cvt_itof(t); gen_cvt_itof(t);
} }
} }
#endif
#if defined TCC_TARGET_ARM64 || defined TCC_TARGET_RISCV64
#define gen_cvt_ftoi1 gen_cvt_ftoi
#else
/* generic ftoi for unsigned long long case */ /* generic ftoi for unsigned long long case */
static void gen_cvt_ftoi1(int t) static void gen_cvt_ftoi1(int t)
{ {
@ -3160,7 +2872,6 @@ static void gen_cvt_ftoi1(int t)
gen_cvt_ftoi(t); gen_cvt_ftoi(t);
} }
} }
#endif
/* special delayed cast for char/short */ /* special delayed cast for char/short */
static void force_charshort_cast(void) static void force_charshort_cast(void)
@ -3217,7 +2928,7 @@ error:
} }
c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST; c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
#if !defined TCC_IS_NATIVE && !defined TCC_IS_NATIVE_387 #if !defined TCC_IS_NATIVE_387
/* don't try to convert to ldouble when cross-compiling /* don't try to convert to ldouble when cross-compiling
(except when it's '0' which is needed for arm:gen_negf()) */ (except when it's '0' which is needed for arm:gen_negf()) */
if (dbt_bt == VT_LDOUBLE && !nocode_wanted && (sf || vtop->c.i != 0)) if (dbt_bt == VT_LDOUBLE && !nocode_wanted && (sf || vtop->c.i != 0))
@ -3373,13 +3084,7 @@ error:
if (ds == 8) { if (ds == 8) {
/* need to convert from 32bit to 64bit */ /* need to convert from 32bit to 64bit */
if (sbt & VT_UNSIGNED) { if (sbt & VT_UNSIGNED) {
#if defined(TCC_TARGET_RISCV64)
/* RISC-V keeps 32bit vals in registers sign-extended.
So here we need a zero-extension. */
trunc = 32;
#else
goto done; goto done;
#endif
} else { } else {
gen_cvt_sxtw(); gen_cvt_sxtw();
goto done; goto done;
@ -3389,9 +3094,7 @@ error:
/* RISC-V keeps 32bit vals in registers sign-extended. /* RISC-V keeps 32bit vals in registers sign-extended.
So here we need a sign-extension for signed types and So here we need a sign-extension for signed types and
zero-extension. for unsigned types. */ zero-extension. for unsigned types. */
#if !defined(TCC_TARGET_RISCV64)
trunc = 32; /* zero upper 32 bits for non RISC-V targets */ trunc = 32; /* zero upper 32 bits for non RISC-V targets */
#endif
} else { } else {
ss = 4; ss = 4;
} }
@ -3399,12 +3102,10 @@ error:
if (ds >= ss) if (ds >= ss)
goto done; goto done;
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 || defined TCC_TARGET_ARM64
if (ss == 4) { if (ss == 4) {
gen_cvt_csti(dbt); gen_cvt_csti(dbt);
goto done; goto done;
} }
#endif
bits = (ss - ds) * 8; bits = (ss - ds) * 8;
/* for unsigned, gen_op will convert SAR to SHR */ /* for unsigned, gen_op will convert SAR to SHR */
vtop->type.t = (ss == 8 ? VT_LLONG : VT_INT) | (dbt & VT_UNSIGNED); vtop->type.t = (ss == 8 ? VT_LLONG : VT_INT) | (dbt & VT_UNSIGNED);
@ -3451,8 +3152,7 @@ ST_FUNC int type_size(CType *type, int *a)
*a = LDOUBLE_ALIGN; *a = LDOUBLE_ALIGN;
return LDOUBLE_SIZE; return LDOUBLE_SIZE;
} else if (bt == VT_DOUBLE || bt == VT_LLONG) { } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
#if (defined TCC_TARGET_I386 && !defined TCC_TARGET_PE) \ #if (defined TCC_TARGET_I386 && !defined TCC_TARGET_PE)
|| (defined TCC_TARGET_ARM && !defined TCC_ARM_EABI)
*a = 4; *a = 4;
#else #else
*a = 8; *a = 8;
@ -3632,27 +3332,16 @@ ST_FUNC void vstore(void)
size = type_size(&vtop->type, &align); size = type_size(&vtop->type, &align);
/* destination, keep on stack() as result */ /* destination, keep on stack() as result */
vpushv(vtop - 1); vpushv(vtop - 1);
#ifdef CONFIG_TCC_BCHECK
if (vtop->r & VT_MUSTBOUND)
gbound(); /* check would be wrong after gaddrof() */
#endif
vtop->type.t = VT_PTR; vtop->type.t = VT_PTR;
gaddrof(); gaddrof();
/* source */ /* source */
vswap(); vswap();
#ifdef CONFIG_TCC_BCHECK
if (vtop->r & VT_MUSTBOUND)
gbound();
#endif
vtop->type.t = VT_PTR; vtop->type.t = VT_PTR;
gaddrof(); gaddrof();
#ifdef TCC_TARGET_NATIVE_STRUCT_COPY #ifdef TCC_TARGET_NATIVE_STRUCT_COPY
if (1 if (1) {
#ifdef CONFIG_TCC_BCHECK
&& !tcc_state->do_bounds_check
#endif
) {
gen_struct_copy(size); gen_struct_copy(size);
} else } else
#endif #endif
@ -3660,13 +3349,6 @@ ST_FUNC void vstore(void)
/* type size */ /* type size */
vpushi(size); vpushi(size);
/* Use memmove, rather than memcpy, as dest and src may be same: */ /* Use memmove, rather than memcpy, as dest and src may be same: */
#ifdef TCC_ARM_EABI
if(!(align & 7))
vpush_helper_func(TOK_memmove8);
else if(!(align & 3))
vpush_helper_func(TOK_memmove4);
else
#endif
vpush_helper_func(TOK_memmove); vpush_helper_func(TOK_memmove);
vrott(4); vrott(4);
gfunc_call(3); gfunc_call(3);
@ -3740,14 +3422,6 @@ ST_FUNC void vstore(void)
gen_cast(&vtop[-1].type); gen_cast(&vtop[-1].type);
} }
#ifdef CONFIG_TCC_BCHECK
/* bound check case */
if (vtop[-1].r & VT_MUSTBOUND) {
vswap();
gbound();
vswap();
}
#endif
gv(RC_TYPE(dbt)); /* generate value */ gv(RC_TYPE(dbt)); /* generate value */
if (delayed_cast) { if (delayed_cast) {
@ -4283,11 +3957,7 @@ static void struct_layout(CType *type, AttributeDef *ad)
bit_pos = BIT_POS(f->type.t); bit_pos = BIT_POS(f->type.t);
size = type_size(&f->type, &align); size = type_size(&f->type, &align);
if (bit_pos + bit_size <= size * 8 && f->c + size <= c if (bit_pos + bit_size <= size * 8 && f->c + size <= c)
#ifdef TCC_TARGET_ARM
&& !(f->c & (align - 1))
#endif
)
continue; continue;
/* try to access the field using a different type */ /* try to access the field using a different type */
@ -4313,11 +3983,7 @@ static void struct_layout(CType *type, AttributeDef *ad)
c0 = cx; c0 = cx;
} }
if (px + bit_size <= s * 8 && cx + s <= c if (px + bit_size <= s * 8 && cx + s <= c) {
#ifdef TCC_TARGET_ARM
&& !(cx & (align - 1))
#endif
) {
/* update offset and bit position */ /* update offset and bit position */
f->c = cx; f->c = cx;
bit_pos = px; bit_pos = px;
@ -4590,8 +4256,6 @@ do_decl:
check_fields(type, 1); check_fields(type, 1);
check_fields(type, 0); check_fields(type, 0);
struct_layout(type, &ad); struct_layout(type, &ad);
if (debug_modes)
tcc_debug_fix_anon(tcc_state, type);
} }
} }
} }
@ -4696,13 +4360,6 @@ static int parse_btype(CType *type, AttributeDef *ad, int ignore_label)
} }
next(); next();
break; break;
#ifdef TCC_TARGET_ARM64
case TOK_UINT128:
/* GCC's __uint128_t appears in some Linux header files. Make it a
synonym for long double to get the size and alignment right. */
u = VT_LDOUBLE;
goto basic_type;
#endif
case TOK_BOOL: case TOK_BOOL:
u = VT_BOOL; u = VT_BOOL;
goto basic_type; goto basic_type;
@ -5222,11 +4879,6 @@ ST_FUNC void indir(void)
if (!(vtop->type.t & (VT_ARRAY | VT_VLA)) if (!(vtop->type.t & (VT_ARRAY | VT_VLA))
&& (vtop->type.t & VT_BTYPE) != VT_FUNC) { && (vtop->type.t & VT_BTYPE) != VT_FUNC) {
vtop->r |= VT_LVAL; vtop->r |= VT_LVAL;
/* if bound checking, the referenced pointer must be checked */
#ifdef CONFIG_TCC_BCHECK
if (tcc_state->do_bounds_check)
vtop->r |= VT_MUSTBOUND;
#endif
} }
} }
@ -5487,10 +5139,6 @@ ST_FUNC void unary(void)
Sym *s; Sym *s;
AttributeDef ad; AttributeDef ad;
/* generate line number info */
if (debug_modes)
tcc_debug_line(tcc_state), tcc_tcov_check_line (tcc_state, 1);
type.ref = NULL; type.ref = NULL;
/* XXX: GCC 2.95.3 does not generate a table although it should be /* XXX: GCC 2.95.3 does not generate a table although it should be
better here */ better here */
@ -5764,92 +5412,18 @@ ST_FUNC void unary(void)
mk_pointer(&type); mk_pointer(&type);
vset(&type, VT_LOCAL, 0); /* local frame */ vset(&type, VT_LOCAL, 0); /* local frame */
while (level--) { while (level--) {
#ifdef TCC_TARGET_RISCV64
vpushi(2*PTR_SIZE);
gen_op('-');
#endif
mk_pointer(&vtop->type); mk_pointer(&vtop->type);
indir(); /* -> parent frame */ indir(); /* -> parent frame */
} }
if (tok1 == TOK_builtin_return_address) { if (tok1 == TOK_builtin_return_address) {
// assume return address is just above frame pointer on stack // assume return address is just above frame pointer on stack
#ifdef TCC_TARGET_ARM
vpushi(2*PTR_SIZE);
gen_op('+');
#elif defined TCC_TARGET_RISCV64
vpushi(PTR_SIZE);
gen_op('-');
#else
vpushi(PTR_SIZE); vpushi(PTR_SIZE);
gen_op('+'); gen_op('+');
#endif
mk_pointer(&vtop->type); mk_pointer(&vtop->type);
indir(); indir();
} }
} }
break; break;
#ifdef TCC_TARGET_RISCV64
case TOK_builtin_va_start:
parse_builtin_params(0, "ee");
r = vtop->r & VT_VALMASK;
if (r == VT_LLOCAL)
r = VT_LOCAL;
if (r != VT_LOCAL)
tcc_error("__builtin_va_start expects a local variable");
gen_va_start();
vstore();
break;
#endif
#ifdef TCC_TARGET_X86_64
#ifdef TCC_TARGET_PE
case TOK_builtin_va_start:
parse_builtin_params(0, "ee");
r = vtop->r & VT_VALMASK;
if (r == VT_LLOCAL)
r = VT_LOCAL;
if (r != VT_LOCAL)
tcc_error("__builtin_va_start expects a local variable");
vtop->r = r;
vtop->type = char_pointer_type;
vtop->c.i += 8;
vstore();
break;
#else
case TOK_builtin_va_arg_types:
parse_builtin_params(0, "t");
vpushi(classify_x86_64_va_arg(&vtop->type));
vswap();
vpop();
break;
#endif
#endif
#ifdef TCC_TARGET_ARM64
case TOK_builtin_va_start: {
parse_builtin_params(0, "ee");
//xx check types
gen_va_start();
vpushi(0);
vtop->type.t = VT_VOID;
break;
}
case TOK_builtin_va_arg: {
parse_builtin_params(0, "et");
type = vtop->type;
vpop();
//xx check types
gen_va_arg(&type);
vtop->type = type;
break;
}
case TOK___arm64_clear_cache: {
parse_builtin_params(0, "ee");
gen_clear_cache();
vpushi(0);
vtop->type.t = VT_VOID;
break;
}
#endif
/* atomic operations */ /* atomic operations */
case TOK___atomic_store: case TOK___atomic_store:
@ -6066,11 +5640,6 @@ special_math_val:
/* an array is never an lvalue */ /* an array is never an lvalue */
if (!(vtop->type.t & VT_ARRAY)) { if (!(vtop->type.t & VT_ARRAY)) {
vtop->r |= VT_LVAL; vtop->r |= VT_LVAL;
#ifdef CONFIG_TCC_BCHECK
/* if bound checking, the referenced pointer must be checked */
if (tcc_state->do_bounds_check)
vtop->r |= VT_MUSTBOUND;
#endif
} }
next(); next();
} else if (tok == '[') { } else if (tok == '[') {
@ -6113,25 +5682,12 @@ special_math_val:
if (ret_nregs <= 0) { if (ret_nregs <= 0) {
/* get some space for the returned structure */ /* get some space for the returned structure */
size = type_size(&s->type, &align); size = type_size(&s->type, &align);
#ifdef TCC_TARGET_ARM64
/* On arm64, a small struct is return in registers.
It is much easier to write it to memory if we know
that we are allowed to write some extra bytes, so
round the allocated space up to a power of 2: */
if (size < 16)
while (size & (size - 1))
size = (size | (size - 1)) + 1;
#endif
loc = (loc - size) & -align; loc = (loc - size) & -align;
ret.type = s->type; ret.type = s->type;
ret.r = VT_LOCAL | VT_LVAL; ret.r = VT_LOCAL | VT_LVAL;
/* pass it as 'int' to avoid structure arg passing /* pass it as 'int' to avoid structure arg passing
problems */ problems */
vseti(VT_LOCAL, loc); vseti(VT_LOCAL, loc);
#ifdef CONFIG_TCC_BCHECK
if (tcc_state->do_bounds_check)
--loc;
#endif
ret.c = vtop->c; ret.c = vtop->c;
if (ret_nregs < 0) if (ret_nregs < 0)
vtop--; vtop--;
@ -6191,9 +5747,6 @@ special_math_val:
if (ret_nregs < 0) { if (ret_nregs < 0) {
vsetc(&ret.type, ret.r, &ret.c); vsetc(&ret.type, ret.r, &ret.c);
#ifdef TCC_TARGET_RISCV64
arch_transfer_ret_regs(1);
#endif
} else { } else {
/* return value */ /* return value */
n = ret_nregs; n = ret_nregs;
@ -6251,8 +5804,6 @@ special_math_val:
} }
} }
if (s->f.func_noreturn) { if (s->f.func_noreturn) {
if (debug_modes)
tcc_tcov_block_end(tcc_state, -1);
CODE_OFF(); CODE_OFF();
} }
} else { } else {
@ -6679,7 +6230,7 @@ ST_FUNC int expr_const(void)
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
/* return from function */ /* return from function */
#ifndef TCC_TARGET_ARM64
static void gfunc_return(CType *func_type) static void gfunc_return(CType *func_type)
{ {
if ((func_type->t & VT_BTYPE) == VT_STRUCT) { if ((func_type->t & VT_BTYPE) == VT_STRUCT) {
@ -6688,9 +6239,6 @@ static void gfunc_return(CType *func_type)
ret_nregs = gfunc_sret(func_type, func_var, &ret_type, ret_nregs = gfunc_sret(func_type, func_var, &ret_type,
&ret_align, &regsize); &ret_align, &regsize);
if (ret_nregs < 0) { if (ret_nregs < 0) {
#ifdef TCC_TARGET_RISCV64
arch_transfer_ret_regs(0);
#endif
} else if (0 == ret_nregs) { } else if (0 == ret_nregs) {
/* if returning structure, must copy it to implicit /* if returning structure, must copy it to implicit
first pointer arg location */ first pointer arg location */
@ -6739,7 +6287,6 @@ static void gfunc_return(CType *func_type)
} }
vtop--; /* NOT vpop() because on x86 it would flush the fp stack */ vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
} }
#endif
static void check_func_return(void) static void check_func_return(void)
{ {
@ -7027,9 +6574,6 @@ again:
goto expr; goto expr;
next(); next();
if (debug_modes)
tcc_tcov_check_line (tcc_state, 0), tcc_tcov_block_begin (tcc_state);
if (t == TOK_IF) { if (t == TOK_IF) {
new_scope_s(&o); new_scope_s(&o);
skip('('); skip('(');
@ -7063,8 +6607,6 @@ again:
prev_scope_s(&o); prev_scope_s(&o);
} else if (t == '{') { } else if (t == '{') {
if (debug_modes)
tcc_debug_stabn(tcc_state, N_LBRAC, ind - func_ind);
new_scope(&o); new_scope(&o);
/* handle local labels declarations */ /* handle local labels declarations */
@ -7089,8 +6631,6 @@ again:
} }
prev_scope(&o, flags & STMT_EXPR); prev_scope(&o, flags & STMT_EXPR);
if (debug_modes)
tcc_debug_stabn(tcc_state, N_RBRAC, ind - func_ind);
if (local_scope) if (local_scope)
next(); next();
else if (!nocode_wanted) else if (!nocode_wanted)
@ -7118,8 +6658,6 @@ again:
/* jump unless last stmt in top-level block */ /* jump unless last stmt in top-level block */
if (tok != '}' || local_scope != 1) if (tok != '}' || local_scope != 1)
rsym = gjmp(rsym); rsym = gjmp(rsym);
if (debug_modes)
tcc_tcov_block_end (tcc_state, -1);
CODE_OFF(); CODE_OFF();
} else if (t == TOK_BREAK) { } else if (t == TOK_BREAK) {
@ -7332,8 +6870,6 @@ again:
AttributeDef ad_tmp; AttributeDef ad_tmp;
parse_attribute(&ad_tmp); parse_attribute(&ad_tmp);
} }
if (debug_modes)
tcc_tcov_reset_ind(tcc_state);
vla_restore(cur_scope->vla.loc); vla_restore(cur_scope->vla.loc);
if (tok != '}') { if (tok != '}') {
@ -7360,9 +6896,6 @@ again:
} }
} }
} }
if (debug_modes)
tcc_tcov_check_line (tcc_state, 0), tcc_tcov_block_end (tcc_state, 0);
} }
/* This skips over a stream of tokens containing balanced {} and () /* This skips over a stream of tokens containing balanced {} and ()
@ -7459,9 +6992,6 @@ static void init_putz(init_params *p, unsigned long c, int size)
vseti(VT_LOCAL, c); vseti(VT_LOCAL, c);
vpushi(0); vpushi(0);
vpushs(size); vpushs(size);
#if defined TCC_TARGET_ARM && defined TCC_ARM_EABI
vswap(); /* using __aeabi_memset(void*, size_t, int) */
#endif
gfunc_call(3); gfunc_call(3);
} }
} }
@ -7834,10 +7364,6 @@ static void decl_initializer(init_params *p, CType *type, unsigned long c, int f
Sym indexsym; Sym indexsym;
CType *t1; CType *t1;
/* generate line number info */
if (debug_modes && !(flags & DIF_SIZE_ONLY) && !p->sec)
tcc_debug_line(tcc_state), tcc_tcov_check_line (tcc_state, 1);
if (!(flags & DIF_HAVE_ELEM) && tok != '{' && if (!(flags & DIF_HAVE_ELEM) && tok != '{' &&
/* In case of strings we have special handling for arrays, so /* In case of strings we have special handling for arrays, so
don't consume them as initializer value (which would commit them don't consume them as initializer value (which would commit them
@ -8060,9 +7586,6 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
Sym *flexible_array; Sym *flexible_array;
Sym *sym; Sym *sym;
int saved_nocode_wanted = nocode_wanted; int saved_nocode_wanted = nocode_wanted;
#ifdef CONFIG_TCC_BCHECK
int bcheck = tcc_state->do_bounds_check && !NODATA_WANTED;
#endif
init_params p = {0}; init_params p = {0};
/* Always allocate static or global variables */ /* Always allocate static or global variables */
@ -8151,21 +7674,10 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
if ((r & VT_VALMASK) == VT_LOCAL) { if ((r & VT_VALMASK) == VT_LOCAL) {
sec = NULL; sec = NULL;
#ifdef CONFIG_TCC_BCHECK
if (bcheck && v) {
/* add padding between stack variables for bound checking */
loc -= align;
}
#endif
loc = (loc - size) & -align; loc = (loc - size) & -align;
addr = loc; addr = loc;
p.local_offset = addr + size; p.local_offset = addr + size;
#ifdef CONFIG_TCC_BCHECK
if (bcheck && v) {
/* add padding between stack variables for bound checking */
loc -= align;
}
#endif
if (v) { if (v) {
/* local variable */ /* local variable */
#ifdef CONFIG_TCC_ASM #ifdef CONFIG_TCC_ASM
@ -8229,11 +7741,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
if (sec) { if (sec) {
addr = section_add(sec, size, align); addr = section_add(sec, size, align);
#ifdef CONFIG_TCC_BCHECK
/* add padding if bound check */
if (bcheck)
section_add(sec, 1, 1);
#endif
} else { } else {
addr = align; /* SHN_COMMON is special, symbol value is align */ addr = align; /* SHN_COMMON is special, symbol value is align */
sec = common_section; sec = common_section;
@ -8253,19 +7761,6 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
vtop->r |= r; vtop->r |= r;
} }
#ifdef CONFIG_TCC_BCHECK
/* handles bounds now because the symbol must be defined
before for the relocation */
if (bcheck) {
addr_t *bounds_ptr;
greloca(bounds_section, sym, bounds_section->data_offset, R_DATA_PTR, 0);
/* then add global bound info */
bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(addr_t));
bounds_ptr[0] = 0; /* relocated */
bounds_ptr[1] = size;
}
#endif
} }
if (type->t & VT_VLA) { if (type->t & VT_VLA) {
@ -8286,11 +7781,6 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
vpush_type_size(type, &a); vpush_type_size(type, &a);
gen_vla_alloc(type, a); gen_vla_alloc(type, a);
#if defined TCC_TARGET_PE && defined TCC_TARGET_X86_64
/* on _WIN64, because of the function args scratch area, the
result of alloca differs from RSP and is returned in RAX. */
gen_vla_result(addr), addr = (loc -= PTR_SIZE);
#endif
gen_vla_sp_save(addr); gen_vla_sp_save(addr);
cur_scope->vla.loc = addr; cur_scope->vla.loc = addr;
cur_scope->vla.num++; cur_scope->vla.num++;
@ -8381,15 +7871,12 @@ static void gen_function(Sym *sym)
if (sym->type.ref->f.func_dtor) if (sym->type.ref->f.func_dtor)
add_array (tcc_state, ".fini_array", sym->c); add_array (tcc_state, ".fini_array", sym->c);
/* put debug symbol */
tcc_debug_funcstart(tcc_state, sym);
/* push a dummy symbol to enable local sym storage */ /* push a dummy symbol to enable local sym storage */
sym_push2(&local_stack, SYM_FIELD, 0, 0); sym_push2(&local_stack, SYM_FIELD, 0, 0);
local_scope = 1; /* for function parameters */ local_scope = 1; /* for function parameters */
nb_temp_local_vars = 0; nb_temp_local_vars = 0;
gfunc_prolog(sym); gfunc_prolog(sym);
tcc_debug_prolog_epilog(tcc_state, 0);
local_scope = 0; local_scope = 0;
rsym = 0; rsym = 0;
@ -8400,11 +7887,8 @@ static void gen_function(Sym *sym)
nocode_wanted = 0; nocode_wanted = 0;
/* reset local stack */ /* reset local stack */
pop_local_syms(NULL, 0); pop_local_syms(NULL, 0);
tcc_debug_prolog_epilog(tcc_state, 1);
gfunc_epilog(); gfunc_epilog();
/* end of function */
tcc_debug_funcend(tcc_state, ind - func_ind);
/* patch symbol size */ /* patch symbol size */
elfsym(sym)->st_size = ind - func_ind; elfsym(sym)->st_size = ind - func_ind;
@ -8691,8 +8175,6 @@ static int decl(int l)
sym->a = ad.a; sym->a = ad.a;
if ((type.t & VT_BTYPE) == VT_FUNC) if ((type.t & VT_BTYPE) == VT_FUNC)
merge_funcattr(&sym->type.ref->f, &ad.f); merge_funcattr(&sym->type.ref->f, &ad.f);
if (debug_modes)
tcc_debug_typedef (tcc_state, sym);
} else if ((type.t & VT_BTYPE) == VT_VOID } else if ((type.t & VT_BTYPE) == VT_VOID
&& !(type.t & VT_EXTERN)) { && !(type.t & VT_EXTERN)) {
tcc_error("declaration of void object"); tcc_error("declaration of void object");

View file

@ -20,6 +20,8 @@
#include "tcc.h" #include "tcc.h"
#define TCC_OUTPUT_DLL 666
#define PE_MERGE_DATA 1 #define PE_MERGE_DATA 1
#define PE_PRINT_SECTIONS 0 #define PE_PRINT_SECTIONS 0
@ -1880,22 +1882,6 @@ static void pe_add_runtime(TCCState *s1, struct pe_info *pe)
++start_symbol; ++start_symbol;
} }
#ifdef CONFIG_TCC_BACKTRACE
if (s1->do_backtrace) {
#ifdef CONFIG_TCC_BCHECK
if (s1->do_bounds_check && s1->output_type != TCC_OUTPUT_DLL)
tcc_add_support(s1, "bcheck.o");
#endif
if (s1->output_type == TCC_OUTPUT_EXE)
tcc_add_support(s1, "bt-exe.o");
if (s1->output_type == TCC_OUTPUT_DLL)
tcc_add_support(s1, "bt-dll.o");
if (s1->output_type != TCC_OUTPUT_DLL)
tcc_add_support(s1, "bt-log.o");
tcc_add_btstub(s1);
}
#endif
/* grab the startup code from libtcc1.a */ /* grab the startup code from libtcc1.a */
#ifdef TCC_IS_NATIVE #ifdef TCC_IS_NATIVE
if (TCC_OUTPUT_MEMORY != s1->output_type || s1->run_main) if (TCC_OUTPUT_MEMORY != s1->output_type || s1->run_main)
@ -1982,9 +1968,6 @@ ST_FUNC int pe_output_file(TCCState *s1, const char *filename)
pe.s1 = s1; pe.s1 = s1;
s1->filetype = 0; s1->filetype = 0;
#ifdef CONFIG_TCC_BCHECK
tcc_add_bcheck(s1);
#endif
tcc_add_pragma_libs(s1); tcc_add_pragma_libs(s1);
pe_add_runtime(s1, &pe); pe_add_runtime(s1, &pe);
resolve_common_syms(s1); resolve_common_syms(s1);

View file

@ -20,6 +20,7 @@
#define USING_GLOBALS #define USING_GLOBALS
#include "tcc.h" #include "tcc.h"
#include "utils/string.h"
/* #define to 1 to enable (see parse_pp_string()) */ /* #define to 1 to enable (see parse_pp_string()) */
#define ACCEPT_LF_IN_STRINGS 0 #define ACCEPT_LF_IN_STRINGS 0
@ -946,12 +947,8 @@ redo_start:
else if (parse_flags & PARSE_FLAG_ASM_FILE) else if (parse_flags & PARSE_FLAG_ASM_FILE)
p = parse_line_comment(p - 1); p = parse_line_comment(p - 1);
} }
#if !defined(TCC_TARGET_ARM)
else if (parse_flags & PARSE_FLAG_ASM_FILE) else if (parse_flags & PARSE_FLAG_ASM_FILE)
p = parse_line_comment(p - 1); p = parse_line_comment(p - 1);
#else
/* ARM assembly uses '#' for constants */
#endif
break; break;
_default: _default:
default: default:
@ -1326,8 +1323,8 @@ static void maybe_run_test(TCCState *s)
p = get_tok_str(tok, NULL); p = get_tok_str(tok, NULL);
if (0 != memcmp(p, "test_", 5)) if (0 != memcmp(p, "test_", 5))
return; return;
if (0 != --s->run_test) /*if (0 != --s->run_test)
return; return;*/
fprintf(s->ppfp, &"\n[%s]\n"[!(s->dflag & 32)], p), fflush(s->ppfp); fprintf(s->ppfp, &"\n[%s]\n"[!(s->dflag & 32)], p), fflush(s->ppfp);
define_push(tok, MACRO_OBJ, NULL, NULL); define_push(tok, MACRO_OBJ, NULL, NULL);
} }
@ -1446,8 +1443,6 @@ static int parse_include(TCCState *s1, int do_next, int test)
dynarray_add(&s1->target_deps, &s1->nb_target_deps, dynarray_add(&s1->target_deps, &s1->nb_target_deps,
tcc_strdup(buf)); tcc_strdup(buf));
} }
/* add include file debug info */
tcc_debug_bincl(s1);
} }
return 1; return 1;
} }
@ -1479,8 +1474,6 @@ static int expr_preprocess(TCCState *s1)
parse_flags |= PARSE_FLAG_PREPROCESS; parse_flags |= PARSE_FLAG_PREPROCESS;
if (tok < TOK_IDENT) if (tok < TOK_IDENT)
expect("identifier after 'defined'"); expect("identifier after 'defined'");
if (s1->run_test)
maybe_run_test(s1);
c = 0; c = 0;
if (define_find(tok) if (define_find(tok)
|| tok == TOK___HAS_INCLUDE || tok == TOK___HAS_INCLUDE
@ -1806,7 +1799,6 @@ ST_FUNC void tccpp_putfile(const char *filename)
if (file->true_filename == file->filename) if (file->true_filename == file->filename)
file->true_filename = tcc_strdup(file->filename); file->true_filename = tcc_strdup(file->filename);
pstrcpy(file->filename, sizeof file->filename, buf); pstrcpy(file->filename, sizeof file->filename, buf);
tcc_debug_newfile(tcc_state);
} }
/* is_bof is true if first non space token at beginning of file */ /* is_bof is true if first non space token at beginning of file */
@ -2615,8 +2607,6 @@ static void next_nomacro(void)
tok_flags &= ~TOK_FLAG_ENDIF; tok_flags &= ~TOK_FLAG_ENDIF;
} }
/* add end of include file debug info */
tcc_debug_eincl(tcc_state);
/* pop include stack */ /* pop include stack */
tcc_close(); tcc_close();
s1->include_stack_ptr--; s1->include_stack_ptr--;
@ -2653,12 +2643,10 @@ maybe_newline:
p++; p++;
tok = TOK_TWOSHARPS; tok = TOK_TWOSHARPS;
} else { } else {
#if !defined(TCC_TARGET_ARM)
if (parse_flags & PARSE_FLAG_ASM_FILE) { if (parse_flags & PARSE_FLAG_ASM_FILE) {
p = parse_line_comment(p - 1); p = parse_line_comment(p - 1);
goto redo_no_start; goto redo_no_start;
} else } else
#endif
{ {
tok = '#'; tok = '#';
} }
@ -3576,24 +3564,12 @@ static void tcc_predefs(TCCState *s1, CString *cs, int is_asm)
putdefs(cs, target_machine_defs); putdefs(cs, target_machine_defs);
putdefs(cs, target_os_defs); putdefs(cs, target_os_defs);
#ifdef TCC_TARGET_ARM
if (s1->float_abi == ARM_HARD_FLOAT)
putdef(cs, "__ARM_PCS_VFP");
#endif
if (is_asm) if (is_asm)
putdef(cs, "__ASSEMBLER__"); putdef(cs, "__ASSEMBLER__");
if (s1->output_type == TCC_OUTPUT_PREPROCESS) if (s1->output_type == TCC_OUTPUT_PREPROCESS)
putdef(cs, "__TCC_PP__"); putdef(cs, "__TCC_PP__");
if (s1->output_type == TCC_OUTPUT_MEMORY) if (s1->output_type == TCC_OUTPUT_MEMORY)
putdef(cs, "__TCC_RUN__"); putdef(cs, "__TCC_RUN__");
#ifdef CONFIG_TCC_BACKTRACE
if (s1->do_backtrace)
putdef(cs, "__TCC_BACKTRACE__");
#endif
#ifdef CONFIG_TCC_BCHECK
if (s1->do_bounds_check)
putdef(cs, "__TCC_BCHECK__");
#endif
if (s1->char_is_unsigned) if (s1->char_is_unsigned)
putdef(cs, "__CHAR_UNSIGNED__"); putdef(cs, "__CHAR_UNSIGNED__");
if (s1->optimize > 0) if (s1->optimize > 0)

View file

@ -68,10 +68,6 @@
DEF(TOK_TYPEOF3, "__typeof__") DEF(TOK_TYPEOF3, "__typeof__")
DEF(TOK_LABEL, "__label__") DEF(TOK_LABEL, "__label__")
#ifdef TCC_TARGET_ARM64
DEF(TOK_UINT128, "__uint128_t")
#endif
/*********************************************************************/ /*********************************************************************/
/* the following are not keywords. They are included to ease parsing */ /* the following are not keywords. They are included to ease parsing */
/* preprocessor only */ /* preprocessor only */
@ -105,10 +101,6 @@
DEF(TOK___NAN__, "__nan__") DEF(TOK___NAN__, "__nan__")
DEF(TOK___SNAN__, "__snan__") DEF(TOK___SNAN__, "__snan__")
DEF(TOK___INF__, "__inf__") DEF(TOK___INF__, "__inf__")
#if defined TCC_TARGET_X86_64
DEF(TOK___mzerosf, "__mzerosf") /* -0.0 */
DEF(TOK___mzerodf, "__mzerodf") /* -0.0 */
#endif
/* attribute identifiers */ /* attribute identifiers */
/* XXX: handle all tokens generically since speed is not critical */ /* XXX: handle all tokens generically since speed is not critical */
@ -173,16 +165,6 @@
DEF(TOK_builtin_expect, "__builtin_expect") DEF(TOK_builtin_expect, "__builtin_expect")
DEF(TOK_builtin_unreachable, "__builtin_unreachable") DEF(TOK_builtin_unreachable, "__builtin_unreachable")
/*DEF(TOK_builtin_va_list, "__builtin_va_list")*/ /*DEF(TOK_builtin_va_list, "__builtin_va_list")*/
#if defined TCC_TARGET_PE && defined TCC_TARGET_X86_64
DEF(TOK_builtin_va_start, "__builtin_va_start")
#elif defined TCC_TARGET_X86_64
DEF(TOK_builtin_va_arg_types, "__builtin_va_arg_types")
#elif defined TCC_TARGET_ARM64
DEF(TOK_builtin_va_start, "__builtin_va_start")
DEF(TOK_builtin_va_arg, "__builtin_va_arg")
#elif defined TCC_TARGET_RISCV64
DEF(TOK_builtin_va_start, "__builtin_va_start")
#endif
/* atomic operations */ /* atomic operations */
#define DEF_ATOMIC(ID) DEF(TOK_##__##ID, "__"#ID) #define DEF_ATOMIC(ID) DEF(TOK_##__##ID, "__"#ID)
@ -205,13 +187,6 @@
/* pragma */ /* pragma */
DEF(TOK_pack, "pack") DEF(TOK_pack, "pack")
#if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_X86_64) && \
!defined(TCC_TARGET_ARM) && !defined(TCC_TARGET_ARM64) && \
!defined(TCC_TARGET_RISCV64)
/* already defined for assembler */
DEF(TOK_ASM_push, "push")
DEF(TOK_ASM_pop, "pop")
#endif
DEF(TOK_comment, "comment") DEF(TOK_comment, "comment")
DEF(TOK_lib, "lib") DEF(TOK_lib, "lib")
DEF(TOK_push_macro, "push_macro") DEF(TOK_push_macro, "push_macro")
@ -220,7 +195,6 @@
DEF(TOK_option, "option") DEF(TOK_option, "option")
/* builtin functions or variables */ /* builtin functions or variables */
#ifndef TCC_ARM_EABI
DEF(TOK_memcpy, "memcpy") DEF(TOK_memcpy, "memcpy")
DEF(TOK_memmove, "memmove") DEF(TOK_memmove, "memmove")
DEF(TOK_memset, "memset") DEF(TOK_memset, "memset")
@ -233,134 +207,16 @@
DEF(TOK___ashldi3, "__ashldi3") DEF(TOK___ashldi3, "__ashldi3")
DEF(TOK___floatundisf, "__floatundisf") DEF(TOK___floatundisf, "__floatundisf")
DEF(TOK___floatundidf, "__floatundidf") DEF(TOK___floatundidf, "__floatundidf")
# ifndef TCC_ARM_VFP
DEF(TOK___floatundixf, "__floatundixf") DEF(TOK___floatundixf, "__floatundixf")
DEF(TOK___fixunsxfdi, "__fixunsxfdi") DEF(TOK___fixunsxfdi, "__fixunsxfdi")
# endif
DEF(TOK___fixunssfdi, "__fixunssfdi") DEF(TOK___fixunssfdi, "__fixunssfdi")
DEF(TOK___fixunsdfdi, "__fixunsdfdi") DEF(TOK___fixunsdfdi, "__fixunsdfdi")
#endif
#if defined TCC_TARGET_ARM
# ifdef TCC_ARM_EABI
DEF(TOK_memcpy, "__aeabi_memcpy")
DEF(TOK_memmove, "__aeabi_memmove")
DEF(TOK_memmove4, "__aeabi_memmove4")
DEF(TOK_memmove8, "__aeabi_memmove8")
DEF(TOK_memset, "__aeabi_memset")
DEF(TOK___aeabi_ldivmod, "__aeabi_ldivmod")
DEF(TOK___aeabi_uldivmod, "__aeabi_uldivmod")
DEF(TOK___aeabi_idivmod, "__aeabi_idivmod")
DEF(TOK___aeabi_uidivmod, "__aeabi_uidivmod")
DEF(TOK___divsi3, "__aeabi_idiv")
DEF(TOK___udivsi3, "__aeabi_uidiv")
DEF(TOK___floatdisf, "__aeabi_l2f")
DEF(TOK___floatdidf, "__aeabi_l2d")
DEF(TOK___fixsfdi, "__aeabi_f2lz")
DEF(TOK___fixdfdi, "__aeabi_d2lz")
DEF(TOK___ashrdi3, "__aeabi_lasr")
DEF(TOK___lshrdi3, "__aeabi_llsr")
DEF(TOK___ashldi3, "__aeabi_llsl")
DEF(TOK___floatundisf, "__aeabi_ul2f")
DEF(TOK___floatundidf, "__aeabi_ul2d")
DEF(TOK___fixunssfdi, "__aeabi_f2ulz")
DEF(TOK___fixunsdfdi, "__aeabi_d2ulz")
# else
DEF(TOK___modsi3, "__modsi3")
DEF(TOK___umodsi3, "__umodsi3")
DEF(TOK___divsi3, "__divsi3")
DEF(TOK___udivsi3, "__udivsi3")
DEF(TOK___floatdisf, "__floatdisf")
DEF(TOK___floatdidf, "__floatdidf")
# ifndef TCC_ARM_VFP
DEF(TOK___floatdixf, "__floatdixf")
DEF(TOK___fixunssfsi, "__fixunssfsi")
DEF(TOK___fixunsdfsi, "__fixunsdfsi")
DEF(TOK___fixunsxfsi, "__fixunsxfsi")
DEF(TOK___fixxfdi, "__fixxfdi")
# endif
DEF(TOK___fixsfdi, "__fixsfdi")
DEF(TOK___fixdfdi, "__fixdfdi")
# endif
#endif
#if defined TCC_TARGET_C67
DEF(TOK__divi, "_divi")
DEF(TOK__divu, "_divu")
DEF(TOK__divf, "_divf")
DEF(TOK__divd, "_divd")
DEF(TOK__remi, "_remi")
DEF(TOK__remu, "_remu")
#endif
#if defined TCC_TARGET_I386
DEF(TOK___fixsfdi, "__fixsfdi") DEF(TOK___fixsfdi, "__fixsfdi")
DEF(TOK___fixdfdi, "__fixdfdi") DEF(TOK___fixdfdi, "__fixdfdi")
DEF(TOK___fixxfdi, "__fixxfdi") DEF(TOK___fixxfdi, "__fixxfdi")
#endif
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
DEF(TOK_alloca, "alloca") DEF(TOK_alloca, "alloca")
#endif
#if defined TCC_TARGET_PE
DEF(TOK___chkstk, "__chkstk")
#endif
#if defined TCC_TARGET_ARM64 || defined TCC_TARGET_RISCV64
DEF(TOK___arm64_clear_cache, "__arm64_clear_cache")
DEF(TOK___addtf3, "__addtf3")
DEF(TOK___subtf3, "__subtf3")
DEF(TOK___multf3, "__multf3")
DEF(TOK___divtf3, "__divtf3")
DEF(TOK___extendsftf2, "__extendsftf2")
DEF(TOK___extenddftf2, "__extenddftf2")
DEF(TOK___trunctfsf2, "__trunctfsf2")
DEF(TOK___trunctfdf2, "__trunctfdf2")
DEF(TOK___fixtfsi, "__fixtfsi")
DEF(TOK___fixtfdi, "__fixtfdi")
DEF(TOK___fixunstfsi, "__fixunstfsi")
DEF(TOK___fixunstfdi, "__fixunstfdi")
DEF(TOK___floatsitf, "__floatsitf")
DEF(TOK___floatditf, "__floatditf")
DEF(TOK___floatunsitf, "__floatunsitf")
DEF(TOK___floatunditf, "__floatunditf")
DEF(TOK___eqtf2, "__eqtf2")
DEF(TOK___netf2, "__netf2")
DEF(TOK___lttf2, "__lttf2")
DEF(TOK___letf2, "__letf2")
DEF(TOK___gttf2, "__gttf2")
DEF(TOK___getf2, "__getf2")
#endif
/* bound checking symbols */
#ifdef CONFIG_TCC_BCHECK
DEF(TOK___bound_ptr_add, "__bound_ptr_add")
DEF(TOK___bound_ptr_indir1, "__bound_ptr_indir1")
DEF(TOK___bound_ptr_indir2, "__bound_ptr_indir2")
DEF(TOK___bound_ptr_indir4, "__bound_ptr_indir4")
DEF(TOK___bound_ptr_indir8, "__bound_ptr_indir8")
DEF(TOK___bound_ptr_indir12, "__bound_ptr_indir12")
DEF(TOK___bound_ptr_indir16, "__bound_ptr_indir16")
DEF(TOK___bound_main_arg, "__bound_main_arg")
DEF(TOK___bound_local_new, "__bound_local_new")
DEF(TOK___bound_local_delete, "__bound_local_delete")
DEF(TOK___bound_setjmp, "__bound_setjmp")
DEF(TOK___bound_longjmp, "__bound_longjmp")
DEF(TOK___bound_new_region, "__bound_new_region")
# ifdef TCC_TARGET_PE
# ifdef TCC_TARGET_X86_64
DEF(TOK___bound_alloca_nr, "__bound_alloca_nr")
# endif
# else
DEF(TOK_sigsetjmp, "sigsetjmp")
DEF(TOK___sigsetjmp, "__sigsetjmp")
DEF(TOK_siglongjmp, "siglongjmp")
# endif
DEF(TOK_setjmp, "setjmp")
DEF(TOK__setjmp, "_setjmp")
DEF(TOK_longjmp, "longjmp")
#endif
/*********************************************************************/ /*********************************************************************/
/* Tiny Assembler */ /* Tiny Assembler */
@ -401,28 +257,12 @@
DEF_ASMDIR(endr) DEF_ASMDIR(endr)
DEF_ASMDIR(org) DEF_ASMDIR(org)
DEF_ASMDIR(quad) DEF_ASMDIR(quad)
#if defined(TCC_TARGET_I386)
DEF_ASMDIR(code16) DEF_ASMDIR(code16)
DEF_ASMDIR(code32) DEF_ASMDIR(code32)
#elif defined(TCC_TARGET_X86_64)
DEF_ASMDIR(code64)
#elif defined(TCC_TARGET_RISCV64)
DEF_ASMDIR(option)
#endif
DEF_ASMDIR(short) DEF_ASMDIR(short)
DEF_ASMDIR(long) DEF_ASMDIR(long)
DEF_ASMDIR(int) DEF_ASMDIR(int)
DEF_ASMDIR(symver) DEF_ASMDIR(symver)
DEF_ASMDIR(section) /* must be last directive */ DEF_ASMDIR(section) /* must be last directive */
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 #include "i386/tok.h"
#include "i386-tok.h"
#endif
#if defined TCC_TARGET_ARM || defined TCC_TARGET_ARM64
#include "arm-tok.h"
#endif
#if defined TCC_TARGET_RISCV64
#include "riscv64-tok.h"
#endif

47
libtcc/utils/string.h Normal file
View file

@ -0,0 +1,47 @@
#ifndef LIBTCC_UTILS_STRING_H
# define LIBTCC_UTILS_STRING_H 1
# include <stddef.h>
# include <string.h>
/* copy a string and truncate it. */
static inline char *
pstrcpy(char *buf, size_t buf_size, const char *s)
{
char *q, *q_end;
int c;
if (buf_size > 0) {
q = buf;
q_end = buf + buf_size - 1;
while (q < q_end) {
c = *s++;
if (c == '\0')
break;
*q++ = c;
}
*q = '\0';
}
return buf;
}
/* strcat and truncate. */
static inline char *
pstrcat(char *buf, size_t buf_size, const char *s)
{
size_t len;
len = strlen(buf);
if (len < buf_size)
pstrcpy(buf + len, buf_size - len, s);
return buf;
}
static inline char *
pstrncpy(char *out, const char *in, size_t num)
{
memcpy(out, in, num);
out[num] = '\0';
return out;
}
#endif /* !LIBTCC_UTILS_STRING_H */

234
stab.def
View file

@ -1,234 +0,0 @@
/* Table of DBX symbol codes for the GNU system.
Copyright (C) 1988, 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* This contains contribution from Cygnus Support. */
/* Global variable. Only the name is significant.
To find the address, look in the corresponding external symbol. */
__define_stab (N_GSYM, 0x20, "GSYM")
/* Function name for BSD Fortran. Only the name is significant.
To find the address, look in the corresponding external symbol. */
__define_stab (N_FNAME, 0x22, "FNAME")
/* Function name or text-segment variable for C. Value is its address.
Desc is supposedly starting line number, but GCC doesn't set it
and DBX seems not to miss it. */
__define_stab (N_FUN, 0x24, "FUN")
/* Data-segment variable with internal linkage. Value is its address.
"Static Sym". */
__define_stab (N_STSYM, 0x26, "STSYM")
/* BSS-segment variable with internal linkage. Value is its address. */
__define_stab (N_LCSYM, 0x28, "LCSYM")
/* Name of main routine. Only the name is significant.
This is not used in C. */
__define_stab (N_MAIN, 0x2a, "MAIN")
/* Global symbol in Pascal.
Supposedly the value is its line number; I'm skeptical. */
__define_stab (N_PC, 0x30, "PC")
/* Number of symbols: 0, files,,funcs,lines according to Ultrix V4.0. */
__define_stab (N_NSYMS, 0x32, "NSYMS")
/* "No DST map for sym: name, ,0,type,ignored" according to Ultrix V4.0. */
__define_stab (N_NOMAP, 0x34, "NOMAP")
/* New stab from Solaris. I don't know what it means, but it
don't seem to contain useful information. */
__define_stab (N_OBJ, 0x38, "OBJ")
/* New stab from Solaris. I don't know what it means, but it
don't seem to contain useful information. Possibly related to the
optimization flags used in this module. */
__define_stab (N_OPT, 0x3c, "OPT")
/* Register variable. Value is number of register. */
__define_stab (N_RSYM, 0x40, "RSYM")
/* Modula-2 compilation unit. Can someone say what info it contains? */
__define_stab (N_M2C, 0x42, "M2C")
/* Line number in text segment. Desc is the line number;
value is corresponding address. */
__define_stab (N_SLINE, 0x44, "SLINE")
/* Similar, for data segment. */
__define_stab (N_DSLINE, 0x46, "DSLINE")
/* Similar, for bss segment. */
__define_stab (N_BSLINE, 0x48, "BSLINE")
/* Sun's source-code browser stabs. ?? Don't know what the fields are.
Supposedly the field is "path to associated .cb file". THIS VALUE
OVERLAPS WITH N_BSLINE! */
__define_stab (N_BROWS, 0x48, "BROWS")
/* GNU Modula-2 definition module dependency. Value is the modification time
of the definition file. Other is non-zero if it is imported with the
GNU M2 keyword %INITIALIZE. Perhaps N_M2C can be used if there
are enough empty fields? */
__define_stab(N_DEFD, 0x4a, "DEFD")
/* THE FOLLOWING TWO STAB VALUES CONFLICT. Happily, one is for Modula-2
and one is for C++. Still,... */
/* GNU C++ exception variable. Name is variable name. */
__define_stab (N_EHDECL, 0x50, "EHDECL")
/* Modula2 info "for imc": name,,0,0,0 according to Ultrix V4.0. */
__define_stab (N_MOD2, 0x50, "MOD2")
/* GNU C++ `catch' clause. Value is its address. Desc is nonzero if
this entry is immediately followed by a CAUGHT stab saying what exception
was caught. Multiple CAUGHT stabs means that multiple exceptions
can be caught here. If Desc is 0, it means all exceptions are caught
here. */
__define_stab (N_CATCH, 0x54, "CATCH")
/* Structure or union element. Value is offset in the structure. */
__define_stab (N_SSYM, 0x60, "SSYM")
/* Name of main source file.
Value is starting text address of the compilation. */
__define_stab (N_SO, 0x64, "SO")
/* Automatic variable in the stack. Value is offset from frame pointer.
Also used for type descriptions. */
__define_stab (N_LSYM, 0x80, "LSYM")
/* Beginning of an include file. Only Sun uses this.
In an object file, only the name is significant.
The Sun linker puts data into some of the other fields. */
__define_stab (N_BINCL, 0x82, "BINCL")
/* Name of sub-source file (#include file).
Value is starting text address of the compilation. */
__define_stab (N_SOL, 0x84, "SOL")
/* Parameter variable. Value is offset from argument pointer.
(On most machines the argument pointer is the same as the frame pointer. */
__define_stab (N_PSYM, 0xa0, "PSYM")
/* End of an include file. No name.
This and N_BINCL act as brackets around the file's output.
In an object file, there is no significant data in this entry.
The Sun linker puts data into some of the fields. */
__define_stab (N_EINCL, 0xa2, "EINCL")
/* Alternate entry point. Value is its address. */
__define_stab (N_ENTRY, 0xa4, "ENTRY")
/* Beginning of lexical block.
The desc is the nesting level in lexical blocks.
The value is the address of the start of the text for the block.
The variables declared inside the block *precede* the N_LBRAC symbol. */
__define_stab (N_LBRAC, 0xc0, "LBRAC")
/* Place holder for deleted include file. Replaces a N_BINCL and everything
up to the corresponding N_EINCL. The Sun linker generates these when
it finds multiple identical copies of the symbols from an include file.
This appears only in output from the Sun linker. */
__define_stab (N_EXCL, 0xc2, "EXCL")
/* Modula-2 scope information. Can someone say what info it contains? */
__define_stab (N_SCOPE, 0xc4, "SCOPE")
/* End of a lexical block. Desc matches the N_LBRAC's desc.
The value is the address of the end of the text for the block. */
__define_stab (N_RBRAC, 0xe0, "RBRAC")
/* Begin named common block. Only the name is significant. */
__define_stab (N_BCOMM, 0xe2, "BCOMM")
/* End named common block. Only the name is significant
(and it should match the N_BCOMM). */
__define_stab (N_ECOMM, 0xe4, "ECOMM")
/* End common (local name): value is address.
I'm not sure how this is used. */
__define_stab (N_ECOML, 0xe8, "ECOML")
/* These STAB's are used on Gould systems for Non-Base register symbols
or something like that. FIXME. I have assigned the values at random
since I don't have a Gould here. Fixups from Gould folk welcome... */
__define_stab (N_NBTEXT, 0xF0, "NBTEXT")
__define_stab (N_NBDATA, 0xF2, "NBDATA")
__define_stab (N_NBBSS, 0xF4, "NBBSS")
__define_stab (N_NBSTS, 0xF6, "NBSTS")
__define_stab (N_NBLCS, 0xF8, "NBLCS")
/* Second symbol entry containing a length-value for the preceding entry.
The value is the length. */
__define_stab (N_LENG, 0xfe, "LENG")
/* The above information, in matrix format.
STAB MATRIX
_________________________________________________
| 00 - 1F are not dbx stab symbols |
| In most cases, the low bit is the EXTernal bit|
| 00 UNDEF | 02 ABS | 04 TEXT | 06 DATA |
| 01 |EXT | 03 |EXT | 05 |EXT | 07 |EXT |
| 08 BSS | 0A INDR | 0C FN_SEQ | 0E |
| 09 |EXT | 0B | 0D | 0F |
| 10 | 12 COMM | 14 SETA | 16 SETT |
| 11 | 13 | 15 | 17 |
| 18 SETD | 1A SETB | 1C SETV | 1E WARNING|
| 19 | 1B | 1D | 1F FN |
|_______________________________________________|
| Debug entries with bit 01 set are unused. |
| 20 GSYM | 22 FNAME | 24 FUN | 26 STSYM |
| 28 LCSYM | 2A MAIN | 2C | 2E |
| 30 PC | 32 NSYMS | 34 NOMAP | 36 |
| 38 OBJ | 3A | 3C OPT | 3E |
| 40 RSYM | 42 M2C | 44 SLINE | 46 DSLINE |
| 48 BSLINE*| 4A DEFD | 4C | 4E |
| 50 EHDECL*| 52 | 54 CATCH | 56 |
| 58 | 5A | 5C | 5E |
| 60 SSYM | 62 | 64 SO | 66 |
| 68 | 6A | 6C | 6E |
| 70 | 72 | 74 | 76 |
| 78 | 7A | 7C | 7E |
| 80 LSYM | 82 BINCL | 84 SOL | 86 |
| 88 | 8A | 8C | 8E |
| 90 | 92 | 94 | 96 |
| 98 | 9A | 9C | 9E |
| A0 PSYM | A2 EINCL | A4 ENTRY | A6 |
| A8 | AA | AC | AE |
| B0 | B2 | B4 | B6 |
| B8 | BA | BC | BE |
| C0 LBRAC | C2 EXCL | C4 SCOPE | C6 |
| C8 | CA | CC | CE |
| D0 | D2 | D4 | D6 |
| D8 | DA | DC | DE |
| E0 RBRAC | E2 BCOMM | E4 ECOMM | E6 |
| E8 ECOML | EA | EC | EE |
| F0 | F2 | F4 | F6 |
| F8 | FA | FC | FE LENG |
+-----------------------------------------------+
* 50 EHDECL is also MOD2.
* 48 BSLINE is also BROWS.
*/

17
stab.h
View file

@ -1,17 +0,0 @@
#ifndef __GNU_STAB__
/* Indicate the GNU stab.h is in use. */
#define __GNU_STAB__
#define __define_stab(NAME, CODE, STRING) NAME=CODE,
enum __stab_debug_code
{
#include "stab.def"
LAST_UNUSED_STAB_CODE
};
#undef __define_stab
#endif /* __GNU_STAB_ */

339
tcc.c
View file

@ -1,339 +0,0 @@
/*
* TCC - Tiny C Compiler
*
* Copyright (c) 2001-2004 Fabrice Bellard
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include "tcc.h"
#include "tcctools.c"
static const char help[] =
"Tiny C Compiler "PACKAGE_VERSION" - Copyright (C) 2001-2006 Fabrice Bellard\n"
"Usage: tcc [options...] [-o outfile] [-c] infile(s)...\n"
" tcc [options...] -run infile (or --) [arguments...]\n"
"General options:\n"
" -c compile only - generate an object file\n"
" -o outfile set output filename\n"
" -run run compiled source\n"
" -fflag set or reset (with 'no-' prefix) 'flag' (see tcc -hh)\n"
" -Wwarning set or reset (with 'no-' prefix) 'warning' (see tcc -hh)\n"
" -w disable all warnings\n"
" -v --version show version\n"
" -vv show search paths or loaded files\n"
" -h -hh show this, show more help\n"
" -bench show compilation statistics\n"
" - use stdin pipe as infile\n"
" @listfile read arguments from listfile\n"
"Preprocessor options:\n"
" -Idir add include path 'dir'\n"
" -Dsym[=val] define 'sym' with value 'val'\n"
" -Usym undefine 'sym'\n"
" -E preprocess only\n"
"Linker options:\n"
" -Ldir add library path 'dir'\n"
" -llib link with dynamic or static library 'lib'\n"
" -r generate (relocatable) object file\n"
" -shared generate a shared library/dll\n"
" -rdynamic export all global symbols to dynamic linker\n"
" -soname set name for shared library to be used at runtime\n"
" -Wl,-opt[=val] set linker option (see tcc -hh)\n"
"Debugger options:\n"
" -g generate stab runtime debug info\n"
" -gdwarf[-x] generate dwarf runtime debug info\n"
#ifdef CONFIG_TCC_BCHECK
" -b compile with built-in memory and bounds checker (implies -g)\n"
#endif
#ifdef CONFIG_TCC_BACKTRACE
" -bt[N] link with backtrace (stack dump) support [show max N callers]\n"
#endif
"Misc. options:\n"
" -std=version define __STDC_VERSION__ according to version (c11/gnu11)\n"
" -x[c|a|b|n] specify type of the next infile (C,ASM,BIN,NONE)\n"
" -nostdinc do not use standard system include paths\n"
" -nostdlib do not link with standard crt and libraries\n"
" -Bdir set tcc's private include/library dir\n"
" -M[M]D generate make dependency file [ignore system files]\n"
" -M[M] as above but no other output\n"
" -MF file specify dependency file name\n"
"Tools:\n"
" create library : tcc -ar [crstvx] lib [files]\n"
;
static const char help2[] =
"Tiny C Compiler "PACKAGE_VERSION" - More Options\n"
"Special options:\n"
" -P -P1 with -E: no/alternative #line output\n"
" -dD -dM with -E: output #define directives\n"
" -pthread same as -D_REENTRANT and -lpthread\n"
" -On same as -D__OPTIMIZE__ for n > 0\n"
" -Wp,-opt same as -opt\n"
" -include file include 'file' above each input file\n"
" -isystem dir add 'dir' to system include path\n"
" -static link to static libraries (not recommended)\n"
" -dumpversion print version\n"
" -print-search-dirs print search paths\n"
" -dt with -run/-E: auto-define 'test_...' macros\n"
"Ignored options:\n"
" -arch -C --param -pedantic -pipe -s -traditional\n"
"-W[no-]... warnings:\n"
" all turn on some (*) warnings\n"
" error[=warning] stop after warning (any or specified)\n"
" write-strings strings are const\n"
" unsupported warn about ignored options, pragmas, etc.\n"
" implicit-function-declaration warn for missing prototype (*)\n"
" discarded-qualifiers warn when const is dropped (*)\n"
"-f[no-]... flags:\n"
" unsigned-char default char is unsigned\n"
" signed-char default char is signed\n"
" common use common section instead of bss\n"
" leading-underscore decorate extern symbols\n"
" ms-extensions allow anonymous struct in struct\n"
" dollars-in-identifiers allow '$' in C symbols\n"
" reverse-funcargs evaluate function arguments right to left\n"
" gnu89-inline 'extern inline' is like 'static inline'\n"
" asynchronous-unwind-tables create eh_frame section [on]\n"
" test-coverage create code coverage code\n"
"-m... target specific options:\n"
" ms-bitfields use MSVC bitfield layout\n"
"-Wl,... linker options:\n"
" -nostdlib do not link with standard crt/libs\n"
" -[no-]whole-archive load lib(s) fully/only as needed\n"
" -export-all-symbols same as -rdynamic\n"
" -export-dynamic same as -rdynamic\n"
" -image-base= -Ttext= set base address of executable\n"
" -section-alignment= set section alignment in executable\n"
" -rpath= set dynamic library search path\n"
" -enable-new-dtags set DT_RUNPATH instead of DT_RPATH\n"
" -soname= set DT_SONAME elf tag\n"
" -Bsymbolic set DT_SYMBOLIC elf tag\n"
" -oformat=[elf32/64-* binary] set executable output format\n"
" -init= -fini= -Map= -as-needed -O (ignored)\n"
"Predefined macros:\n"
" tcc -E -dM - < /dev/null\n"
"See also the manual for more details.\n"
;
static const char version[] =
"tcc version "PACKAGE_VERSION
" (i386)\n"
;
static void print_dirs(const char *msg, char **paths, int nb_paths)
{
int i;
printf("%s:\n%s", msg, nb_paths ? "" : " -\n");
for(i = 0; i < nb_paths; i++)
printf(" %s\n", paths[i]);
}
static void print_search_dirs(TCCState *s)
{
printf("install: %s\n", s->tcc_lib_path);
/* print_dirs("programs", NULL, 0); */
print_dirs("include", s->sysinclude_paths, s->nb_sysinclude_paths);
print_dirs("libraries", s->library_paths, s->nb_library_paths);
printf("libtcc1:\n %s/%s\n", s->library_paths[0], CONFIG_TCC_CROSSPREFIX TCC_LIBTCC1);
print_dirs("crt", s->crt_paths, s->nb_crt_paths);
printf("elfinterp:\n %s\n", DEFAULT_ELFINTERP(s));
}
static void set_environment(TCCState *s)
{
char * path;
path = getenv("C_INCLUDE_PATH");
if(path != NULL) {
tcc_add_sysinclude_path(s, path);
}
path = getenv("CPATH");
if(path != NULL) {
tcc_add_include_path(s, path);
}
path = getenv("LIBRARY_PATH");
if(path != NULL) {
tcc_add_library_path(s, path);
}
}
static char *default_outputfile(TCCState *s, const char *first_file)
{
char buf[1024];
char *ext;
const char *name = "a";
if (first_file && strcmp(first_file, "-"))
name = tcc_basename(first_file);
snprintf(buf, sizeof(buf), "%s", name);
ext = tcc_fileextension(buf);
if ((s->just_deps || s->output_type == TCC_OUTPUT_OBJ) && !s->option_r && *ext)
strcpy(ext, ".obj");
else
strcpy(buf, "a.out");
return tcc_strdup(buf);
}
static unsigned getclock_ms(void)
{
#ifdef _WIN32
return GetTickCount();
#else
struct timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_sec*1000 + (tv.tv_usec+500)/1000;
#endif
}
int main(int argc0, char **argv0)
{
TCCState *s, *s1;
int ret, opt, n = 0, t = 0, done;
unsigned start_time = 0, end_time = 0;
const char *first_file;
int argc; char **argv;
FILE *ppfp = stdout;
redo:
argc = argc0, argv = argv0;
s = s1 = tcc_new();
#ifdef CONFIG_TCC_SWITCHES /* predefined options */
tcc_set_options(s, CONFIG_TCC_SWITCHES);
#endif
opt = tcc_parse_args(s, &argc, &argv, 1);
if (opt < 0)
return 1;
if (n == 0) {
if (opt == OPT_HELP) {
fputs(help, stdout);
if (!s->verbose)
return 0;
++opt;
}
if (opt == OPT_HELP2) {
fputs(help2, stdout);
return 0;
}
if (opt == OPT_M32 || opt == OPT_M64)
return tcc_tool_cross(s, argv, opt);
if (s->verbose)
printf("%s", version);
if (opt == OPT_AR)
return tcc_tool_ar(s, argc, argv);
if (opt == OPT_V)
return 0;
if (opt == OPT_PRINT_DIRS) {
/* initialize search dirs */
set_environment(s);
tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
print_search_dirs(s);
return 0;
}
if (s->nb_files == 0) {
tcc_error_noabort("no input files");
} else if (s->output_type == TCC_OUTPUT_PREPROCESS) {
if (s->outfile && 0!=strcmp("-",s->outfile)) {
ppfp = fopen(s->outfile, "wb");
if (!ppfp)
tcc_error_noabort("could not write '%s'", s->outfile);
}
} else if (s->output_type == TCC_OUTPUT_OBJ && !s->option_r) {
if (s->nb_libraries)
tcc_error_noabort("cannot specify libraries with -c");
else if (s->nb_files > 1 && s->outfile)
tcc_error_noabort("cannot specify output file with -c many files");
}
if (s->nb_errors)
return 1;
if (s->do_bench)
start_time = getclock_ms();
}
set_environment(s);
if (s->output_type == 0)
s->output_type = TCC_OUTPUT_EXE;
tcc_set_output_type(s, s->output_type);
s->ppfp = ppfp;
if ((s->output_type == TCC_OUTPUT_MEMORY
|| s->output_type == TCC_OUTPUT_PREPROCESS)
&& (s->dflag & 16)) { /* -dt option */
if (t)
s->dflag |= 32;
s->run_test = ++t;
if (n)
--n;
}
/* compile or add each files or library */
first_file = NULL;
do {
struct filespec *f = s->files[n];
s->filetype = f->type;
if (f->type & AFF_TYPE_LIB) {
ret = tcc_add_library(s, f->name);
} else {
if (1 == s->verbose)
printf("-> %s\n", f->name);
if (!first_file)
first_file = f->name;
ret = tcc_add_file(s, f->name);
}
} while (++n < s->nb_files
&& 0 == ret
&& (s->output_type != TCC_OUTPUT_OBJ || s->option_r));
if (s->do_bench)
end_time = getclock_ms();
if (s->run_test) {
t = 0;
} else if (s->output_type == TCC_OUTPUT_PREPROCESS) {
;
} else if (0 == ret) {
if (s->output_type == TCC_OUTPUT_MEMORY) {
} else {
if (!s->outfile)
s->outfile = default_outputfile(s, first_file);
if (!s->just_deps)
ret = tcc_output_file(s, s->outfile);
if (!ret && s->gen_deps)
gen_makedeps(s, s->outfile, s->deps_outfile);
}
}
done = 1;
if (t)
done = 0; /* run more tests with -dt -run */
else if (ret) {
if (s->nb_errors)
ret = 1;
/* else keep the original exit code from tcc_run() */
} else if (n < s->nb_files)
done = 0; /* compile more files with -c */
else if (s->do_bench)
tcc_print_stats(s, end_time - start_time);
tcc_delete(s);
if (!done)
goto redo;
if (ppfp && ppfp != stdout)
fclose(ppfp);
return ret;
}

5
tcc/Makefile.am Normal file
View file

@ -0,0 +1,5 @@
bin_PROGRAMS = tcc
tcc_SOURCES = tcc.c tcctools.c
tcc_LDADD = ../libtcc/libtcc.a
tcc_CPPFLAGS = -I$(top_srcdir)

314
tcc/tcc.c Normal file
View file

@ -0,0 +1,314 @@
/*
* TCC - Tiny C Compiler
*
* Copyright (c) 2001-2004 Fabrice Bellard
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include "libtcc/tcc.h"
#include "tcctools.h"
static const char HELP_STR[] =
"Tiny C Compiler "PACKAGE_VERSION" - Copyright (C) 2001-2006 Fabrice Bellard\n"
"Usage: tcc [options...] [-o outfile] [-c] infile(s)...\n"
" tcc [options...] -run infile (or --) [arguments...]\n"
"General options:\n"
" -c compile only - generate an object file\n"
" -o outfile set output filename\n"
" -run run compiled source\n"
" -fflag set or reset (with 'no-' prefix) 'flag' (see tcc -hh)\n"
" -Wwarning set or reset (with 'no-' prefix) 'warning' (see tcc -hh)\n"
" -w disable all warnings\n"
" -v --version show version\n"
" -vv show search paths or loaded files\n"
" -h -hh show this, show more help\n"
" -bench show compilation statistics\n"
" - use stdin pipe as infile\n"
" @listfile read arguments from listfile\n"
"Preprocessor options:\n"
" -Idir add include path 'dir'\n"
" -Dsym[=val] define 'sym' with value 'val'\n"
" -Usym undefine 'sym'\n"
" -E preprocess only\n"
"Linker options:\n"
" -Ldir add library path 'dir'\n"
" -llib link with dynamic or static library 'lib'\n"
" -r generate (relocatable) object file\n"
" -shared generate a shared library/dll\n"
" -rdynamic export all global symbols to dynamic linker\n"
" -soname set name for shared library to be used at runtime\n"
" -Wl,-opt[=val] set linker option (see tcc -hh)\n"
"Misc. options:\n"
" -std=version define __STDC_VERSION__ according to version (c11/gnu11)\n"
" -x[c|a|b|n] specify type of the next infile (C,ASM,BIN,NONE)\n"
" -nostdinc do not use standard system include paths\n"
" -nostdlib do not link with standard crt and libraries\n"
" -Bdir set tcc's private include/library dir\n"
" -M[M]D generate make dependency file [ignore system files]\n"
" -M[M] as above but no other output\n"
" -MF file specify dependency file name\n"
"Tools:\n"
" create library : tcc -ar [crstvx] lib [files]\n"
;
static const char HELP_MORE_STR[] =
"Tiny C Compiler "PACKAGE_VERSION" - More Options\n"
"Special options:\n"
" -P -P1 with -E: no/alternative #line output\n"
" -dD -dM with -E: output #define directives\n"
" -pthread same as -D_REENTRANT and -lpthread\n"
" -On same as -D__OPTIMIZE__ for n > 0\n"
" -Wp,-opt same as -opt\n"
" -include file include 'file' above each input file\n"
" -isystem dir add 'dir' to system include path\n"
" -static link to static libraries (not recommended)\n"
" -dumpversion print version\n"
" -print-search-dirs print search paths\n"
"Ignored options:\n"
" -arch -C --param -pedantic -pipe -s -traditional\n"
"-W[no-]... warnings:\n"
" all turn on some (*) warnings\n"
" error[=warning] stop after warning (any or specified)\n"
" write-strings strings are const\n"
" unsupported warn about ignored options, pragmas, etc.\n"
" implicit-function-declaration warn for missing prototype (*)\n"
" discarded-qualifiers warn when const is dropped (*)\n"
"-f[no-]... flags:\n"
" unsigned-char default char is unsigned\n"
" signed-char default char is signed\n"
" common use common section instead of bss\n"
" leading-underscore decorate extern symbols\n"
" ms-extensions allow anonymous struct in struct\n"
" dollars-in-identifiers allow '$' in C symbols\n"
" reverse-funcargs evaluate function arguments right to left\n"
" gnu89-inline 'extern inline' is like 'static inline'\n"
" asynchronous-unwind-tables create eh_frame section [on]\n"
"-m... target specific options:\n"
" ms-bitfields use MSVC bitfield layout\n"
"-Wl,... linker options:\n"
" -nostdlib do not link with standard crt/libs\n"
" -[no-]whole-archive load lib(s) fully/only as needed\n"
" -export-all-symbols same as -rdynamic\n"
" -export-dynamic same as -rdynamic\n"
" -image-base= -Ttext= set base address of executable\n"
" -section-alignment= set section alignment in executable\n"
" -rpath= set dynamic library search path\n"
" -enable-new-dtags set DT_RUNPATH instead of DT_RPATH\n"
" -soname= set DT_SONAME elf tag\n"
" -Bsymbolic set DT_SYMBOLIC elf tag\n"
" -oformat=[coff,binary] set executable output format\n"
" -init= -fini= -Map= -as-needed -O (ignored)\n"
"Predefined macros:\n"
" tcc -E -dM - < /dev/null\n"
"See also the manual for more details.\n"
;
static const char VERSION_STR[] =
"tcc version "PACKAGE_VERSION" (i386)\n";
static void print_dirs(const char *msg, char **paths, int nb_paths)
{
int i;
printf("%s:\n%s", msg, nb_paths ? "" : " -\n");
for(i = 0; i < nb_paths; i++)
printf(" %s\n", paths[i]);
}
static void print_search_dirs(TCCState *s)
{
printf("install: %s\n", s->tcc_lib_path);
/* print_dirs("programs", NULL, 0); */
print_dirs("include", s->sysinclude_paths, s->nb_sysinclude_paths);
print_dirs("libraries", s->library_paths, s->nb_library_paths);
printf("libtcc1:\n %s/%s\n", s->library_paths[0], CONFIG_TCC_CROSSPREFIX TCC_LIBTCC1);
print_dirs("crt", s->crt_paths, s->nb_crt_paths);
printf("elfinterp:\n %s\n", DEFAULT_ELFINTERP(s));
}
static void set_environment(TCCState *s)
{
char * path;
path = getenv("C_INCLUDE_PATH");
if(path != NULL) {
tcc_add_sysinclude_path(s, path);
}
path = getenv("CPATH");
if(path != NULL) {
tcc_add_include_path(s, path);
}
path = getenv("LIBRARY_PATH");
if(path != NULL) {
tcc_add_library_path(s, path);
}
}
static char *default_outputfile(TCCState *s, const char *first_file)
{
char buf[1024];
char *ext;
const char *name = "a";
if (first_file && strcmp(first_file, "-"))
name = tcc_basename(first_file);
snprintf(buf, sizeof(buf), "%s", name);
ext = tcc_fileextension(buf);
if ((s->just_deps || s->output_type == TCC_OUTPUT_OBJ) && !s->option_r && *ext)
strcpy(ext, ".obj");
else
strcpy(buf, "a.out");
return tcc_strdup(buf);
}
static unsigned getclock_ms(void)
{
#ifdef _WIN32
return GetTickCount();
#else
struct timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_sec*1000 + (tv.tv_usec+500)/1000;
#endif
}
int main(int argc0, char **argv0)
{
TCCState *s, *s1;
int ret, opt, n = 0, t = 0, done;
unsigned start_time = 0, end_time = 0;
const char *first_file;
int argc; char **argv;
FILE *ppfp = stdout;
redo:
argc = argc0, argv = argv0;
s = s1 = tcc_new();
#ifdef CONFIG_TCC_SWITCHES /* predefined options */
tcc_set_options(s, CONFIG_TCC_SWITCHES);
#endif
opt = tcc_parse_args(s, &argc, &argv, 1);
if (opt < 0)
return 1;
if (n == 0) {
if (opt == OPT_HELP) {
fputs(HELP_STR, stdout);
if (!s->verbose)
return 0;
++opt;
}
if (opt == OPT_HELP2) {
fputs(HELP_MORE_STR, stdout);
return 0;
}
if (opt == OPT_M32 || opt == OPT_M64)
return tcc_tool_cross(s, argv, opt);
if (s->verbose)
printf("%s", VERSION_STR);
if (opt == OPT_AR)
return tcc_tool_ar(s, argc, argv);
if (opt == OPT_V)
return 0;
if (opt == OPT_PRINT_DIRS) {
/* initialize search dirs */
set_environment(s);
tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
print_search_dirs(s);
return 0;
}
if (s->nb_files == 0) {
tcc_error_noabort("no input files");
} else if (s->output_type == TCC_OUTPUT_PREPROCESS) {
if (s->outfile && 0!=strcmp("-",s->outfile)) {
ppfp = fopen(s->outfile, "wb");
if (!ppfp)
tcc_error_noabort("could not write '%s'", s->outfile);
}
} else if (s->output_type == TCC_OUTPUT_OBJ && !s->option_r) {
if (s->nb_libraries)
tcc_error_noabort("cannot specify libraries with -c");
else if (s->nb_files > 1 && s->outfile)
tcc_error_noabort("cannot specify output file with -c many files");
}
if (s->nb_errors)
return 1;
if (s->do_bench)
start_time = getclock_ms();
}
set_environment(s);
if (s->output_type == 0)
s->output_type = TCC_OUTPUT_EXE;
tcc_set_output_type(s, s->output_type);
s->ppfp = ppfp;
/* compile or add each files or library */
first_file = NULL;
do {
struct filespec *f = s->files[n];
s->filetype = f->type;
if (f->type & AFF_TYPE_LIB) {
ret = tcc_add_library(s, f->name);
} else {
if (1 == s->verbose)
printf("-> %s\n", f->name);
if (!first_file)
first_file = f->name;
ret = tcc_add_file(s, f->name);
}
} while (++n < s->nb_files
&& 0 == ret
&& (s->output_type != TCC_OUTPUT_OBJ || s->option_r));
if (s->do_bench)
end_time = getclock_ms();
if (s->output_type == TCC_OUTPUT_PREPROCESS) {
;
} else if (0 == ret) {
if (s->output_type == TCC_OUTPUT_MEMORY) {
} else {
if (!s->outfile)
s->outfile = default_outputfile(s, first_file);
if (!s->just_deps)
ret = tcc_output_file(s, s->outfile);
if (!ret && s->gen_deps)
gen_makedeps(s, s->outfile, s->deps_outfile);
}
}
done = 1;
if (t)
done = 0; /* run more tests with -dt -run */
else if (ret) {
if (s->nb_errors)
ret = 1;
/* else keep the original exit code from tcc_run() */
} else if (n < s->nb_files)
done = 0; /* compile more files with -c */
else if (s->do_bench)
tcc_print_stats(s, end_time - start_time);
tcc_delete(s);
if (!done)
goto redo;
if (ppfp && ppfp != stdout)
fclose(ppfp);
return ret;
}

134
tcc/tcc_new.c Normal file
View file

@ -0,0 +1,134 @@
/*
* TCC - Tiny C Compiler
*
* Copyright (c) 2001-2004 Fabrice Bellard
* Copyright (c) 2025 d0p1
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdlib.h>
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif /* HAVE_CONFIG_H */
#include "libtcc.h"
static const char help_str[] =
"Tiny C Compiler "PACKAGE_VERSION" - Copyright (C) 2001-2006 Fabrice Bellard\n"
"Usage: tcc [options...] [-o outfile] [-c] infile(s)...\n"
"General options:\n"
" -c compile only - generate an object file\n"
" -o outfile set output filename\n"
" -run run compiled source\n"
" -fflag set or reset (with 'no-' prefix) 'flag' (see tcc -hh)\n"
" -Wwarning set or reset (with 'no-' prefix) 'warning' (see tcc -hh)\n"
" -w disable all warnings\n"
" -v --version show version\n"
" -vv show search paths or loaded files\n"
" -h -hh show this, show more help\n"
" -bench show compilation statistics\n"
" - use stdin pipe as infile\n"
" @listfile read arguments from listfile\n"
"Preprocessor options:\n"
" -Idir add include path 'dir'\n"
" -Dsym[=val] define 'sym' with value 'val'\n"
" -Usym undefine 'sym'\n"
" -E preprocess only\n"
"Linker options:\n"
" -Ldir add library path 'dir'\n"
" -llib link with dynamic or static library 'lib'\n"
" -r generate (relocatable) object file\n"
" -rdynamic export all global symbols to dynamic linker\n"
" -soname set name for shared library to be used at runtime\n"
" -Wl,-opt[=val] set linker option (see tcc -hh)\n"
"Debugger options:\n"
" -g generate stab runtime debug info\n"
" -gdwarf[-x] generate dwarf runtime debug info\n"
"Misc. options:\n"
" -std=version define __STDC_VERSION__ according to version (c11/gnu11)\n"
" -x[c|a|b|n] specify type of the next infile (C,ASM,BIN,NONE)\n"
" -nostdinc do not use standard system include paths\n"
" -nostdlib do not link with standard crt and libraries\n"
" -Bdir set tcc's private include/library dir\n"
" -M[M]D generate make dependency file [ignore system files]\n"
" -M[M] as above but no other output\n"
" -MF file specify dependency file name\n"
"Tools:\n"
" create library : tcc -ar [crstvx] lib [files]\n"
;
static const char help_more_str[] =
"Tiny C Compiler "PACKAGE_VERSION" - More Options\n"
"Special options:\n"
" -P -P1 with -E: no/alternative #line output\n"
" -dD -dM with -E: output #define directives\n"
" -pthread same as -D_REENTRANT and -lpthread\n"
" -On same as -D__OPTIMIZE__ for n > 0\n"
" -Wp,-opt same as -opt\n"
" -include file include 'file' above each input file\n"
" -isystem dir add 'dir' to system include path\n"
" -static link to static libraries (not recommended)\n"
" -dumpversion print version\n"
" -print-search-dirs print search paths\n"
" -dt with -run/-E: auto-define 'test_...' macros\n"
"Ignored options:\n"
" -arch -C --param -pedantic -pipe -s -traditional\n"
"-W[no-]... warnings:\n"
" all turn on some (*) warnings\n"
" error[=warning] stop after warning (any or specified)\n"
" write-strings strings are const\n"
" unsupported warn about ignored options, pragmas, etc.\n"
" implicit-function-declaration warn for missing prototype (*)\n"
" discarded-qualifiers warn when const is dropped (*)\n"
"-f[no-]... flags:\n"
" unsigned-char default char is unsigned\n"
" signed-char default char is signed\n"
" common use common section instead of bss\n"
" leading-underscore decorate extern symbols\n"
" ms-extensions allow anonymous struct in struct\n"
" dollars-in-identifiers allow '$' in C symbols\n"
" reverse-funcargs evaluate function arguments right to left\n"
" gnu89-inline 'extern inline' is like 'static inline'\n"
" asynchronous-unwind-tables create eh_frame section [on]\n"
" test-coverage create code coverage code\n"
"-m... target specific options:\n"
" ms-bitfields use MSVC bitfield layout\n"
"-Wl,... linker options:\n"
" -nostdlib do not link with standard crt/libs\n"
" -[no-]whole-archive load lib(s) fully/only as needed\n"
" -export-all-symbols same as -rdynamic\n"
" -export-dynamic same as -rdynamic\n"
" -image-base= -Ttext= set base address of executable\n"
" -section-alignment= set section alignment in executable\n"
" -rpath= set dynamic library search path\n"
" -enable-new-dtags set DT_RUNPATH instead of DT_RPATH\n"
" -soname= set DT_SONAME elf tag\n"
" -Bsymbolic set DT_SYMBOLIC elf tag\n"
" -oformat=[coff,binary] set executable output format\n"
" -init= -fini= -Map= -as-needed -O (ignored)\n"
"Predefined macros:\n"
" tcc -E -dM - < /dev/null\n"
"See also the manual for more details.\n"
;
static const char version_str[] = "tcc version "PACKAGE_VERSION" (i386)\n";
int
main(int argc, char *argv[])
{
TCCState *s;
}

View file

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

10
tcc/tcctools.h Normal file
View file

@ -0,0 +1,10 @@
#ifndef TCC_TCCTOOLS_H
# define TCC_TCCTOOLS_H 1
# include "libtcc/libtcc.h"
int tcc_tool_ar(TCCState *s1, int argc, char **argv);
int tcc_tool_cross(TCCState *s1, char **argv, int target);
int gen_makedeps(TCCState *s1, const char *target, const char *filename);
#endif /* !TCC_TCCTOOLS_H */

2482
tccdbg.c

File diff suppressed because it is too large Load diff

2480
tccmacho.c

File diff suppressed because it is too large Load diff