Refactor and remove code (tccdbg, tccmacho, ...)
This commit is contained in:
parent
05611e2658
commit
f08ef63153
60 changed files with 1887 additions and 8579 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -15,7 +15,7 @@
|
|||
.gdb_history
|
||||
a.out
|
||||
tcc_g
|
||||
tcc
|
||||
tcc/tcc
|
||||
tcc_c
|
||||
tcc_p
|
||||
*-tcc
|
||||
|
@ -77,3 +77,5 @@ stamp-h1
|
|||
*.cache
|
||||
.deps
|
||||
build-aux
|
||||
configure
|
||||
.dirstamp
|
|
@ -72,7 +72,7 @@ User interface:
|
|||
- -pthread option (same as -D_REENTRANT -lpthread) (Henry Kroll III)
|
||||
- -m32/-m64 to re-exec cross compiler (Henry Kroll III)
|
||||
- -Wl, Mimic all GNU -option forms supported by ld (Kirill Smelkov)
|
||||
- new LIBTCCAPI tcc_set_options() (grischka)
|
||||
- new tcc_set_options() (grischka)
|
||||
|
||||
Platforms:
|
||||
- Many improvements for x86-64 target (Shinichiro Hamaji, Michael Matz, grischka)
|
||||
|
|
11
Makefile.am
11
Makefile.am
|
@ -1,12 +1,3 @@
|
|||
AM_CFLAGS =
|
||||
|
||||
|
||||
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)
|
||||
SUBDIRS = libtcc tcc
|
||||
|
|
3
compile_flags.txt
Normal file
3
compile_flags.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
-I.
|
||||
-DHAVE_CONFIG_H
|
||||
-Ilibtcc
|
|
@ -7,7 +7,10 @@ AC_CONFIG_AUX_DIR([build-aux])
|
|||
AM_INIT_AUTOMAKE([foreign subdir-objects -Werror -Wall])
|
||||
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_CONFIG_FILES([Makefile])
|
||||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
libtcc/Makefile
|
||||
tcc/Makefile])
|
||||
|
||||
AC_LANG([C])
|
||||
AC_PROG_CC
|
||||
|
|
105
lib/Makefile
105
lib/Makefile
|
@ -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
116
libtcc.h
|
@ -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
6
libtcc/Makefile.am
Normal 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
|
|
@ -2,7 +2,8 @@
|
|||
/* COFF.H */
|
||||
/* COFF data structures and related definitions used by the linker */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef COFF_H
|
||||
# define COFF_H 1
|
||||
# include <stdint.h>
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
@ -389,3 +390,5 @@ union auxent
|
|||
#define _DORIGIN "_dorigin"
|
||||
|
||||
#define _SORIGIN "_sorigin"
|
||||
|
||||
#endif /* COFF_H */
|
|
@ -141,9 +141,6 @@ static const uint8_t reg_to_size[9] = {
|
|||
[OP_REG8] = 0,
|
||||
[OP_REG16] = 1,
|
||||
[OP_REG32] = 2,
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
[OP_REG64] = 3,
|
||||
#endif
|
||||
*/
|
||||
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_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 */
|
||||
{ 0, },
|
||||
};
|
||||
|
@ -216,7 +213,7 @@ static const uint16_t op0_codes[] = {
|
|||
#define DEF_ASM_OP1(name, opcode, group, instr_type, op0)
|
||||
#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1)
|
||||
#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)
|
||||
|
@ -1293,11 +1290,6 @@ ST_FUNC void subst_asm_operand(CString *add_str,
|
|||
size = 1;
|
||||
else if ((sv->type.t & VT_BTYPE) == VT_SHORT)
|
||||
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
|
||||
size = 4;
|
||||
if (size == 1 && reg >= 4)
|
|
@ -99,13 +99,6 @@ ST_DATA const int reg_classes[NB_REGS] = {
|
|||
|
||||
static unsigned long func_sub_sp_offset;
|
||||
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 ? */
|
||||
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 */
|
||||
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;
|
||||
Sym *func_sym;
|
||||
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
if (tcc_state->do_bounds_check)
|
||||
gbound_args(nb_args);
|
||||
#endif
|
||||
|
||||
args_size = 0;
|
||||
for(i = 0;i < nb_args; i++) {
|
||||
if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
|
||||
|
@ -591,10 +568,6 @@ ST_FUNC void gfunc_prolog(Sym *func_sym)
|
|||
func_ret_sub = 4;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
if (tcc_state->do_bounds_check)
|
||||
gen_bounds_prolog();
|
||||
#endif
|
||||
}
|
||||
|
||||
/* generate function epilog */
|
||||
|
@ -602,11 +575,6 @@ ST_FUNC void gfunc_epilog(void)
|
|||
{
|
||||
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 */
|
||||
v = (-loc + 3) & -4;
|
||||
|
||||
|
@ -1043,55 +1011,6 @@ ST_FUNC void ggoto(void)
|
|||
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 */
|
||||
ST_FUNC void gen_vla_sp_save(int addr) {
|
||||
/* 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) {
|
||||
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 */
|
||||
use_call = 1;
|
||||
#endif
|
|
@ -99,10 +99,6 @@ ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_
|
|||
int modrm;
|
||||
unsigned plt_offset, relofs;
|
||||
|
||||
/* on i386 if we build a DLL, we add a %ebx offset */
|
||||
if (s1->output_type & TCC_OUTPUT_DYN)
|
||||
modrm = 0xa3;
|
||||
else
|
||||
modrm = 0x25;
|
||||
|
||||
/* empty PLT: create PLT0 entry that pushes the library identifier
|
||||
|
@ -148,7 +144,7 @@ ST_FUNC void relocate_plt(TCCState *s1)
|
|||
p = s1->plt->data;
|
||||
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 + 8, s1->got->sh_addr);
|
||||
p += 16;
|
||||
|
@ -179,31 +175,9 @@ ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
|
|||
|
||||
switch (type) {
|
||||
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);
|
||||
return;
|
||||
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);
|
||||
return;
|
||||
case R_386_PLT32:
|
|
@ -266,7 +266,7 @@
|
|||
#define DEF_ASM_OP1(name, opcode, group, instr_type, op0)
|
||||
#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1)
|
||||
#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2)
|
||||
#include "i386-asm.h"
|
||||
#include "asm.h"
|
||||
|
||||
#define ALT(x)
|
||||
#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_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)
|
||||
#include "i386-asm.h"
|
||||
#include "asm.h"
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
|
||||
#include "tcc.h"
|
||||
#include "utils/string.h"
|
||||
|
||||
/********************************************************/
|
||||
/* global variables */
|
||||
|
@ -78,44 +79,6 @@ PUB_FUNC void tcc_exit_state(TCCState *s1)
|
|||
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 */
|
||||
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 */
|
||||
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;
|
||||
}
|
||||
|
@ -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_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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
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 */
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
LIBTCCAPI TCCState *tcc_new(void)
|
||||
TCCState *tcc_new(void)
|
||||
{
|
||||
TCCState *s;
|
||||
|
||||
|
@ -779,7 +742,7 @@ LIBTCCAPI TCCState *tcc_new(void)
|
|||
return s;
|
||||
}
|
||||
|
||||
LIBTCCAPI void tcc_delete(TCCState *s1)
|
||||
void tcc_delete(TCCState *s1)
|
||||
{
|
||||
/* free sections */
|
||||
tccelf_delete(s1);
|
||||
|
@ -808,7 +771,6 @@ LIBTCCAPI void tcc_delete(TCCState *s1)
|
|||
cstr_free(&s1->cmdline_defs);
|
||||
cstr_free(&s1->cmdline_incl);
|
||||
cstr_free(&s1->linker_arg);
|
||||
tcc_free(s1->dState);
|
||||
/* free loaded dlls array */
|
||||
dynarray_reset(&s1->loaded_dlls, &s1->nb_loaded_dlls);
|
||||
tcc_free(s1);
|
||||
|
@ -817,12 +779,8 @@ LIBTCCAPI void tcc_delete(TCCState *s1)
|
|||
#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;
|
||||
|
||||
if (!s->nostdinc) {
|
||||
|
@ -832,7 +790,6 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
|
|||
}
|
||||
|
||||
if (output_type == TCC_OUTPUT_PREPROCESS) {
|
||||
s->do_debug = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -854,13 +811,13 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
|
|||
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);
|
||||
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);
|
||||
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));
|
||||
break;
|
||||
|
||||
#ifdef TCC_TARGET_PE
|
||||
default:
|
||||
ret = pe_load_file(s1, fd, filename);
|
||||
goto check_success;
|
||||
case AFF_BINTYPE_COFF:
|
||||
ret = coff_load_file(s1, fd, filename);
|
||||
break;
|
||||
|
||||
#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:
|
||||
if (s1->output_type == TCC_OUTPUT_MEMORY) {
|
||||
} else
|
||||
|
@ -980,20 +902,9 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
|
|||
default:
|
||||
/* as GNU ld, consider it is an ld script if not recognized */
|
||||
ret = tcc_load_ldscript(s1, fd);
|
||||
goto check_success;
|
||||
|
||||
#endif /* pe / macos / unix */
|
||||
|
||||
check_success:
|
||||
if (ret < 0)
|
||||
tcc_error_noabort("%s: unrecognized file type", filename);
|
||||
break;
|
||||
|
||||
#ifdef TCC_TARGET_COFF
|
||||
case AFF_BINTYPE_C67:
|
||||
ret = tcc_load_coff(s1, fd);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
close(fd);
|
||||
} else {
|
||||
|
@ -1030,12 +941,12 @@ static int guess_filetype(const char *filename)
|
|||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
#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)
|
||||
{
|
||||
return tcc_add_library_internal(s1, "%s/%s",
|
||||
|
@ -1083,7 +994,7 @@ ST_FUNC int tcc_add_crt(TCCState *s1, const char *filename)
|
|||
#endif
|
||||
|
||||
/* 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 };
|
||||
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]);
|
||||
}
|
||||
|
||||
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];
|
||||
if (s1->leading_underscore) {
|
||||
|
@ -1118,7 +1029,7 @@ LIBTCCAPI int tcc_add_symbol(TCCState *s1, const char *name, const void *val)
|
|||
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);
|
||||
s->tcc_lib_path = tcc_strdup(path);
|
||||
|
@ -1393,13 +1304,6 @@ static const TCCOption tcc_options[] = {
|
|||
{ "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
|
||||
{ "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG },
|
||||
{ "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 },
|
||||
{ "dumpmachine", TCC_OPTION_dumpmachine, 0},
|
||||
{ "dumpversion", TCC_OPTION_dumpversion, 0},
|
||||
|
@ -1435,6 +1339,7 @@ static const TCCOption tcc_options[] = {
|
|||
{ "ar", TCC_OPTION_ar, 0},
|
||||
/* ignored (silently, except after -Wunsupported) */
|
||||
{ "arch", 0, TCC_OPTION_HAS_ARG},
|
||||
{ "g", 0, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP},
|
||||
{ "C", 0, 0 },
|
||||
{ "-param", 0, TCC_OPTION_HAS_ARG },
|
||||
{ "pedantic", 0, 0 },
|
||||
|
@ -1470,7 +1375,6 @@ static const FlagDef options_f[] = {
|
|||
{ offsetof(TCCState, leading_underscore), 0, "leading-underscore" },
|
||||
{ offsetof(TCCState, ms_extensions), 0, "ms-extensions" },
|
||||
{ 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, gnu89_inline), 0, "gnu89-inline" },
|
||||
{ offsetof(TCCState, unwind_tables), 0, "asynchronous-unwind-tables" },
|
||||
|
@ -1675,32 +1579,6 @@ dorun:
|
|||
case TCC_OPTION_bench:
|
||||
s->do_bench = 1;
|
||||
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:
|
||||
x = TCC_OUTPUT_OBJ;
|
||||
set_output_type:
|
||||
|
@ -1713,8 +1591,6 @@ dorun:
|
|||
s->dflag = 3;
|
||||
else if (*optarg == 'M')
|
||||
s->dflag = 7;
|
||||
else if (*optarg == 't')
|
||||
s->dflag = 16;
|
||||
else if (isnum(*optarg))
|
||||
s->g_debug |= atoi(optarg);
|
||||
else
|
||||
|
@ -1727,9 +1603,6 @@ dorun:
|
|||
if (strcmp(optarg, "=c11") == 0 || strcmp(optarg, "=gnu11") == 0)
|
||||
s->cversion = 201112;
|
||||
break;
|
||||
case TCC_OPTION_shared:
|
||||
x = TCC_OUTPUT_DLL;
|
||||
goto set_output_type;
|
||||
case TCC_OPTION_soname:
|
||||
s->soname = tcc_strdup(optarg);
|
||||
break;
|
||||
|
@ -1885,7 +1758,7 @@ unsupported_option:
|
|||
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;
|
||||
int argc = 0, ret;
|
||||
|
@ -1913,15 +1786,6 @@ PUB_FUNC void tcc_print_stats(TCCState *s1, unsigned total_time)
|
|||
);
|
||||
#ifdef MEM_DEBUG
|
||||
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);
|
||||
#endif
|
||||
}
|
179
libtcc/libtcc.h
Normal file
179
libtcc/libtcc.h
Normal 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
35
libtcc/object/archive.h
Normal 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
69
libtcc/object/coff.h
Normal 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
2
libtcc/option.c
Normal file
|
@ -0,0 +1,2 @@
|
|||
#include "tcc.h"
|
||||
|
6
libtcc/option.h
Normal file
6
libtcc/option.h
Normal 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 */
|
|
@ -69,7 +69,7 @@ extern long double strtold (const char *__nptr, char **__endptr);
|
|||
# define strtoull _strtoui64
|
||||
# endif
|
||||
# ifdef LIBTCC_AS_DLL
|
||||
# define LIBTCCAPI __declspec(dllexport)
|
||||
# define __declspec(dllexport)
|
||||
# define PUB_FUNC LIBTCCAPI
|
||||
# endif
|
||||
# ifdef _MSC_VER
|
||||
|
@ -138,29 +138,8 @@ extern long double strtold (const char *__nptr, char **__endptr);
|
|||
/* assembler 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
|
||||
|
||||
#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
|
||||
# define CONFIG_TCC_PIC 1
|
||||
#endif
|
||||
|
@ -231,14 +210,6 @@ extern long double strtold (const char *__nptr, char **__endptr);
|
|||
# define CONFIG_TCC_ELFINTERP "/lib/ld.so"
|
||||
# elif defined(TCC_TARGET_PE)
|
||||
# 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
|
||||
# define CONFIG_TCC_ELFINTERP "/lib/ld-linux.so.2"
|
||||
# endif
|
||||
|
@ -268,8 +239,7 @@ extern long double strtold (const char *__nptr, char **__endptr);
|
|||
|
||||
#include "libtcc.h"
|
||||
#include "elf.h"
|
||||
#include "stab.h"
|
||||
#include "dwarf.h"
|
||||
#include "coff.h"
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
|
@ -290,8 +260,8 @@ extern long double strtold (const char *__nptr, char **__endptr);
|
|||
/* include the target specific definitions */
|
||||
|
||||
#define TARGET_DEFS_ONLY
|
||||
# include "i386-gen.c"
|
||||
# include "i386-link.c"
|
||||
# include "i386/gen.c"
|
||||
# include "i386/link.c"
|
||||
#undef TARGET_DEFS_ONLY
|
||||
|
||||
# define ELFCLASSW ELFCLASS32
|
||||
|
@ -606,9 +576,6 @@ struct sym_attr {
|
|||
unsigned plt_offset;
|
||||
int plt_sym;
|
||||
int dyn_index;
|
||||
#ifdef TCC_TARGET_ARM
|
||||
unsigned char plt_thumb_stub:1;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct TCCState {
|
||||
|
@ -653,16 +620,6 @@ struct TCCState {
|
|||
unsigned char include_sys_deps; /* option -MD */
|
||||
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 */
|
||||
unsigned char gnu_ext;
|
||||
/* use TinyCC extensions */
|
||||
|
@ -671,19 +628,11 @@ struct TCCState {
|
|||
unsigned char dflag; /* -dX value */
|
||||
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;
|
||||
addr_t text_addr; /* address of text section */
|
||||
unsigned section_align; /* section alignment */
|
||||
#ifdef TCC_TARGET_I386
|
||||
|
||||
int seg_size; /* 32. Can be 16 with i386 assembler (.code16) */
|
||||
#endif
|
||||
|
||||
char *tcc_lib_path; /* CONFIG_TCCDIR or -B option */
|
||||
char *soname; /* as specified on the command line (-soname) */
|
||||
|
@ -697,8 +646,6 @@ struct TCCState {
|
|||
int output_type;
|
||||
/* output format, see TCC_OUTPUT_FORMAT_xxx */
|
||||
int output_format;
|
||||
/* nth test to run with -dt -run */
|
||||
int run_test;
|
||||
|
||||
/* array of all loaded dlls (including those referenced by loaded dlls) */
|
||||
DLLReference **loaded_dlls;
|
||||
|
@ -772,11 +719,6 @@ struct TCCState {
|
|||
Section *text_section, *data_section, *rodata_section, *bss_section;
|
||||
Section *common_section;
|
||||
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 */
|
||||
union { Section *symtab_section, *symtab; }; /* historical alias */
|
||||
/* temporary dynamic symbol sections (for dll loading) */
|
||||
|
@ -789,19 +731,6 @@ struct TCCState {
|
|||
Section *eh_frame_section;
|
||||
Section *eh_frame_hdr_section;
|
||||
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() */
|
||||
int new_undef_sym;
|
||||
|
@ -812,11 +741,6 @@ struct TCCState {
|
|||
ElfW_Rel *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
|
||||
/* PE info */
|
||||
int pe_subsystem;
|
||||
|
@ -824,17 +748,6 @@ struct TCCState {
|
|||
unsigned pe_file_align;
|
||||
unsigned pe_stack_size;
|
||||
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
|
||||
|
||||
#ifndef ELF_OBJ_ONLY
|
||||
|
@ -847,24 +760,6 @@ struct TCCState {
|
|||
Section *verneed_section;
|
||||
#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 */
|
||||
int total_idents;
|
||||
int total_lines;
|
||||
|
@ -1079,9 +974,6 @@ ST_DATA void** stk_data;
|
|||
ST_DATA int nb_stk_data;
|
||||
|
||||
/* 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_fileextension (const char *name);
|
||||
|
||||
|
@ -1156,7 +1048,7 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
|
|||
#define AFF_BINTYPE_REL 1
|
||||
#define AFF_BINTYPE_DYN 2
|
||||
#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 */
|
||||
#define FILE_NOT_FOUND -2
|
||||
|
@ -1166,12 +1058,7 @@ ST_FUNC int tcc_add_crt(TCCState *s, const char *filename);
|
|||
#endif
|
||||
ST_FUNC int tcc_add_dll(TCCState *s, const char *filename, int flags);
|
||||
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);
|
||||
PUB_FUNC int tcc_add_library_err(TCCState *s, const char *f);
|
||||
PUB_FUNC void tcc_print_stats(TCCState *s, unsigned total_time);
|
||||
|
@ -1353,9 +1240,6 @@ ST_FUNC void vpop(void);
|
|||
#if PTR_SIZE == 4
|
||||
ST_FUNC void lexpand(void);
|
||||
#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_upstack(int r, int n);
|
||||
ST_FUNC int get_reg(int rc);
|
||||
|
@ -1374,23 +1258,12 @@ ST_FUNC void indir(void);
|
|||
ST_FUNC void unary(void);
|
||||
ST_FUNC void gexpr(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 ------------ */
|
||||
|
||||
#define TCC_OUTPUT_FORMAT_ELF 0 /* default output format: ELF */
|
||||
#define TCC_OUTPUT_FORMAT_BINARY 1 /* binary image output */
|
||||
#define TCC_OUTPUT_FORMAT_COFF 2 /* COFF */
|
||||
#define TCC_OUTPUT_DYN TCC_OUTPUT_DLL
|
||||
|
||||
#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);
|
||||
#endif
|
||||
|
||||
int coff_load_file(TCCState *s1, int fd, const char *fname);
|
||||
|
||||
/* ------------ 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 gotplt_entry_type (int reloc_type);
|
||||
/* 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
|
||||
|
||||
#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 void relocate_plt(TCCState *s1);
|
||||
ST_FUNC void build_got_entries(TCCState *s1, int got_sym); /* in tccelf.c */
|
||||
#define NEED_BUILD_GOT
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
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_ftof(int t);
|
||||
ST_FUNC void ggoto(void);
|
||||
#ifndef TCC_TARGET_C67
|
||||
ST_FUNC void o(unsigned int c);
|
||||
#endif
|
||||
ST_FUNC void gen_vla_sp_save(int addr);
|
||||
ST_FUNC void gen_vla_sp_restore(int addr);
|
||||
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 ------------ */
|
||||
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 || defined TCC_TARGET_ARM
|
||||
ST_FUNC void g(int c);
|
||||
ST_FUNC void gen_le16(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_addrpc32(int r, Sym *sym, int c);
|
||||
ST_FUNC void gen_cvt_csti(int t);
|
||||
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
|
||||
|
||||
|
||||
/* ------------ 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 ------------ */
|
||||
|
||||
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 stabstr_section stab_section->link
|
||||
#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_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 */
|
||||
#ifndef CONFIG_DWARF_VERSION
|
||||
|
@ -1693,8 +1517,6 @@ ST_FUNC void tcc_tcov_reset_ind(TCCState *s1);
|
|||
|
||||
#if defined TCC_TARGET_PE
|
||||
# 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
|
||||
# define R_DATA_32DW R_DATA_32
|
||||
#endif
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#define USING_GLOBALS
|
||||
#include "tcc.h"
|
||||
#include "utils/string.h"
|
||||
#ifdef CONFIG_TCC_ASM
|
||||
|
||||
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();
|
||||
if (tok == TOK_EOF)
|
||||
break;
|
||||
tcc_debug_line(s1);
|
||||
parse_flags |= PARSE_FLAG_LINEFEED; /* XXX: suppress that hack */
|
||||
redo:
|
||||
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)
|
||||
{
|
||||
int ret;
|
||||
tcc_debug_start(s1);
|
||||
/* default section is text */
|
||||
cur_text_section = text_section;
|
||||
ind = cur_text_section->data_offset;
|
||||
nocode_wanted = 0;
|
||||
ret = tcc_assemble_internal(s1, do_preprocess, 1);
|
||||
cur_text_section->data_offset = ind;
|
||||
tcc_debug_end(s1);
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -15,14 +15,29 @@ coff_load_lib(TCCState *s1, int fd)
|
|||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
coff_merge_or_create(void)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
coff_resolve_symbols(void)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
coff_load_obj(TCCState *s1, int fd)
|
||||
{
|
||||
FILHDR hdr;
|
||||
SCNHDR *scns;
|
||||
SYMENT *syments;
|
||||
RELOC *relocs;
|
||||
Section *s;
|
||||
uint16_t i;
|
||||
int32_t j;
|
||||
int k;
|
||||
char buff[9];
|
||||
|
||||
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)
|
||||
return (tcc_error_noabort("invalid coff object file"));
|
||||
|
||||
/* load symtab */
|
||||
|
||||
/* read sections */
|
||||
scns = tcc_malloc(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);
|
||||
memcpy(buff, scns[i].s_name, 8);
|
||||
printf("sec: %s\n", buff);
|
||||
|
||||
for (k = 1; k < s1->nb_sections; k++)
|
||||
{
|
||||
if (strcmp(s1->sections[k]->name, buff) != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* load symtab */
|
||||
|
@ -54,7 +78,7 @@ coff_load_obj(TCCState *s1, int fd)
|
|||
for (j = 0; j < hdr.f_nsyms; j++)
|
||||
{
|
||||
memset(buff, 0, 9);
|
||||
memcpy(buff, syments[i].n_name, 8);
|
||||
memcpy(buff, syments[j].n_name, 8);
|
||||
printf("sym: %s\n", buff);
|
||||
}
|
||||
|
951
libtcc/tcccoff.c_old.c
Normal file
951
libtcc/tcccoff.c_old.c
Normal 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 = §ion_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 = §ion_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 = §ion_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 = §ion_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 = §ion_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 = §ion_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 = §ion_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 = §ion_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;
|
||||
}
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
|
||||
#include "tcc.h"
|
||||
#include "utils/string.h"
|
||||
|
||||
/* Define this to get some debug output during relocation processing. */
|
||||
#undef DEBUG_RELOC
|
||||
|
@ -84,26 +85,6 @@ ST_FUNC void tccelf_new(TCCState *s)
|
|||
".dynhashtab", SHF_PRIVATE);
|
||||
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
|
||||
/* to make sure that -ltcc1 -Wl,-e,_start will grab the startup code
|
||||
from libtcc1.a (unless _start defined) */
|
||||
|
@ -158,10 +139,6 @@ ST_FUNC void tccelf_begin_file(TCCState *s1)
|
|||
}
|
||||
/* disable symbol hashing during compilation */
|
||||
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);
|
||||
|
@ -520,7 +497,7 @@ ST_FUNC addr_t get_sym_addr(TCCState *s1, const char *name, int err, int forc)
|
|||
}
|
||||
|
||||
/* 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);
|
||||
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 */
|
||||
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))
|
||||
{
|
||||
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;
|
||||
/* Use ld.so to resolve symbol for us (for tcc -run) */
|
||||
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 */
|
||||
} else if (s1->dynsym && find_elf_sym(s1->dynsym, name))
|
||||
goto found;
|
||||
|
@ -1107,7 +1065,6 @@ static void relocate_section(TCCState *s1, Section *s, Section *sr)
|
|||
int type, sym_index;
|
||||
unsigned char *ptr;
|
||||
addr_t tgt, addr;
|
||||
int is_dwarf = s->sh_num >= s1->dwlo && s->sh_num < s1->dwhi;
|
||||
|
||||
qrel = (ElfW_Rel *)sr->data;
|
||||
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
|
||||
tgt += rel->r_addend;
|
||||
#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;
|
||||
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 (sr->sh_flags & SHF_ALLOC) {
|
||||
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
|
||||
}
|
||||
|
@ -1158,11 +1098,9 @@ ST_FUNC void relocate_sections(TCCState *s1)
|
|||
if (sr->sh_type != SHT_RELX)
|
||||
continue;
|
||||
s = s1->sections[sr->sh_info];
|
||||
#ifndef TCC_TARGET_MACHO
|
||||
if (s != s1->got
|
||||
|| s1->static_link
|
||||
|| s1->output_type == TCC_OUTPUT_MEMORY)
|
||||
#endif
|
||||
{
|
||||
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)
|
||||
{
|
||||
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;
|
||||
for_each_elem(sr, 0, rel, ElfW_Rel) {
|
||||
int sym_index = ELFW(R_SYM)(rel->r_info);
|
||||
int type = ELFW(R_TYPE)(rel->r_info);
|
||||
switch(type) {
|
||||
#if defined(TCC_TARGET_I386)
|
||||
|
||||
case R_386_32:
|
||||
if (!get_sym_attr(s1, sym_index, 0)->dyn_index
|
||||
&& ((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);
|
||||
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++;
|
||||
break;
|
||||
#if defined(TCC_TARGET_I386)
|
||||
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)
|
||||
count++;
|
||||
break;
|
||||
|
@ -1242,7 +1145,7 @@ static int prepare_dynamic_rel(TCCState *s1, Section *sr)
|
|||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return count;
|
||||
}
|
||||
#endif
|
||||
|
@ -1399,9 +1302,7 @@ redo:
|
|||
if (sym->st_shndx == SHN_UNDEF) {
|
||||
ElfW(Sym) *esym;
|
||||
int dynindex;
|
||||
if (!PCRELATIVE_DLLPLT
|
||||
&& (s1->output_type & TCC_OUTPUT_DYN))
|
||||
continue;
|
||||
|
||||
/* Relocations for UNDEF symbols would normally need
|
||||
to be transferred into the executable or shared object.
|
||||
If that were done AUTO_GOTPLT_ENTRY wouldn't exist.
|
||||
|
@ -1425,28 +1326,14 @@ redo:
|
|||
} else if (sym->st_shndx == SHN_ABS) {
|
||||
if (sym->st_value == 0) /* from tcc_add_btstub() */
|
||||
continue;
|
||||
#ifndef TCC_TARGET_ARM
|
||||
if (PTR_SIZE != 8)
|
||||
continue;
|
||||
#endif
|
||||
/* from tcc_add_symbol(): on 64 bit platforms these
|
||||
need to go through .got */
|
||||
} else
|
||||
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);
|
||||
if (reloc_type == -1) {
|
||||
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);
|
||||
}
|
||||
|
||||
#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
|
||||
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)
|
||||
|
@ -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 */
|
||||
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);
|
||||
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)
|
||||
{
|
||||
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
|
||||
#if !defined TCC_TARGET_PE
|
||||
/* add libc crt1/crti objects */
|
||||
ST_FUNC void tccelf_add_crtbegin(TCCState *s1)
|
||||
{
|
||||
#if TARGETOS_OpenBSD
|
||||
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");
|
||||
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)
|
||||
{
|
||||
#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");
|
||||
#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
|
||||
/* add tcc runtime libraries */
|
||||
|
@ -1758,34 +1450,12 @@ ST_FUNC void tcc_add_runtime(TCCState *s1)
|
|||
{
|
||||
s1->filetype = 0;
|
||||
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
tcc_add_bcheck(s1);
|
||||
#endif
|
||||
tcc_add_pragma_libs(s1);
|
||||
|
||||
/* add libc */
|
||||
if (!s1->nostdlib) {
|
||||
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)
|
||||
tcc_add_library(s1, "pthread");
|
||||
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);
|
||||
}
|
||||
#endif
|
||||
#if defined TCC_TARGET_ARM && TARGETOS_FreeBSD
|
||||
tcc_add_library(s1, "gcc_s"); // unwind code
|
||||
#endif
|
||||
|
||||
if (TCC_LIBTCC1[0])
|
||||
tcc_add_support(s1, TCC_LIBTCC1);
|
||||
#ifndef TCC_TARGET_MACHO
|
||||
if (s1->output_type != TCC_OUTPUT_MEMORY)
|
||||
tccelf_add_crtend(s1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#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, "_edata", data_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 */
|
||||
add_init_array_defines(s1, ".preinit_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)) {
|
||||
/* when generating a DLL, we include relocations but
|
||||
we may patch them */
|
||||
if ((file_type & TCC_OUTPUT_DYN)
|
||||
&& (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) {
|
||||
} else if ((s->sh_flags & SHF_ALLOC)) {
|
||||
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;
|
||||
}
|
||||
|
@ -2313,8 +1950,6 @@ static int layout_sections(TCCState *s1, int *sec_order, struct dyn_inf *d)
|
|||
s_align = s1->section_align;
|
||||
|
||||
addr = ELF_START_ADDR;
|
||||
if (s1->output_type & TCC_OUTPUT_DYN)
|
||||
addr = 0;
|
||||
|
||||
if (s1->has_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) {
|
||||
put_dt(dynamic, DT_FINI, s->sh_addr);
|
||||
}
|
||||
if (s1->do_debug)
|
||||
put_dt(dynamic, DT_DEBUG, 0);
|
||||
put_dt(dynamic, DT_NULL, 0);
|
||||
}
|
||||
|
||||
|
@ -2574,25 +2207,9 @@ static int tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr)
|
|||
ehdr.e_ident[5] = ELFDATA2LSB;
|
||||
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) {
|
||||
ehdr.e_type = ET_REL;
|
||||
} else {
|
||||
if (file_type & TCC_OUTPUT_DYN)
|
||||
ehdr.e_type = ET_DYN;
|
||||
else
|
||||
ehdr.e_type = ET_EXEC;
|
||||
if (s1->elf_entryname)
|
||||
ehdr.e_entry = get_sym_addr(s1, s1->elf_entryname, 1, 0);
|
||||
|
@ -2752,63 +2369,6 @@ static void reorder_sections(TCCState *s1, int *sec_order)
|
|||
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);
|
||||
|
||||
/* Output an elf, coff or binary file */
|
||||
|
@ -2827,21 +2387,6 @@ static int elf_output_file(TCCState *s1, const char *filename)
|
|||
sec_order = NULL;
|
||||
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.) */
|
||||
tcc_add_runtime(s1);
|
||||
resolve_common_syms(s1);
|
||||
|
@ -2876,7 +2421,6 @@ static int elf_output_file(TCCState *s1, const char *filename)
|
|||
|
||||
got_sym = build_got(s1);
|
||||
if (file_type & TCC_OUTPUT_EXE) {
|
||||
bind_exe_dynsyms(s1, file_type & TCC_OUTPUT_DYN);
|
||||
if (s1->nb_errors)
|
||||
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 */
|
||||
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);
|
||||
} else {
|
||||
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));
|
||||
|
||||
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_1, dt_flags_1);
|
||||
if (s1->symbolic)
|
||||
|
@ -2946,8 +2476,7 @@ static int elf_output_file(TCCState *s1, const char *filename)
|
|||
if (dynamic) {
|
||||
/* put in GOT the dynamic section address and relocate PLT */
|
||||
write32le(s1->got->data, dynamic->sh_addr);
|
||||
if (file_type == TCC_OUTPUT_EXE
|
||||
|| (RELOCATE_DLLPLT && (file_type & TCC_OUTPUT_DYN)))
|
||||
if (file_type == TCC_OUTPUT_EXE)
|
||||
relocate_plt(s1);
|
||||
/* relocate symbols in .dynsym now that final addresses are known */
|
||||
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);
|
||||
|
||||
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' */
|
||||
ret = tcc_write_elf_file(s1, filename, dyninf.phnum, dyninf.phdr);
|
||||
the_end:
|
||||
|
@ -3027,16 +2553,12 @@ static int elf_output_obj(TCCState *s1, const char *filename)
|
|||
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)
|
||||
return elf_output_obj(s, filename);
|
||||
#ifdef TCC_TARGET_PE
|
||||
return pe_output_file(s, filename);
|
||||
#elif defined TCC_TARGET_MACHO
|
||||
return macho_output_file(s, filename);
|
||||
#else
|
||||
return elf_output_file(s, filename);
|
||||
#endif
|
||||
|
@ -3082,10 +2604,8 @@ ST_FUNC int tcc_object_type(int fd, ElfW(Ehdr) *h)
|
|||
} else if (size >= 8) {
|
||||
if (0 == memcmp(h, ARMAG, 8))
|
||||
return AFF_BINTYPE_AR;
|
||||
#ifdef TCC_TARGET_COFF
|
||||
if (((struct filehdr*)h)->f_magic == COFF_C67_MAGIC)
|
||||
return AFF_BINTYPE_C67;
|
||||
#endif
|
||||
else if (((FILHDR *)h)->f_magic == F_MACH_I386)
|
||||
return (AFF_BINTYPE_COFF);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -3167,7 +2687,7 @@ invalid:
|
|||
sh_name = strsec + sh->sh_name;
|
||||
if (0 == strncmp(sh_name, ".debug_", 7)
|
||||
|| 0 == strncmp(sh_name, ".stab", 5)) {
|
||||
if (!s1->do_debug || seencompressed)
|
||||
if (seencompressed)
|
||||
continue;
|
||||
} else
|
||||
if (sh->sh_type != SHT_PROGBITS &&
|
||||
|
@ -3202,12 +2722,6 @@ invalid:
|
|||
sm_table[i].link_once = 1;
|
||||
goto next;
|
||||
}
|
||||
if (stab_section) {
|
||||
if (s == stab_section)
|
||||
stab_index = i;
|
||||
if (s == stab_section->link)
|
||||
stabstr_index = i;
|
||||
}
|
||||
goto found;
|
||||
}
|
||||
/* not found: create new section */
|
||||
|
@ -3335,12 +2849,6 @@ invalid:
|
|||
sym_index = old_to_new_syms[sym_index];
|
||||
/* ignore link_once in rel section. */
|
||||
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:
|
||||
tcc_error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
|
||||
|
@ -3350,18 +2858,6 @@ invalid:
|
|||
rel->r_info = ELFW(R_INFO)(sym_index, type);
|
||||
/* offset the relocation offset */
|
||||
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;
|
||||
default:
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#define USING_GLOBALS
|
||||
#include "tcc.h"
|
||||
#include "utils/string.h"
|
||||
|
||||
/********************************************************/
|
||||
/* global variables */
|
||||
|
@ -43,7 +44,6 @@ static int nb_sym_pools;
|
|||
|
||||
static Sym *all_cleanups, *pending_gotos;
|
||||
static int local_scope;
|
||||
ST_DATA char debug_modes;
|
||||
|
||||
ST_DATA SValue *vtop;
|
||||
static SValue _vstack[1 + VSTACK_SIZE];
|
||||
|
@ -176,8 +176,6 @@ static int gind()
|
|||
{
|
||||
int t = ind;
|
||||
CODE_ON();
|
||||
if (debug_modes)
|
||||
tcc_tcov_block_begin(tcc_state);
|
||||
return t;
|
||||
}
|
||||
|
||||
|
@ -233,13 +231,6 @@ static int R_RET(int t)
|
|||
{
|
||||
if (!is_float(t))
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -250,14 +241,6 @@ static int R2_RET(int t)
|
|||
#if PTR_SIZE == 4
|
||||
if (t == VT_LLONG)
|
||||
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
|
||||
return VT_CONST;
|
||||
}
|
||||
|
@ -282,15 +265,6 @@ static int RC_TYPE(int t)
|
|||
{
|
||||
if (!is_float(t))
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -323,10 +297,7 @@ ST_FUNC int ieee_finite(double d)
|
|||
}
|
||||
|
||||
/* 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
|
||||
#endif
|
||||
|
||||
ST_FUNC void test_lvalue(void)
|
||||
{
|
||||
|
@ -386,13 +357,7 @@ ST_FUNC int tccgen_compile(TCCState *s1)
|
|||
func_ind = -1;
|
||||
anon_sym = SYM_FIRST_ANOM;
|
||||
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
|
||||
printf("%s: **** new file\n", file->filename);
|
||||
#endif
|
||||
|
@ -402,17 +367,12 @@ ST_FUNC int tccgen_compile(TCCState *s1)
|
|||
gen_inline_functions(s1);
|
||||
check_vstack();
|
||||
/* 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;
|
||||
}
|
||||
|
||||
ST_FUNC void tccgen_finish(TCCState *s1)
|
||||
{
|
||||
tcc_debug_end(s1); /* just in case of errors: free memory */
|
||||
free_inline_functions(s1);
|
||||
sym_pop(&global_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);
|
||||
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 {
|
||||
esym = elfsym(sym);
|
||||
esym->st_value = value;
|
||||
|
@ -882,13 +839,10 @@ ST_FUNC void vpop(void)
|
|||
{
|
||||
int v;
|
||||
v = vtop->r & VT_VALMASK;
|
||||
#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
|
||||
/* for x86, we need to pop the FP stack */
|
||||
if (v == TREG_ST0) {
|
||||
o(0xd8dd); /* fstp %st(0) */
|
||||
} else
|
||||
#endif
|
||||
if (v == VT_CMP) {
|
||||
} else if (v == VT_CMP) {
|
||||
/* need to put correct jump if && or || without test */
|
||||
gsym(vtop->jtrue);
|
||||
gsym(vtop->jfalse);
|
||||
|
@ -1375,12 +1329,10 @@ ST_FUNC void save_reg_upstack(int r, int n)
|
|||
sv.r = VT_LOCAL | VT_LVAL;
|
||||
sv.c.i = l;
|
||||
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 */
|
||||
if (r == TREG_ST0) {
|
||||
o(0xd8dd); /* fstp %st(0) */
|
||||
}
|
||||
#endif
|
||||
/* special long long case */
|
||||
if (p->r2 < VT_CONST && USING_TWO_WORDS(bt)) {
|
||||
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 */
|
||||
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;
|
||||
}
|
||||
|
||||
#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. */
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -1846,18 +1627,9 @@ ST_FUNC int gv(int rc)
|
|||
init_putv(&p, &vtop->type, offset);
|
||||
vtop->r |= VT_LVAL;
|
||||
}
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
if (vtop->r & VT_MUSTBOUND)
|
||||
gbound();
|
||||
#endif
|
||||
|
||||
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);
|
||||
|
||||
/* need to reload if:
|
||||
|
@ -1932,11 +1704,6 @@ ST_FUNC int gv(int rc)
|
|||
}
|
||||
}
|
||||
vtop->r = r;
|
||||
#ifdef TCC_TARGET_C67
|
||||
/* uses register pairs for doubles */
|
||||
if (bt == VT_DOUBLE)
|
||||
vtop->r2 = r+1;
|
||||
#endif
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
@ -2066,10 +1833,6 @@ static void gen_opl(int op)
|
|||
case TOK_UMOD:
|
||||
func = TOK___umoddi3;
|
||||
gen_mod_func:
|
||||
#ifdef TCC_ARM_EABI
|
||||
reg_iret = TREG_R2;
|
||||
reg_lret = TREG_R3;
|
||||
#endif
|
||||
gen_func:
|
||||
/* call generic long long function */
|
||||
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
|
||||
#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 */
|
||||
static void gen_opif(int op)
|
||||
|
@ -3037,21 +2770,7 @@ op_err:
|
|||
type1 = vtop[-1].type;
|
||||
vpush_type_size(pointed_type(&vtop[-1].type), &align);
|
||||
gen_op('*');
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
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);
|
||||
/* put again type if gen_opic() swaped operands */
|
||||
vtop->type = type1;
|
||||
|
@ -3107,9 +2826,6 @@ op_err:
|
|||
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 */
|
||||
static void gen_cvt_itof1(int t)
|
||||
{
|
||||
|
@ -3132,11 +2848,7 @@ static void gen_cvt_itof1(int 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 */
|
||||
static void gen_cvt_ftoi1(int t)
|
||||
{
|
||||
|
@ -3160,7 +2872,6 @@ static void gen_cvt_ftoi1(int t)
|
|||
gen_cvt_ftoi(t);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* special delayed cast for char/short */
|
||||
static void force_charshort_cast(void)
|
||||
|
@ -3217,7 +2928,7 @@ error:
|
|||
}
|
||||
|
||||
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
|
||||
(except when it's '0' which is needed for arm:gen_negf()) */
|
||||
if (dbt_bt == VT_LDOUBLE && !nocode_wanted && (sf || vtop->c.i != 0))
|
||||
|
@ -3373,13 +3084,7 @@ error:
|
|||
if (ds == 8) {
|
||||
/* need to convert from 32bit to 64bit */
|
||||
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;
|
||||
#endif
|
||||
} else {
|
||||
gen_cvt_sxtw();
|
||||
goto done;
|
||||
|
@ -3389,9 +3094,7 @@ error:
|
|||
/* RISC-V keeps 32bit vals in registers sign-extended.
|
||||
So here we need a sign-extension for signed types and
|
||||
zero-extension. for unsigned types. */
|
||||
#if !defined(TCC_TARGET_RISCV64)
|
||||
trunc = 32; /* zero upper 32 bits for non RISC-V targets */
|
||||
#endif
|
||||
} else {
|
||||
ss = 4;
|
||||
}
|
||||
|
@ -3399,12 +3102,10 @@ error:
|
|||
|
||||
if (ds >= ss)
|
||||
goto done;
|
||||
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 || defined TCC_TARGET_ARM64
|
||||
if (ss == 4) {
|
||||
gen_cvt_csti(dbt);
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
bits = (ss - ds) * 8;
|
||||
/* for unsigned, gen_op will convert SAR to SHR */
|
||||
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;
|
||||
return LDOUBLE_SIZE;
|
||||
} else if (bt == VT_DOUBLE || bt == VT_LLONG) {
|
||||
#if (defined TCC_TARGET_I386 && !defined TCC_TARGET_PE) \
|
||||
|| (defined TCC_TARGET_ARM && !defined TCC_ARM_EABI)
|
||||
#if (defined TCC_TARGET_I386 && !defined TCC_TARGET_PE)
|
||||
*a = 4;
|
||||
#else
|
||||
*a = 8;
|
||||
|
@ -3632,27 +3332,16 @@ ST_FUNC void vstore(void)
|
|||
size = type_size(&vtop->type, &align);
|
||||
/* destination, keep on stack() as result */
|
||||
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;
|
||||
gaddrof();
|
||||
/* source */
|
||||
vswap();
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
if (vtop->r & VT_MUSTBOUND)
|
||||
gbound();
|
||||
#endif
|
||||
vtop->type.t = VT_PTR;
|
||||
gaddrof();
|
||||
|
||||
#ifdef TCC_TARGET_NATIVE_STRUCT_COPY
|
||||
if (1
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
&& !tcc_state->do_bounds_check
|
||||
#endif
|
||||
) {
|
||||
if (1) {
|
||||
gen_struct_copy(size);
|
||||
} else
|
||||
#endif
|
||||
|
@ -3660,13 +3349,6 @@ ST_FUNC void vstore(void)
|
|||
/* type size */
|
||||
vpushi(size);
|
||||
/* 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);
|
||||
vrott(4);
|
||||
gfunc_call(3);
|
||||
|
@ -3740,14 +3422,6 @@ ST_FUNC void vstore(void)
|
|||
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 */
|
||||
|
||||
if (delayed_cast) {
|
||||
|
@ -4283,11 +3957,7 @@ static void struct_layout(CType *type, AttributeDef *ad)
|
|||
bit_pos = BIT_POS(f->type.t);
|
||||
size = type_size(&f->type, &align);
|
||||
|
||||
if (bit_pos + bit_size <= size * 8 && f->c + size <= c
|
||||
#ifdef TCC_TARGET_ARM
|
||||
&& !(f->c & (align - 1))
|
||||
#endif
|
||||
)
|
||||
if (bit_pos + bit_size <= size * 8 && f->c + size <= c)
|
||||
continue;
|
||||
|
||||
/* try to access the field using a different type */
|
||||
|
@ -4313,11 +3983,7 @@ static void struct_layout(CType *type, AttributeDef *ad)
|
|||
c0 = cx;
|
||||
}
|
||||
|
||||
if (px + bit_size <= s * 8 && cx + s <= c
|
||||
#ifdef TCC_TARGET_ARM
|
||||
&& !(cx & (align - 1))
|
||||
#endif
|
||||
) {
|
||||
if (px + bit_size <= s * 8 && cx + s <= c) {
|
||||
/* update offset and bit position */
|
||||
f->c = cx;
|
||||
bit_pos = px;
|
||||
|
@ -4590,8 +4256,6 @@ do_decl:
|
|||
check_fields(type, 1);
|
||||
check_fields(type, 0);
|
||||
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();
|
||||
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:
|
||||
u = VT_BOOL;
|
||||
goto basic_type;
|
||||
|
@ -5222,11 +4879,6 @@ ST_FUNC void indir(void)
|
|||
if (!(vtop->type.t & (VT_ARRAY | VT_VLA))
|
||||
&& (vtop->type.t & VT_BTYPE) != VT_FUNC) {
|
||||
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;
|
||||
AttributeDef ad;
|
||||
|
||||
/* generate line number info */
|
||||
if (debug_modes)
|
||||
tcc_debug_line(tcc_state), tcc_tcov_check_line (tcc_state, 1);
|
||||
|
||||
type.ref = NULL;
|
||||
/* XXX: GCC 2.95.3 does not generate a table although it should be
|
||||
better here */
|
||||
|
@ -5764,92 +5412,18 @@ ST_FUNC void unary(void)
|
|||
mk_pointer(&type);
|
||||
vset(&type, VT_LOCAL, 0); /* local frame */
|
||||
while (level--) {
|
||||
#ifdef TCC_TARGET_RISCV64
|
||||
vpushi(2*PTR_SIZE);
|
||||
gen_op('-');
|
||||
#endif
|
||||
mk_pointer(&vtop->type);
|
||||
indir(); /* -> parent frame */
|
||||
}
|
||||
if (tok1 == TOK_builtin_return_address) {
|
||||
// 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);
|
||||
gen_op('+');
|
||||
#endif
|
||||
mk_pointer(&vtop->type);
|
||||
indir();
|
||||
}
|
||||
}
|
||||
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 */
|
||||
case TOK___atomic_store:
|
||||
|
@ -6066,11 +5640,6 @@ special_math_val:
|
|||
/* an array is never an lvalue */
|
||||
if (!(vtop->type.t & VT_ARRAY)) {
|
||||
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();
|
||||
} else if (tok == '[') {
|
||||
|
@ -6113,25 +5682,12 @@ special_math_val:
|
|||
if (ret_nregs <= 0) {
|
||||
/* get some space for the returned structure */
|
||||
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;
|
||||
ret.type = s->type;
|
||||
ret.r = VT_LOCAL | VT_LVAL;
|
||||
/* pass it as 'int' to avoid structure arg passing
|
||||
problems */
|
||||
vseti(VT_LOCAL, loc);
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
if (tcc_state->do_bounds_check)
|
||||
--loc;
|
||||
#endif
|
||||
ret.c = vtop->c;
|
||||
if (ret_nregs < 0)
|
||||
vtop--;
|
||||
|
@ -6191,9 +5747,6 @@ special_math_val:
|
|||
|
||||
if (ret_nregs < 0) {
|
||||
vsetc(&ret.type, ret.r, &ret.c);
|
||||
#ifdef TCC_TARGET_RISCV64
|
||||
arch_transfer_ret_regs(1);
|
||||
#endif
|
||||
} else {
|
||||
/* return value */
|
||||
n = ret_nregs;
|
||||
|
@ -6251,8 +5804,6 @@ special_math_val:
|
|||
}
|
||||
}
|
||||
if (s->f.func_noreturn) {
|
||||
if (debug_modes)
|
||||
tcc_tcov_block_end(tcc_state, -1);
|
||||
CODE_OFF();
|
||||
}
|
||||
} else {
|
||||
|
@ -6679,7 +6230,7 @@ ST_FUNC int expr_const(void)
|
|||
/* ------------------------------------------------------------------------- */
|
||||
/* return from function */
|
||||
|
||||
#ifndef TCC_TARGET_ARM64
|
||||
|
||||
static void gfunc_return(CType *func_type)
|
||||
{
|
||||
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_align, ®size);
|
||||
if (ret_nregs < 0) {
|
||||
#ifdef TCC_TARGET_RISCV64
|
||||
arch_transfer_ret_regs(0);
|
||||
#endif
|
||||
} else if (0 == ret_nregs) {
|
||||
/* if returning structure, must copy it to implicit
|
||||
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 */
|
||||
}
|
||||
#endif
|
||||
|
||||
static void check_func_return(void)
|
||||
{
|
||||
|
@ -7027,9 +6574,6 @@ again:
|
|||
goto expr;
|
||||
next();
|
||||
|
||||
if (debug_modes)
|
||||
tcc_tcov_check_line (tcc_state, 0), tcc_tcov_block_begin (tcc_state);
|
||||
|
||||
if (t == TOK_IF) {
|
||||
new_scope_s(&o);
|
||||
skip('(');
|
||||
|
@ -7063,8 +6607,6 @@ again:
|
|||
prev_scope_s(&o);
|
||||
|
||||
} else if (t == '{') {
|
||||
if (debug_modes)
|
||||
tcc_debug_stabn(tcc_state, N_LBRAC, ind - func_ind);
|
||||
new_scope(&o);
|
||||
|
||||
/* handle local labels declarations */
|
||||
|
@ -7089,8 +6631,6 @@ again:
|
|||
}
|
||||
|
||||
prev_scope(&o, flags & STMT_EXPR);
|
||||
if (debug_modes)
|
||||
tcc_debug_stabn(tcc_state, N_RBRAC, ind - func_ind);
|
||||
if (local_scope)
|
||||
next();
|
||||
else if (!nocode_wanted)
|
||||
|
@ -7118,8 +6658,6 @@ again:
|
|||
/* jump unless last stmt in top-level block */
|
||||
if (tok != '}' || local_scope != 1)
|
||||
rsym = gjmp(rsym);
|
||||
if (debug_modes)
|
||||
tcc_tcov_block_end (tcc_state, -1);
|
||||
CODE_OFF();
|
||||
|
||||
} else if (t == TOK_BREAK) {
|
||||
|
@ -7332,8 +6870,6 @@ again:
|
|||
AttributeDef ad_tmp;
|
||||
parse_attribute(&ad_tmp);
|
||||
}
|
||||
if (debug_modes)
|
||||
tcc_tcov_reset_ind(tcc_state);
|
||||
vla_restore(cur_scope->vla.loc);
|
||||
|
||||
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 ()
|
||||
|
@ -7459,9 +6992,6 @@ static void init_putz(init_params *p, unsigned long c, int size)
|
|||
vseti(VT_LOCAL, c);
|
||||
vpushi(0);
|
||||
vpushs(size);
|
||||
#if defined TCC_TARGET_ARM && defined TCC_ARM_EABI
|
||||
vswap(); /* using __aeabi_memset(void*, size_t, int) */
|
||||
#endif
|
||||
gfunc_call(3);
|
||||
}
|
||||
}
|
||||
|
@ -7834,10 +7364,6 @@ static void decl_initializer(init_params *p, CType *type, unsigned long c, int f
|
|||
Sym indexsym;
|
||||
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 != '{' &&
|
||||
/* In case of strings we have special handling for arrays, so
|
||||
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 *sym;
|
||||
int saved_nocode_wanted = nocode_wanted;
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
int bcheck = tcc_state->do_bounds_check && !NODATA_WANTED;
|
||||
#endif
|
||||
init_params p = {0};
|
||||
|
||||
/* 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) {
|
||||
sec = NULL;
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
if (bcheck && v) {
|
||||
/* add padding between stack variables for bound checking */
|
||||
loc -= align;
|
||||
}
|
||||
#endif
|
||||
|
||||
loc = (loc - size) & -align;
|
||||
addr = loc;
|
||||
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) {
|
||||
/* local variable */
|
||||
#ifdef CONFIG_TCC_ASM
|
||||
|
@ -8229,11 +7741,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
|
|||
|
||||
if (sec) {
|
||||
addr = section_add(sec, size, align);
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
/* add padding if bound check */
|
||||
if (bcheck)
|
||||
section_add(sec, 1, 1);
|
||||
#endif
|
||||
|
||||
} else {
|
||||
addr = align; /* SHN_COMMON is special, symbol value is align */
|
||||
sec = common_section;
|
||||
|
@ -8253,19 +7761,6 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int 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) {
|
||||
|
@ -8286,11 +7781,6 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
|
|||
|
||||
vpush_type_size(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);
|
||||
cur_scope->vla.loc = addr;
|
||||
cur_scope->vla.num++;
|
||||
|
@ -8381,15 +7871,12 @@ static void gen_function(Sym *sym)
|
|||
if (sym->type.ref->f.func_dtor)
|
||||
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 */
|
||||
sym_push2(&local_stack, SYM_FIELD, 0, 0);
|
||||
local_scope = 1; /* for function parameters */
|
||||
nb_temp_local_vars = 0;
|
||||
gfunc_prolog(sym);
|
||||
tcc_debug_prolog_epilog(tcc_state, 0);
|
||||
|
||||
local_scope = 0;
|
||||
rsym = 0;
|
||||
|
@ -8400,11 +7887,8 @@ static void gen_function(Sym *sym)
|
|||
nocode_wanted = 0;
|
||||
/* reset local stack */
|
||||
pop_local_syms(NULL, 0);
|
||||
tcc_debug_prolog_epilog(tcc_state, 1);
|
||||
gfunc_epilog();
|
||||
|
||||
/* end of function */
|
||||
tcc_debug_funcend(tcc_state, ind - func_ind);
|
||||
|
||||
/* patch symbol size */
|
||||
elfsym(sym)->st_size = ind - func_ind;
|
||||
|
@ -8691,8 +8175,6 @@ static int decl(int l)
|
|||
sym->a = ad.a;
|
||||
if ((type.t & VT_BTYPE) == VT_FUNC)
|
||||
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
|
||||
&& !(type.t & VT_EXTERN)) {
|
||||
tcc_error("declaration of void object");
|
|
@ -20,6 +20,8 @@
|
|||
|
||||
#include "tcc.h"
|
||||
|
||||
#define TCC_OUTPUT_DLL 666
|
||||
|
||||
#define PE_MERGE_DATA 1
|
||||
#define PE_PRINT_SECTIONS 0
|
||||
|
||||
|
@ -1880,22 +1882,6 @@ static void pe_add_runtime(TCCState *s1, struct pe_info *pe)
|
|||
++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 */
|
||||
#ifdef TCC_IS_NATIVE
|
||||
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;
|
||||
s1->filetype = 0;
|
||||
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
tcc_add_bcheck(s1);
|
||||
#endif
|
||||
tcc_add_pragma_libs(s1);
|
||||
pe_add_runtime(s1, &pe);
|
||||
resolve_common_syms(s1);
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#define USING_GLOBALS
|
||||
#include "tcc.h"
|
||||
#include "utils/string.h"
|
||||
|
||||
/* #define to 1 to enable (see parse_pp_string()) */
|
||||
#define ACCEPT_LF_IN_STRINGS 0
|
||||
|
@ -946,12 +947,8 @@ redo_start:
|
|||
else if (parse_flags & PARSE_FLAG_ASM_FILE)
|
||||
p = parse_line_comment(p - 1);
|
||||
}
|
||||
#if !defined(TCC_TARGET_ARM)
|
||||
else if (parse_flags & PARSE_FLAG_ASM_FILE)
|
||||
p = parse_line_comment(p - 1);
|
||||
#else
|
||||
/* ARM assembly uses '#' for constants */
|
||||
#endif
|
||||
break;
|
||||
_default:
|
||||
default:
|
||||
|
@ -1326,8 +1323,8 @@ static void maybe_run_test(TCCState *s)
|
|||
p = get_tok_str(tok, NULL);
|
||||
if (0 != memcmp(p, "test_", 5))
|
||||
return;
|
||||
if (0 != --s->run_test)
|
||||
return;
|
||||
/*if (0 != --s->run_test)
|
||||
return;*/
|
||||
fprintf(s->ppfp, &"\n[%s]\n"[!(s->dflag & 32)], p), fflush(s->ppfp);
|
||||
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,
|
||||
tcc_strdup(buf));
|
||||
}
|
||||
/* add include file debug info */
|
||||
tcc_debug_bincl(s1);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
@ -1479,8 +1474,6 @@ static int expr_preprocess(TCCState *s1)
|
|||
parse_flags |= PARSE_FLAG_PREPROCESS;
|
||||
if (tok < TOK_IDENT)
|
||||
expect("identifier after 'defined'");
|
||||
if (s1->run_test)
|
||||
maybe_run_test(s1);
|
||||
c = 0;
|
||||
if (define_find(tok)
|
||||
|| tok == TOK___HAS_INCLUDE
|
||||
|
@ -1806,7 +1799,6 @@ ST_FUNC void tccpp_putfile(const char *filename)
|
|||
if (file->true_filename == file->filename)
|
||||
file->true_filename = tcc_strdup(file->filename);
|
||||
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 */
|
||||
|
@ -2615,8 +2607,6 @@ static void next_nomacro(void)
|
|||
tok_flags &= ~TOK_FLAG_ENDIF;
|
||||
}
|
||||
|
||||
/* add end of include file debug info */
|
||||
tcc_debug_eincl(tcc_state);
|
||||
/* pop include stack */
|
||||
tcc_close();
|
||||
s1->include_stack_ptr--;
|
||||
|
@ -2653,12 +2643,10 @@ maybe_newline:
|
|||
p++;
|
||||
tok = TOK_TWOSHARPS;
|
||||
} else {
|
||||
#if !defined(TCC_TARGET_ARM)
|
||||
if (parse_flags & PARSE_FLAG_ASM_FILE) {
|
||||
p = parse_line_comment(p - 1);
|
||||
goto redo_no_start;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
tok = '#';
|
||||
}
|
||||
|
@ -3576,24 +3564,12 @@ static void tcc_predefs(TCCState *s1, CString *cs, int is_asm)
|
|||
putdefs(cs, target_machine_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)
|
||||
putdef(cs, "__ASSEMBLER__");
|
||||
if (s1->output_type == TCC_OUTPUT_PREPROCESS)
|
||||
putdef(cs, "__TCC_PP__");
|
||||
if (s1->output_type == TCC_OUTPUT_MEMORY)
|
||||
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)
|
||||
putdef(cs, "__CHAR_UNSIGNED__");
|
||||
if (s1->optimize > 0)
|
|
@ -68,10 +68,6 @@
|
|||
DEF(TOK_TYPEOF3, "__typeof__")
|
||||
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 */
|
||||
/* preprocessor only */
|
||||
|
@ -105,10 +101,6 @@
|
|||
DEF(TOK___NAN__, "__nan__")
|
||||
DEF(TOK___SNAN__, "__snan__")
|
||||
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 */
|
||||
/* XXX: handle all tokens generically since speed is not critical */
|
||||
|
@ -173,16 +165,6 @@
|
|||
DEF(TOK_builtin_expect, "__builtin_expect")
|
||||
DEF(TOK_builtin_unreachable, "__builtin_unreachable")
|
||||
/*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 */
|
||||
#define DEF_ATOMIC(ID) DEF(TOK_##__##ID, "__"#ID)
|
||||
|
@ -205,13 +187,6 @@
|
|||
|
||||
/* pragma */
|
||||
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_lib, "lib")
|
||||
DEF(TOK_push_macro, "push_macro")
|
||||
|
@ -220,7 +195,6 @@
|
|||
DEF(TOK_option, "option")
|
||||
|
||||
/* builtin functions or variables */
|
||||
#ifndef TCC_ARM_EABI
|
||||
DEF(TOK_memcpy, "memcpy")
|
||||
DEF(TOK_memmove, "memmove")
|
||||
DEF(TOK_memset, "memset")
|
||||
|
@ -233,134 +207,16 @@
|
|||
DEF(TOK___ashldi3, "__ashldi3")
|
||||
DEF(TOK___floatundisf, "__floatundisf")
|
||||
DEF(TOK___floatundidf, "__floatundidf")
|
||||
# ifndef TCC_ARM_VFP
|
||||
DEF(TOK___floatundixf, "__floatundixf")
|
||||
DEF(TOK___fixunsxfdi, "__fixunsxfdi")
|
||||
# endif
|
||||
DEF(TOK___fixunssfdi, "__fixunssfdi")
|
||||
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___fixdfdi, "__fixdfdi")
|
||||
DEF(TOK___fixxfdi, "__fixxfdi")
|
||||
#endif
|
||||
|
||||
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
|
||||
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 */
|
||||
|
@ -401,28 +257,12 @@
|
|||
DEF_ASMDIR(endr)
|
||||
DEF_ASMDIR(org)
|
||||
DEF_ASMDIR(quad)
|
||||
#if defined(TCC_TARGET_I386)
|
||||
DEF_ASMDIR(code16)
|
||||
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(long)
|
||||
DEF_ASMDIR(int)
|
||||
DEF_ASMDIR(symver)
|
||||
DEF_ASMDIR(section) /* must be last directive */
|
||||
|
||||
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
|
||||
#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
|
||||
#include "i386/tok.h"
|
47
libtcc/utils/string.h
Normal file
47
libtcc/utils/string.h
Normal 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
234
stab.def
|
@ -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
17
stab.h
|
@ -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
339
tcc.c
|
@ -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
5
tcc/Makefile.am
Normal 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
314
tcc/tcc.c
Normal 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
134
tcc/tcc_new.c
Normal 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;
|
||||
}
|
|
@ -28,7 +28,7 @@
|
|||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "tcc.h"
|
||||
#include "libtcc/tcc.h"
|
||||
|
||||
//#define ARMAG "!<arch>\n"
|
||||
#define ARFMAG "`\n"
|
10
tcc/tcctools.h
Normal file
10
tcc/tcctools.h
Normal 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 */
|
2480
tccmacho.c
2480
tccmacho.c
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue