Refactor and remove code (tccdbg, tccmacho, ...)
This commit is contained in:
parent
05611e2658
commit
f08ef63153
60 changed files with 1887 additions and 8579 deletions
6
.gitignore
vendored
6
.gitignore
vendored
|
@ -15,7 +15,7 @@
|
||||||
.gdb_history
|
.gdb_history
|
||||||
a.out
|
a.out
|
||||||
tcc_g
|
tcc_g
|
||||||
tcc
|
tcc/tcc
|
||||||
tcc_c
|
tcc_c
|
||||||
tcc_p
|
tcc_p
|
||||||
*-tcc
|
*-tcc
|
||||||
|
@ -76,4 +76,6 @@ stamp-h1
|
||||||
*_old
|
*_old
|
||||||
*.cache
|
*.cache
|
||||||
.deps
|
.deps
|
||||||
build-aux
|
build-aux
|
||||||
|
configure
|
||||||
|
.dirstamp
|
|
@ -72,7 +72,7 @@ User interface:
|
||||||
- -pthread option (same as -D_REENTRANT -lpthread) (Henry Kroll III)
|
- -pthread option (same as -D_REENTRANT -lpthread) (Henry Kroll III)
|
||||||
- -m32/-m64 to re-exec cross compiler (Henry Kroll III)
|
- -m32/-m64 to re-exec cross compiler (Henry Kroll III)
|
||||||
- -Wl, Mimic all GNU -option forms supported by ld (Kirill Smelkov)
|
- -Wl, Mimic all GNU -option forms supported by ld (Kirill Smelkov)
|
||||||
- new LIBTCCAPI tcc_set_options() (grischka)
|
- new tcc_set_options() (grischka)
|
||||||
|
|
||||||
Platforms:
|
Platforms:
|
||||||
- Many improvements for x86-64 target (Shinichiro Hamaji, Michael Matz, grischka)
|
- Many improvements for x86-64 target (Shinichiro Hamaji, Michael Matz, grischka)
|
||||||
|
|
11
Makefile.am
11
Makefile.am
|
@ -1,12 +1,3 @@
|
||||||
AM_CFLAGS =
|
AM_CFLAGS =
|
||||||
|
|
||||||
|
SUBDIRS = libtcc tcc
|
||||||
noinst_LIBRARIES = libtcc.a
|
|
||||||
libtcc_a_SOURCES = libtcc.c tccpp.c tccgen.c tccdbg.c tccasm.c tccelf.c i386-gen.c i386-link.c i386-asm.c
|
|
||||||
libtcc_a_CPPFLAGS = -I$(top_srcdir)
|
|
||||||
|
|
||||||
bin_PROGRAMS = tcc
|
|
||||||
|
|
||||||
tcc_SOURCES = tcc.c
|
|
||||||
tcc_LDADD = libtcc.a
|
|
||||||
tcc_CPPFLAGS = -I$(top_srcdir)
|
|
||||||
|
|
3
compile_flags.txt
Normal file
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])
|
AM_INIT_AUTOMAKE([foreign subdir-objects -Werror -Wall])
|
||||||
|
|
||||||
AC_CONFIG_HEADERS([config.h])
|
AC_CONFIG_HEADERS([config.h])
|
||||||
AC_CONFIG_FILES([Makefile])
|
AC_CONFIG_FILES([
|
||||||
|
Makefile
|
||||||
|
libtcc/Makefile
|
||||||
|
tcc/Makefile])
|
||||||
|
|
||||||
AC_LANG([C])
|
AC_LANG([C])
|
||||||
AC_PROG_CC
|
AC_PROG_CC
|
||||||
|
|
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.H */
|
||||||
/* COFF data structures and related definitions used by the linker */
|
/* COFF data structures and related definitions used by the linker */
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
|
#ifndef COFF_H
|
||||||
|
# define COFF_H 1
|
||||||
# include <stdint.h>
|
# include <stdint.h>
|
||||||
|
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
|
@ -389,3 +390,5 @@ union auxent
|
||||||
#define _DORIGIN "_dorigin"
|
#define _DORIGIN "_dorigin"
|
||||||
|
|
||||||
#define _SORIGIN "_sorigin"
|
#define _SORIGIN "_sorigin"
|
||||||
|
|
||||||
|
#endif /* COFF_H */
|
|
@ -141,9 +141,6 @@ static const uint8_t reg_to_size[9] = {
|
||||||
[OP_REG8] = 0,
|
[OP_REG8] = 0,
|
||||||
[OP_REG16] = 1,
|
[OP_REG16] = 1,
|
||||||
[OP_REG32] = 2,
|
[OP_REG32] = 2,
|
||||||
#ifdef TCC_TARGET_X86_64
|
|
||||||
[OP_REG64] = 3,
|
|
||||||
#endif
|
|
||||||
*/
|
*/
|
||||||
0, 0, 1, 0, 2, 0, 0, 0, 3
|
0, 0, 1, 0, 2, 0, 0, 0, 3
|
||||||
};
|
};
|
||||||
|
@ -204,7 +201,7 @@ static const ASMInstr asm_instrs[] = {
|
||||||
#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) { TOK_ASM_ ## name, O(opcode), T(opcode, instr_type, group), 2, { op0, op1 }},
|
#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) { TOK_ASM_ ## name, O(opcode), T(opcode, instr_type, group), 2, { op0, op1 }},
|
||||||
#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) { TOK_ASM_ ## name, O(opcode), T(opcode, instr_type, group), 3, { op0, op1, op2 }},
|
#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) { TOK_ASM_ ## name, O(opcode), T(opcode, instr_type, group), 3, { op0, op1, op2 }},
|
||||||
|
|
||||||
#include "i386-asm.h"
|
#include "asm.h"
|
||||||
/* last operation */
|
/* last operation */
|
||||||
{ 0, },
|
{ 0, },
|
||||||
};
|
};
|
||||||
|
@ -216,7 +213,7 @@ static const uint16_t op0_codes[] = {
|
||||||
#define DEF_ASM_OP1(name, opcode, group, instr_type, op0)
|
#define DEF_ASM_OP1(name, opcode, group, instr_type, op0)
|
||||||
#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1)
|
#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1)
|
||||||
#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2)
|
#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2)
|
||||||
#include "i386-asm.h"
|
#include "asm.h"
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline int get_reg_shift(TCCState *s1)
|
static inline int get_reg_shift(TCCState *s1)
|
||||||
|
@ -1293,11 +1290,6 @@ ST_FUNC void subst_asm_operand(CString *add_str,
|
||||||
size = 1;
|
size = 1;
|
||||||
else if ((sv->type.t & VT_BTYPE) == VT_SHORT)
|
else if ((sv->type.t & VT_BTYPE) == VT_SHORT)
|
||||||
size = 2;
|
size = 2;
|
||||||
#ifdef TCC_TARGET_X86_64
|
|
||||||
else if ((sv->type.t & VT_BTYPE) == VT_LLONG ||
|
|
||||||
(sv->type.t & VT_BTYPE) == VT_PTR)
|
|
||||||
size = 8;
|
|
||||||
#endif
|
|
||||||
else
|
else
|
||||||
size = 4;
|
size = 4;
|
||||||
if (size == 1 && reg >= 4)
|
if (size == 1 && reg >= 4)
|
|
@ -99,13 +99,6 @@ ST_DATA const int reg_classes[NB_REGS] = {
|
||||||
|
|
||||||
static unsigned long func_sub_sp_offset;
|
static unsigned long func_sub_sp_offset;
|
||||||
static int func_ret_sub;
|
static int func_ret_sub;
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
|
||||||
static addr_t func_bound_offset;
|
|
||||||
static unsigned long func_bound_ind;
|
|
||||||
ST_DATA int func_bound_add_epilog;
|
|
||||||
static void gen_bounds_prolog(void);
|
|
||||||
static void gen_bounds_epilog(void);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* XXX: make it faster ? */
|
/* XXX: make it faster ? */
|
||||||
ST_FUNC void g(int c)
|
ST_FUNC void g(int c)
|
||||||
|
@ -335,17 +328,6 @@ static void gadd_sp(int val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined CONFIG_TCC_BCHECK || defined TCC_TARGET_PE
|
|
||||||
static void gen_static_call(int v)
|
|
||||||
{
|
|
||||||
Sym *sym;
|
|
||||||
|
|
||||||
sym = external_helper_sym(v);
|
|
||||||
oad(0xe8, -4);
|
|
||||||
greloc(cur_text_section, sym, ind-4, R_386_PC32);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* 'is_jmp' is '1' if it is a jump */
|
/* 'is_jmp' is '1' if it is a jump */
|
||||||
static void gcall_or_jmp(int is_jmp)
|
static void gcall_or_jmp(int is_jmp)
|
||||||
{
|
{
|
||||||
|
@ -401,11 +383,6 @@ ST_FUNC void gfunc_call(int nb_args)
|
||||||
int size, align, r, args_size, i, func_call;
|
int size, align, r, args_size, i, func_call;
|
||||||
Sym *func_sym;
|
Sym *func_sym;
|
||||||
|
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
|
||||||
if (tcc_state->do_bounds_check)
|
|
||||||
gbound_args(nb_args);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
args_size = 0;
|
args_size = 0;
|
||||||
for(i = 0;i < nb_args; i++) {
|
for(i = 0;i < nb_args; i++) {
|
||||||
if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
|
if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
|
||||||
|
@ -591,10 +568,6 @@ ST_FUNC void gfunc_prolog(Sym *func_sym)
|
||||||
func_ret_sub = 4;
|
func_ret_sub = 4;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
|
||||||
if (tcc_state->do_bounds_check)
|
|
||||||
gen_bounds_prolog();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* generate function epilog */
|
/* generate function epilog */
|
||||||
|
@ -602,11 +575,6 @@ ST_FUNC void gfunc_epilog(void)
|
||||||
{
|
{
|
||||||
addr_t v, saved_ind;
|
addr_t v, saved_ind;
|
||||||
|
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
|
||||||
if (tcc_state->do_bounds_check)
|
|
||||||
gen_bounds_epilog();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* align local size to word & save local variables */
|
/* align local size to word & save local variables */
|
||||||
v = (-loc + 3) & -4;
|
v = (-loc + 3) & -4;
|
||||||
|
|
||||||
|
@ -1043,55 +1011,6 @@ ST_FUNC void ggoto(void)
|
||||||
vtop--;
|
vtop--;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* bound check support functions */
|
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
|
||||||
|
|
||||||
static void gen_bounds_prolog(void)
|
|
||||||
{
|
|
||||||
/* leave some room for bound checking code */
|
|
||||||
func_bound_offset = lbounds_section->data_offset;
|
|
||||||
func_bound_ind = ind;
|
|
||||||
func_bound_add_epilog = 0;
|
|
||||||
oad(0xb8, 0); /* lbound section pointer */
|
|
||||||
oad(0xb8, 0); /* call to function */
|
|
||||||
}
|
|
||||||
|
|
||||||
static void gen_bounds_epilog(void)
|
|
||||||
{
|
|
||||||
addr_t saved_ind;
|
|
||||||
addr_t *bounds_ptr;
|
|
||||||
Sym *sym_data;
|
|
||||||
int offset_modified = func_bound_offset != lbounds_section->data_offset;
|
|
||||||
|
|
||||||
if (!offset_modified && !func_bound_add_epilog)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* add end of table info */
|
|
||||||
bounds_ptr = section_ptr_add(lbounds_section, sizeof(addr_t));
|
|
||||||
*bounds_ptr = 0;
|
|
||||||
|
|
||||||
sym_data = get_sym_ref(&char_pointer_type, lbounds_section,
|
|
||||||
func_bound_offset, PTR_SIZE);
|
|
||||||
|
|
||||||
/* generate bound local allocation */
|
|
||||||
if (offset_modified) {
|
|
||||||
saved_ind = ind;
|
|
||||||
ind = func_bound_ind;
|
|
||||||
greloc(cur_text_section, sym_data, ind + 1, R_386_32);
|
|
||||||
ind = ind + 5;
|
|
||||||
gen_static_call(TOK___bound_local_new);
|
|
||||||
ind = saved_ind;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* generate bound check local freeing */
|
|
||||||
o(0x5250); /* save returned value, if any */
|
|
||||||
greloc(cur_text_section, sym_data, ind + 1, R_386_32);
|
|
||||||
oad(0xb8, 0); /* mov %eax, xxx */
|
|
||||||
gen_static_call(TOK___bound_local_delete);
|
|
||||||
o(0x585a); /* restore returned value, if any */
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Save the stack pointer onto the stack */
|
/* Save the stack pointer onto the stack */
|
||||||
ST_FUNC void gen_vla_sp_save(int addr) {
|
ST_FUNC void gen_vla_sp_save(int addr) {
|
||||||
/* mov %esp,addr(%ebp)*/
|
/* mov %esp,addr(%ebp)*/
|
||||||
|
@ -1109,9 +1028,6 @@ ST_FUNC void gen_vla_sp_restore(int addr) {
|
||||||
ST_FUNC void gen_vla_alloc(CType *type, int align) {
|
ST_FUNC void gen_vla_alloc(CType *type, int align) {
|
||||||
int use_call = 0;
|
int use_call = 0;
|
||||||
|
|
||||||
#if defined(CONFIG_TCC_BCHECK)
|
|
||||||
use_call = tcc_state->do_bounds_check;
|
|
||||||
#endif
|
|
||||||
#ifdef TCC_TARGET_PE /* alloca does more than just adjust %rsp on Windows */
|
#ifdef TCC_TARGET_PE /* alloca does more than just adjust %rsp on Windows */
|
||||||
use_call = 1;
|
use_call = 1;
|
||||||
#endif
|
#endif
|
|
@ -99,11 +99,7 @@ ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_
|
||||||
int modrm;
|
int modrm;
|
||||||
unsigned plt_offset, relofs;
|
unsigned plt_offset, relofs;
|
||||||
|
|
||||||
/* on i386 if we build a DLL, we add a %ebx offset */
|
modrm = 0x25;
|
||||||
if (s1->output_type & TCC_OUTPUT_DYN)
|
|
||||||
modrm = 0xa3;
|
|
||||||
else
|
|
||||||
modrm = 0x25;
|
|
||||||
|
|
||||||
/* empty PLT: create PLT0 entry that pushes the library identifier
|
/* empty PLT: create PLT0 entry that pushes the library identifier
|
||||||
(GOT + PTR_SIZE) and jumps to ld.so resolution routine
|
(GOT + PTR_SIZE) and jumps to ld.so resolution routine
|
||||||
|
@ -148,7 +144,7 @@ ST_FUNC void relocate_plt(TCCState *s1)
|
||||||
p = s1->plt->data;
|
p = s1->plt->data;
|
||||||
p_end = p + s1->plt->data_offset;
|
p_end = p + s1->plt->data_offset;
|
||||||
|
|
||||||
if (!(s1->output_type & TCC_OUTPUT_DYN) && p < p_end) {
|
if (p < p_end) {
|
||||||
add32le(p + 2, s1->got->sh_addr);
|
add32le(p + 2, s1->got->sh_addr);
|
||||||
add32le(p + 8, s1->got->sh_addr);
|
add32le(p + 8, s1->got->sh_addr);
|
||||||
p += 16;
|
p += 16;
|
||||||
|
@ -179,31 +175,9 @@ ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case R_386_32:
|
case R_386_32:
|
||||||
if (s1->output_type & TCC_OUTPUT_DYN) {
|
|
||||||
esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index;
|
|
||||||
qrel->r_offset = rel->r_offset;
|
|
||||||
if (esym_index) {
|
|
||||||
qrel->r_info = ELFW(R_INFO)(esym_index, R_386_32);
|
|
||||||
qrel++;
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
qrel->r_info = ELFW(R_INFO)(0, R_386_RELATIVE);
|
|
||||||
qrel++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
add32le(ptr, val);
|
add32le(ptr, val);
|
||||||
return;
|
return;
|
||||||
case R_386_PC32:
|
case R_386_PC32:
|
||||||
if (s1->output_type == TCC_OUTPUT_DLL) {
|
|
||||||
/* DLL relocation */
|
|
||||||
esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index;
|
|
||||||
if (esym_index) {
|
|
||||||
qrel->r_offset = rel->r_offset;
|
|
||||||
qrel->r_info = ELFW(R_INFO)(esym_index, R_386_PC32);
|
|
||||||
qrel++;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
add32le(ptr, val - addr);
|
add32le(ptr, val - addr);
|
||||||
return;
|
return;
|
||||||
case R_386_PLT32:
|
case R_386_PLT32:
|
|
@ -266,7 +266,7 @@
|
||||||
#define DEF_ASM_OP1(name, opcode, group, instr_type, op0)
|
#define DEF_ASM_OP1(name, opcode, group, instr_type, op0)
|
||||||
#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1)
|
#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1)
|
||||||
#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2)
|
#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2)
|
||||||
#include "i386-asm.h"
|
#include "asm.h"
|
||||||
|
|
||||||
#define ALT(x)
|
#define ALT(x)
|
||||||
#define DEF_ASM_OP0(name, opcode)
|
#define DEF_ASM_OP0(name, opcode)
|
||||||
|
@ -274,4 +274,4 @@
|
||||||
#define DEF_ASM_OP1(name, opcode, group, instr_type, op0) DEF_ASM(name)
|
#define DEF_ASM_OP1(name, opcode, group, instr_type, op0) DEF_ASM(name)
|
||||||
#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) DEF_ASM(name)
|
#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) DEF_ASM(name)
|
||||||
#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) DEF_ASM(name)
|
#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) DEF_ASM(name)
|
||||||
#include "i386-asm.h"
|
#include "asm.h"
|
|
@ -19,6 +19,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "tcc.h"
|
#include "tcc.h"
|
||||||
|
#include "utils/string.h"
|
||||||
|
|
||||||
/********************************************************/
|
/********************************************************/
|
||||||
/* global variables */
|
/* global variables */
|
||||||
|
@ -78,44 +79,6 @@ PUB_FUNC void tcc_exit_state(TCCState *s1)
|
||||||
POST_SEM(&tcc_compile_sem);
|
POST_SEM(&tcc_compile_sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************/
|
|
||||||
/* copy a string and truncate it. */
|
|
||||||
ST_FUNC char *pstrcpy(char *buf, size_t buf_size, const char *s)
|
|
||||||
{
|
|
||||||
char *q, *q_end;
|
|
||||||
int c;
|
|
||||||
|
|
||||||
if (buf_size > 0) {
|
|
||||||
q = buf;
|
|
||||||
q_end = buf + buf_size - 1;
|
|
||||||
while (q < q_end) {
|
|
||||||
c = *s++;
|
|
||||||
if (c == '\0')
|
|
||||||
break;
|
|
||||||
*q++ = c;
|
|
||||||
}
|
|
||||||
*q = '\0';
|
|
||||||
}
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* strcat and truncate. */
|
|
||||||
ST_FUNC char *pstrcat(char *buf, size_t buf_size, const char *s)
|
|
||||||
{
|
|
||||||
size_t len;
|
|
||||||
len = strlen(buf);
|
|
||||||
if (len < buf_size)
|
|
||||||
pstrcpy(buf + len, buf_size - len, s);
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
ST_FUNC char *pstrncpy(char *out, const char *in, size_t num)
|
|
||||||
{
|
|
||||||
memcpy(out, in, num);
|
|
||||||
out[num] = '\0';
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* extract the basename of a file */
|
/* extract the basename of a file */
|
||||||
PUB_FUNC char *tcc_basename(const char *name)
|
PUB_FUNC char *tcc_basename(const char *name)
|
||||||
{
|
{
|
||||||
|
@ -180,7 +143,7 @@ ST_FUNC void libc_free(void *ptr)
|
||||||
/* global so that every tcc_alloc()/tcc_free() call doesn't need to be changed */
|
/* global so that every tcc_alloc()/tcc_free() call doesn't need to be changed */
|
||||||
static void *(*reallocator)(void*, unsigned long) = default_reallocator;
|
static void *(*reallocator)(void*, unsigned long) = default_reallocator;
|
||||||
|
|
||||||
LIBTCCAPI void tcc_set_realloc(TCCReallocFunc *realloc)
|
void tcc_set_realloc(TCCReallocFunc *realloc)
|
||||||
{
|
{
|
||||||
reallocator = realloc ? realloc : default_reallocator;
|
reallocator = realloc ? realloc : default_reallocator;
|
||||||
}
|
}
|
||||||
|
@ -574,7 +537,7 @@ static void error1(int mode, const char *fmt, va_list ap)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LIBTCCAPI void tcc_set_error_func(TCCState *s, void *error_opaque, TCCErrorFunc *error_func)
|
void tcc_set_error_func(TCCState *s, void *error_opaque, TCCErrorFunc *error_func)
|
||||||
{
|
{
|
||||||
s->error_opaque = error_opaque;
|
s->error_opaque = error_opaque;
|
||||||
s->error_func = error_func;
|
s->error_func = error_func;
|
||||||
|
@ -720,13 +683,13 @@ static int tcc_compile(TCCState *s1, int filetype, const char *str, int fd)
|
||||||
return s1->nb_errors != 0 ? -1 : 0;
|
return s1->nb_errors != 0 ? -1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
LIBTCCAPI int tcc_compile_string(TCCState *s, const char *str)
|
int tcc_compile_string(TCCState *s, const char *str)
|
||||||
{
|
{
|
||||||
return tcc_compile(s, s->filetype, str, -1);
|
return tcc_compile(s, s->filetype, str, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* define a preprocessor symbol. value can be NULL, sym can be "sym=val" */
|
/* define a preprocessor symbol. value can be NULL, sym can be "sym=val" */
|
||||||
LIBTCCAPI void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
|
void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
|
||||||
{
|
{
|
||||||
const char *eq;
|
const char *eq;
|
||||||
if (NULL == (eq = strchr(sym, '=')))
|
if (NULL == (eq = strchr(sym, '=')))
|
||||||
|
@ -737,13 +700,13 @@ LIBTCCAPI void tcc_define_symbol(TCCState *s1, const char *sym, const char *valu
|
||||||
}
|
}
|
||||||
|
|
||||||
/* undefine a preprocessor symbol */
|
/* undefine a preprocessor symbol */
|
||||||
LIBTCCAPI void tcc_undefine_symbol(TCCState *s1, const char *sym)
|
void tcc_undefine_symbol(TCCState *s1, const char *sym)
|
||||||
{
|
{
|
||||||
cstr_printf(&s1->cmdline_defs, "#undef %s\n", sym);
|
cstr_printf(&s1->cmdline_defs, "#undef %s\n", sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LIBTCCAPI TCCState *tcc_new(void)
|
TCCState *tcc_new(void)
|
||||||
{
|
{
|
||||||
TCCState *s;
|
TCCState *s;
|
||||||
|
|
||||||
|
@ -779,7 +742,7 @@ LIBTCCAPI TCCState *tcc_new(void)
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
LIBTCCAPI void tcc_delete(TCCState *s1)
|
void tcc_delete(TCCState *s1)
|
||||||
{
|
{
|
||||||
/* free sections */
|
/* free sections */
|
||||||
tccelf_delete(s1);
|
tccelf_delete(s1);
|
||||||
|
@ -808,7 +771,6 @@ LIBTCCAPI void tcc_delete(TCCState *s1)
|
||||||
cstr_free(&s1->cmdline_defs);
|
cstr_free(&s1->cmdline_defs);
|
||||||
cstr_free(&s1->cmdline_incl);
|
cstr_free(&s1->cmdline_incl);
|
||||||
cstr_free(&s1->linker_arg);
|
cstr_free(&s1->linker_arg);
|
||||||
tcc_free(s1->dState);
|
|
||||||
/* free loaded dlls array */
|
/* free loaded dlls array */
|
||||||
dynarray_reset(&s1->loaded_dlls, &s1->nb_loaded_dlls);
|
dynarray_reset(&s1->loaded_dlls, &s1->nb_loaded_dlls);
|
||||||
tcc_free(s1);
|
tcc_free(s1);
|
||||||
|
@ -817,12 +779,8 @@ LIBTCCAPI void tcc_delete(TCCState *s1)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
|
int tcc_set_output_type(TCCState *s, int output_type)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_TCC_PIE
|
|
||||||
if (output_type == TCC_OUTPUT_EXE)
|
|
||||||
output_type |= TCC_OUTPUT_DYN;
|
|
||||||
#endif
|
|
||||||
s->output_type = output_type;
|
s->output_type = output_type;
|
||||||
|
|
||||||
if (!s->nostdinc) {
|
if (!s->nostdinc) {
|
||||||
|
@ -832,7 +790,6 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (output_type == TCC_OUTPUT_PREPROCESS) {
|
if (output_type == TCC_OUTPUT_PREPROCESS) {
|
||||||
s->do_debug = 0;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -854,13 +811,13 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
LIBTCCAPI int tcc_add_include_path(TCCState *s, const char *pathname)
|
int tcc_add_include_path(TCCState *s, const char *pathname)
|
||||||
{
|
{
|
||||||
tcc_split_path(s, &s->include_paths, &s->nb_include_paths, pathname);
|
tcc_split_path(s, &s->include_paths, &s->nb_include_paths, pathname);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
LIBTCCAPI int tcc_add_sysinclude_path(TCCState *s, const char *pathname)
|
int tcc_add_sysinclude_path(TCCState *s, const char *pathname)
|
||||||
{
|
{
|
||||||
tcc_split_path(s, &s->sysinclude_paths, &s->nb_sysinclude_paths, pathname);
|
tcc_split_path(s, &s->sysinclude_paths, &s->nb_sysinclude_paths, pathname);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -932,45 +889,10 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
|
||||||
ret = tcc_load_archive(s1, fd, !(flags & AFF_WHOLE_ARCHIVE));
|
ret = tcc_load_archive(s1, fd, !(flags & AFF_WHOLE_ARCHIVE));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#ifdef TCC_TARGET_PE
|
case AFF_BINTYPE_COFF:
|
||||||
default:
|
ret = coff_load_file(s1, fd, filename);
|
||||||
ret = pe_load_file(s1, fd, filename);
|
break;
|
||||||
goto check_success;
|
|
||||||
|
|
||||||
#elif defined TCC_TARGET_MACHO
|
|
||||||
case AFF_BINTYPE_DYN:
|
|
||||||
case_dyn_or_tbd:
|
|
||||||
if (s1->output_type == TCC_OUTPUT_MEMORY) {
|
|
||||||
#ifdef TCC_IS_NATIVE
|
|
||||||
void* dl;
|
|
||||||
const char* soname = filename;
|
|
||||||
if (obj_type != AFF_BINTYPE_DYN)
|
|
||||||
soname = macho_tbd_soname(filename);
|
|
||||||
dl = dlopen(soname, RTLD_GLOBAL | RTLD_LAZY);
|
|
||||||
if (dl)
|
|
||||||
tcc_add_dllref(s1, soname, 0)->handle = dl, ret = 0;
|
|
||||||
if (filename != soname)
|
|
||||||
tcc_free((void *)soname);
|
|
||||||
#endif
|
|
||||||
} else if (obj_type == AFF_BINTYPE_DYN) {
|
|
||||||
ret = macho_load_dll(s1, fd, filename, (flags & AFF_REFERENCED_DLL) != 0);
|
|
||||||
} else {
|
|
||||||
ret = macho_load_tbd(s1, fd, filename, (flags & AFF_REFERENCED_DLL) != 0);
|
|
||||||
}
|
|
||||||
goto check_success;
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
const char *ext = tcc_fileextension(filename);
|
|
||||||
if (!strcmp(ext, ".tbd"))
|
|
||||||
goto case_dyn_or_tbd;
|
|
||||||
if (!strcmp(ext, ".dylib")) {
|
|
||||||
obj_type = AFF_BINTYPE_DYN;
|
|
||||||
goto case_dyn_or_tbd;
|
|
||||||
}
|
|
||||||
goto check_success;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else /* unix */
|
|
||||||
case AFF_BINTYPE_DYN:
|
case AFF_BINTYPE_DYN:
|
||||||
if (s1->output_type == TCC_OUTPUT_MEMORY) {
|
if (s1->output_type == TCC_OUTPUT_MEMORY) {
|
||||||
} else
|
} else
|
||||||
|
@ -980,20 +902,9 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
|
||||||
default:
|
default:
|
||||||
/* as GNU ld, consider it is an ld script if not recognized */
|
/* as GNU ld, consider it is an ld script if not recognized */
|
||||||
ret = tcc_load_ldscript(s1, fd);
|
ret = tcc_load_ldscript(s1, fd);
|
||||||
goto check_success;
|
|
||||||
|
|
||||||
#endif /* pe / macos / unix */
|
|
||||||
|
|
||||||
check_success:
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
tcc_error_noabort("%s: unrecognized file type", filename);
|
tcc_error_noabort("%s: unrecognized file type", filename);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#ifdef TCC_TARGET_COFF
|
|
||||||
case AFF_BINTYPE_C67:
|
|
||||||
ret = tcc_load_coff(s1, fd);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1030,12 +941,12 @@ static int guess_filetype(const char *filename)
|
||||||
return filetype;
|
return filetype;
|
||||||
}
|
}
|
||||||
|
|
||||||
LIBTCCAPI int tcc_add_file(TCCState *s, const char *filename)
|
int tcc_add_file(TCCState *s, const char *filename)
|
||||||
{
|
{
|
||||||
return tcc_add_file_internal(s, filename, s->filetype | AFF_PRINT_ERROR);
|
return tcc_add_file_internal(s, filename, s->filetype | AFF_PRINT_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname)
|
int tcc_add_library_path(TCCState *s, const char *pathname)
|
||||||
{
|
{
|
||||||
tcc_split_path(s, &s->library_paths, &s->nb_library_paths, pathname);
|
tcc_split_path(s, &s->library_paths, &s->nb_library_paths, pathname);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1074,7 +985,7 @@ ST_FUNC int tcc_add_support(TCCState *s1, const char *filename)
|
||||||
return tcc_add_dll(s1, filename, AFF_PRINT_ERROR);
|
return tcc_add_dll(s1, filename, AFF_PRINT_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined TCC_TARGET_PE && !defined TCC_TARGET_MACHO
|
#if !defined TCC_TARGET_PE
|
||||||
ST_FUNC int tcc_add_crt(TCCState *s1, const char *filename)
|
ST_FUNC int tcc_add_crt(TCCState *s1, const char *filename)
|
||||||
{
|
{
|
||||||
return tcc_add_library_internal(s1, "%s/%s",
|
return tcc_add_library_internal(s1, "%s/%s",
|
||||||
|
@ -1083,7 +994,7 @@ ST_FUNC int tcc_add_crt(TCCState *s1, const char *filename)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* the library name is the same as the argument of the '-l' option */
|
/* the library name is the same as the argument of the '-l' option */
|
||||||
LIBTCCAPI int tcc_add_library(TCCState *s, const char *libraryname)
|
int tcc_add_library(TCCState *s, const char *libraryname)
|
||||||
{
|
{
|
||||||
static const char * const libs[] = { "%s/lib%s.a", NULL };
|
static const char * const libs[] = { "%s/lib%s.a", NULL };
|
||||||
const char * const *pp = libs;
|
const char * const *pp = libs;
|
||||||
|
@ -1106,7 +1017,7 @@ ST_FUNC void tcc_add_pragma_libs(TCCState *s1)
|
||||||
tcc_add_library(s1, s1->pragma_libs[i]);
|
tcc_add_library(s1, s1->pragma_libs[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
LIBTCCAPI int tcc_add_symbol(TCCState *s1, const char *name, const void *val)
|
int tcc_add_symbol(TCCState *s1, const char *name, const void *val)
|
||||||
{
|
{
|
||||||
char buf[256];
|
char buf[256];
|
||||||
if (s1->leading_underscore) {
|
if (s1->leading_underscore) {
|
||||||
|
@ -1118,7 +1029,7 @@ LIBTCCAPI int tcc_add_symbol(TCCState *s1, const char *name, const void *val)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path)
|
void tcc_set_lib_path(TCCState *s, const char *path)
|
||||||
{
|
{
|
||||||
tcc_free(s->tcc_lib_path);
|
tcc_free(s->tcc_lib_path);
|
||||||
s->tcc_lib_path = tcc_strdup(path);
|
s->tcc_lib_path = tcc_strdup(path);
|
||||||
|
@ -1393,13 +1304,6 @@ static const TCCOption tcc_options[] = {
|
||||||
{ "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
|
{ "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
|
||||||
{ "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG },
|
{ "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG },
|
||||||
{ "bench", TCC_OPTION_bench, 0 },
|
{ "bench", TCC_OPTION_bench, 0 },
|
||||||
#ifdef CONFIG_TCC_BACKTRACE
|
|
||||||
{ "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
|
||||||
{ "b", TCC_OPTION_b, 0 },
|
|
||||||
#endif
|
|
||||||
{ "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
|
|
||||||
{ "c", TCC_OPTION_c, 0 },
|
{ "c", TCC_OPTION_c, 0 },
|
||||||
{ "dumpmachine", TCC_OPTION_dumpmachine, 0},
|
{ "dumpmachine", TCC_OPTION_dumpmachine, 0},
|
||||||
{ "dumpversion", TCC_OPTION_dumpversion, 0},
|
{ "dumpversion", TCC_OPTION_dumpversion, 0},
|
||||||
|
@ -1435,6 +1339,7 @@ static const TCCOption tcc_options[] = {
|
||||||
{ "ar", TCC_OPTION_ar, 0},
|
{ "ar", TCC_OPTION_ar, 0},
|
||||||
/* ignored (silently, except after -Wunsupported) */
|
/* ignored (silently, except after -Wunsupported) */
|
||||||
{ "arch", 0, TCC_OPTION_HAS_ARG},
|
{ "arch", 0, TCC_OPTION_HAS_ARG},
|
||||||
|
{ "g", 0, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP},
|
||||||
{ "C", 0, 0 },
|
{ "C", 0, 0 },
|
||||||
{ "-param", 0, TCC_OPTION_HAS_ARG },
|
{ "-param", 0, TCC_OPTION_HAS_ARG },
|
||||||
{ "pedantic", 0, 0 },
|
{ "pedantic", 0, 0 },
|
||||||
|
@ -1470,7 +1375,6 @@ static const FlagDef options_f[] = {
|
||||||
{ offsetof(TCCState, leading_underscore), 0, "leading-underscore" },
|
{ offsetof(TCCState, leading_underscore), 0, "leading-underscore" },
|
||||||
{ offsetof(TCCState, ms_extensions), 0, "ms-extensions" },
|
{ offsetof(TCCState, ms_extensions), 0, "ms-extensions" },
|
||||||
{ offsetof(TCCState, dollars_in_identifiers), 0, "dollars-in-identifiers" },
|
{ offsetof(TCCState, dollars_in_identifiers), 0, "dollars-in-identifiers" },
|
||||||
{ offsetof(TCCState, test_coverage), 0, "test-coverage" },
|
|
||||||
{ offsetof(TCCState, reverse_funcargs), 0, "reverse-funcargs" },
|
{ offsetof(TCCState, reverse_funcargs), 0, "reverse-funcargs" },
|
||||||
{ offsetof(TCCState, gnu89_inline), 0, "gnu89-inline" },
|
{ offsetof(TCCState, gnu89_inline), 0, "gnu89-inline" },
|
||||||
{ offsetof(TCCState, unwind_tables), 0, "asynchronous-unwind-tables" },
|
{ offsetof(TCCState, unwind_tables), 0, "asynchronous-unwind-tables" },
|
||||||
|
@ -1675,32 +1579,6 @@ dorun:
|
||||||
case TCC_OPTION_bench:
|
case TCC_OPTION_bench:
|
||||||
s->do_bench = 1;
|
s->do_bench = 1;
|
||||||
break;
|
break;
|
||||||
#ifdef CONFIG_TCC_BACKTRACE
|
|
||||||
case TCC_OPTION_bt:
|
|
||||||
s->rt_num_callers = atoi(optarg); /* zero = default (6) */
|
|
||||||
goto enable_backtrace;
|
|
||||||
enable_backtrace:
|
|
||||||
s->do_backtrace = 1;
|
|
||||||
s->do_debug = s->do_debug ? s->do_debug : 1;
|
|
||||||
s->dwarf = CONFIG_DWARF_VERSION;
|
|
||||||
break;
|
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
|
||||||
case TCC_OPTION_b:
|
|
||||||
s->do_bounds_check = 1;
|
|
||||||
goto enable_backtrace;
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
case TCC_OPTION_g:
|
|
||||||
s->do_debug = 2;
|
|
||||||
s->dwarf = CONFIG_DWARF_VERSION;
|
|
||||||
if (strstart("dwarf", &optarg)) {
|
|
||||||
s->dwarf = (*optarg) ? (0 - atoi(optarg)) : DEFAULT_DWARF_VERSION;
|
|
||||||
} else if (isnum(*optarg)) {
|
|
||||||
x = *optarg - '0';
|
|
||||||
/* -g0 = no info, -g1 = lines/functions only, -g2 = full info */
|
|
||||||
s->do_debug = x > 2 ? 2 : x == 0 && s->do_backtrace ? 1 : x;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case TCC_OPTION_c:
|
case TCC_OPTION_c:
|
||||||
x = TCC_OUTPUT_OBJ;
|
x = TCC_OUTPUT_OBJ;
|
||||||
set_output_type:
|
set_output_type:
|
||||||
|
@ -1713,8 +1591,6 @@ dorun:
|
||||||
s->dflag = 3;
|
s->dflag = 3;
|
||||||
else if (*optarg == 'M')
|
else if (*optarg == 'M')
|
||||||
s->dflag = 7;
|
s->dflag = 7;
|
||||||
else if (*optarg == 't')
|
|
||||||
s->dflag = 16;
|
|
||||||
else if (isnum(*optarg))
|
else if (isnum(*optarg))
|
||||||
s->g_debug |= atoi(optarg);
|
s->g_debug |= atoi(optarg);
|
||||||
else
|
else
|
||||||
|
@ -1727,9 +1603,6 @@ dorun:
|
||||||
if (strcmp(optarg, "=c11") == 0 || strcmp(optarg, "=gnu11") == 0)
|
if (strcmp(optarg, "=c11") == 0 || strcmp(optarg, "=gnu11") == 0)
|
||||||
s->cversion = 201112;
|
s->cversion = 201112;
|
||||||
break;
|
break;
|
||||||
case TCC_OPTION_shared:
|
|
||||||
x = TCC_OUTPUT_DLL;
|
|
||||||
goto set_output_type;
|
|
||||||
case TCC_OPTION_soname:
|
case TCC_OPTION_soname:
|
||||||
s->soname = tcc_strdup(optarg);
|
s->soname = tcc_strdup(optarg);
|
||||||
break;
|
break;
|
||||||
|
@ -1885,7 +1758,7 @@ unsupported_option:
|
||||||
return OPT_HELP;
|
return OPT_HELP;
|
||||||
}
|
}
|
||||||
|
|
||||||
LIBTCCAPI int tcc_set_options(TCCState *s, const char *r)
|
int tcc_set_options(TCCState *s, const char *r)
|
||||||
{
|
{
|
||||||
char **argv = NULL;
|
char **argv = NULL;
|
||||||
int argc = 0, ret;
|
int argc = 0, ret;
|
||||||
|
@ -1913,15 +1786,6 @@ PUB_FUNC void tcc_print_stats(TCCState *s1, unsigned total_time)
|
||||||
);
|
);
|
||||||
#ifdef MEM_DEBUG
|
#ifdef MEM_DEBUG
|
||||||
fprintf(stderr, "# memory usage");
|
fprintf(stderr, "# memory usage");
|
||||||
#ifdef TCC_IS_NATIVE
|
|
||||||
if (s1->run_size) {
|
|
||||||
Section *s = s1->symtab;
|
|
||||||
unsigned ms = s->data_offset + s->link->data_offset + s->hash->data_offset;
|
|
||||||
unsigned rs = s1->run_size;
|
|
||||||
fprintf(stderr, ": %d to run, %d symbols, %d other,",
|
|
||||||
rs, ms, mem_cur_size - rs - ms);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
fprintf(stderr, " %d max (bytes)\n", mem_max_size);
|
fprintf(stderr, " %d max (bytes)\n", mem_max_size);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
179
libtcc/libtcc.h
Normal file
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
|
# define strtoull _strtoui64
|
||||||
# endif
|
# endif
|
||||||
# ifdef LIBTCC_AS_DLL
|
# ifdef LIBTCC_AS_DLL
|
||||||
# define LIBTCCAPI __declspec(dllexport)
|
# define __declspec(dllexport)
|
||||||
# define PUB_FUNC LIBTCCAPI
|
# define PUB_FUNC LIBTCCAPI
|
||||||
# endif
|
# endif
|
||||||
# ifdef _MSC_VER
|
# ifdef _MSC_VER
|
||||||
|
@ -138,29 +138,8 @@ extern long double strtold (const char *__nptr, char **__endptr);
|
||||||
/* assembler debug */
|
/* assembler debug */
|
||||||
/* #define ASM_DEBUG */
|
/* #define ASM_DEBUG */
|
||||||
|
|
||||||
/* target selection */
|
|
||||||
/* #define TCC_TARGET_I386 *//* i386 code generator */
|
|
||||||
/* #define TCC_TARGET_X86_64 *//* x86-64 code generator */
|
|
||||||
/* #define TCC_TARGET_ARM *//* ARMv4 code generator */
|
|
||||||
/* #define TCC_TARGET_ARM64 *//* ARMv8 code generator */
|
|
||||||
/* #define TCC_TARGET_C67 *//* TMS320C67xx code generator */
|
|
||||||
/* #define TCC_TARGET_RISCV64 *//* risc-v code generator */
|
|
||||||
|
|
||||||
/* default target is I386 */
|
|
||||||
# define TCC_TARGET_I386
|
# define TCC_TARGET_I386
|
||||||
|
|
||||||
#if defined CONFIG_TCC_BACKTRACE && CONFIG_TCC_BACKTRACE==0
|
|
||||||
# undef CONFIG_TCC_BACKTRACE
|
|
||||||
#else
|
|
||||||
# define CONFIG_TCC_BACKTRACE 1 /* enable builtin stack backtraces */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined CONFIG_TCC_BCHECK && CONFIG_TCC_BCHECK==0
|
|
||||||
# undef CONFIG_TCC_BCHECK
|
|
||||||
#else
|
|
||||||
# define CONFIG_TCC_BCHECK 1 /* enable bound checking code */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_TCC_PIE
|
#ifdef CONFIG_TCC_PIE
|
||||||
# define CONFIG_TCC_PIC 1
|
# define CONFIG_TCC_PIC 1
|
||||||
#endif
|
#endif
|
||||||
|
@ -231,14 +210,6 @@ extern long double strtold (const char *__nptr, char **__endptr);
|
||||||
# define CONFIG_TCC_ELFINTERP "/lib/ld.so"
|
# define CONFIG_TCC_ELFINTERP "/lib/ld.so"
|
||||||
# elif defined(TCC_TARGET_PE)
|
# elif defined(TCC_TARGET_PE)
|
||||||
# define CONFIG_TCC_ELFINTERP "-"
|
# define CONFIG_TCC_ELFINTERP "-"
|
||||||
# elif defined TCC_TARGET_ARM64
|
|
||||||
# define CONFIG_TCC_ELFINTERP "/lib/ld-linux-aarch64.so.1"
|
|
||||||
# elif defined(TCC_TARGET_X86_64)
|
|
||||||
# define CONFIG_TCC_ELFINTERP "/lib64/ld-linux-x86-64.so.2"
|
|
||||||
# elif defined(TCC_TARGET_RISCV64)
|
|
||||||
# define CONFIG_TCC_ELFINTERP "/lib/ld-linux-riscv64-lp64d.so.1"
|
|
||||||
# elif defined(TCC_ARM_EABI)
|
|
||||||
# define DEFAULT_ELFINTERP(s) default_elfinterp(s)
|
|
||||||
# else
|
# else
|
||||||
# define CONFIG_TCC_ELFINTERP "/lib/ld-linux.so.2"
|
# define CONFIG_TCC_ELFINTERP "/lib/ld-linux.so.2"
|
||||||
# endif
|
# endif
|
||||||
|
@ -268,8 +239,7 @@ extern long double strtold (const char *__nptr, char **__endptr);
|
||||||
|
|
||||||
#include "libtcc.h"
|
#include "libtcc.h"
|
||||||
#include "elf.h"
|
#include "elf.h"
|
||||||
#include "stab.h"
|
#include "coff.h"
|
||||||
#include "dwarf.h"
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
|
@ -290,8 +260,8 @@ extern long double strtold (const char *__nptr, char **__endptr);
|
||||||
/* include the target specific definitions */
|
/* include the target specific definitions */
|
||||||
|
|
||||||
#define TARGET_DEFS_ONLY
|
#define TARGET_DEFS_ONLY
|
||||||
# include "i386-gen.c"
|
# include "i386/gen.c"
|
||||||
# include "i386-link.c"
|
# include "i386/link.c"
|
||||||
#undef TARGET_DEFS_ONLY
|
#undef TARGET_DEFS_ONLY
|
||||||
|
|
||||||
# define ELFCLASSW ELFCLASS32
|
# define ELFCLASSW ELFCLASS32
|
||||||
|
@ -606,9 +576,6 @@ struct sym_attr {
|
||||||
unsigned plt_offset;
|
unsigned plt_offset;
|
||||||
int plt_sym;
|
int plt_sym;
|
||||||
int dyn_index;
|
int dyn_index;
|
||||||
#ifdef TCC_TARGET_ARM
|
|
||||||
unsigned char plt_thumb_stub:1;
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TCCState {
|
struct TCCState {
|
||||||
|
@ -653,16 +620,6 @@ struct TCCState {
|
||||||
unsigned char include_sys_deps; /* option -MD */
|
unsigned char include_sys_deps; /* option -MD */
|
||||||
unsigned char gen_phony_deps; /* option -MP */
|
unsigned char gen_phony_deps; /* option -MP */
|
||||||
|
|
||||||
/* compile with debug symbol (and use them if error during execution) */
|
|
||||||
unsigned char do_debug;
|
|
||||||
unsigned char dwarf;
|
|
||||||
unsigned char do_backtrace;
|
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
|
||||||
/* compile with built-in memory and bounds checker */
|
|
||||||
unsigned char do_bounds_check;
|
|
||||||
#endif
|
|
||||||
unsigned char test_coverage; /* generate test coverage code */
|
|
||||||
|
|
||||||
/* use GNU C extensions */
|
/* use GNU C extensions */
|
||||||
unsigned char gnu_ext;
|
unsigned char gnu_ext;
|
||||||
/* use TinyCC extensions */
|
/* use TinyCC extensions */
|
||||||
|
@ -671,19 +628,11 @@ struct TCCState {
|
||||||
unsigned char dflag; /* -dX value */
|
unsigned char dflag; /* -dX value */
|
||||||
unsigned char Pflag; /* -P switch (LINE_MACRO_OUTPUT_FORMAT) */
|
unsigned char Pflag; /* -P switch (LINE_MACRO_OUTPUT_FORMAT) */
|
||||||
|
|
||||||
#ifdef TCC_TARGET_X86_64
|
|
||||||
unsigned char nosse; /* For -mno-sse support. */
|
|
||||||
#endif
|
|
||||||
#ifdef TCC_TARGET_ARM
|
|
||||||
unsigned char float_abi; /* float ABI of the generated code*/
|
|
||||||
#endif
|
|
||||||
|
|
||||||
unsigned char has_text_addr;
|
unsigned char has_text_addr;
|
||||||
addr_t text_addr; /* address of text section */
|
addr_t text_addr; /* address of text section */
|
||||||
unsigned section_align; /* section alignment */
|
unsigned section_align; /* section alignment */
|
||||||
#ifdef TCC_TARGET_I386
|
|
||||||
int seg_size; /* 32. Can be 16 with i386 assembler (.code16) */
|
int seg_size; /* 32. Can be 16 with i386 assembler (.code16) */
|
||||||
#endif
|
|
||||||
|
|
||||||
char *tcc_lib_path; /* CONFIG_TCCDIR or -B option */
|
char *tcc_lib_path; /* CONFIG_TCCDIR or -B option */
|
||||||
char *soname; /* as specified on the command line (-soname) */
|
char *soname; /* as specified on the command line (-soname) */
|
||||||
|
@ -697,8 +646,6 @@ struct TCCState {
|
||||||
int output_type;
|
int output_type;
|
||||||
/* output format, see TCC_OUTPUT_FORMAT_xxx */
|
/* output format, see TCC_OUTPUT_FORMAT_xxx */
|
||||||
int output_format;
|
int output_format;
|
||||||
/* nth test to run with -dt -run */
|
|
||||||
int run_test;
|
|
||||||
|
|
||||||
/* array of all loaded dlls (including those referenced by loaded dlls) */
|
/* array of all loaded dlls (including those referenced by loaded dlls) */
|
||||||
DLLReference **loaded_dlls;
|
DLLReference **loaded_dlls;
|
||||||
|
@ -772,11 +719,6 @@ struct TCCState {
|
||||||
Section *text_section, *data_section, *rodata_section, *bss_section;
|
Section *text_section, *data_section, *rodata_section, *bss_section;
|
||||||
Section *common_section;
|
Section *common_section;
|
||||||
Section *cur_text_section; /* current section where function code is generated */
|
Section *cur_text_section; /* current section where function code is generated */
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
|
||||||
/* bound check related sections */
|
|
||||||
Section *bounds_section; /* contains global data bound description */
|
|
||||||
Section *lbounds_section; /* contains local data bound description */
|
|
||||||
#endif
|
|
||||||
/* symbol section */
|
/* symbol section */
|
||||||
union { Section *symtab_section, *symtab; }; /* historical alias */
|
union { Section *symtab_section, *symtab; }; /* historical alias */
|
||||||
/* temporary dynamic symbol sections (for dll loading) */
|
/* temporary dynamic symbol sections (for dll loading) */
|
||||||
|
@ -789,19 +731,6 @@ struct TCCState {
|
||||||
Section *eh_frame_section;
|
Section *eh_frame_section;
|
||||||
Section *eh_frame_hdr_section;
|
Section *eh_frame_hdr_section;
|
||||||
unsigned long eh_start;
|
unsigned long eh_start;
|
||||||
/* debug sections */
|
|
||||||
Section *stab_section;
|
|
||||||
Section *dwarf_info_section;
|
|
||||||
Section *dwarf_abbrev_section;
|
|
||||||
Section *dwarf_line_section;
|
|
||||||
Section *dwarf_aranges_section;
|
|
||||||
Section *dwarf_str_section;
|
|
||||||
Section *dwarf_line_str_section;
|
|
||||||
int dwlo, dwhi; /* dwarf section range */
|
|
||||||
/* test coverage */
|
|
||||||
Section *tcov_section;
|
|
||||||
/* debug state */
|
|
||||||
struct _tccdbg *dState;
|
|
||||||
|
|
||||||
/* Is there a new undefined sym since last new_undef_sym() */
|
/* Is there a new undefined sym since last new_undef_sym() */
|
||||||
int new_undef_sym;
|
int new_undef_sym;
|
||||||
|
@ -812,11 +741,6 @@ struct TCCState {
|
||||||
ElfW_Rel *qrel;
|
ElfW_Rel *qrel;
|
||||||
#define qrel s1->qrel
|
#define qrel s1->qrel
|
||||||
|
|
||||||
#ifdef TCC_TARGET_RISCV64
|
|
||||||
struct pcrel_hi { addr_t addr, val; } last_hi;
|
|
||||||
#define last_hi s1->last_hi
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_TARGET_PE
|
||||||
/* PE info */
|
/* PE info */
|
||||||
int pe_subsystem;
|
int pe_subsystem;
|
||||||
|
@ -824,17 +748,6 @@ struct TCCState {
|
||||||
unsigned pe_file_align;
|
unsigned pe_file_align;
|
||||||
unsigned pe_stack_size;
|
unsigned pe_stack_size;
|
||||||
addr_t pe_imagebase;
|
addr_t pe_imagebase;
|
||||||
# ifdef TCC_TARGET_X86_64
|
|
||||||
Section *uw_pdata;
|
|
||||||
int uw_sym;
|
|
||||||
unsigned uw_offs;
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined TCC_TARGET_MACHO
|
|
||||||
char *install_name;
|
|
||||||
uint32_t compatibility_version;
|
|
||||||
uint32_t current_version;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef ELF_OBJ_ONLY
|
#ifndef ELF_OBJ_ONLY
|
||||||
|
@ -847,24 +760,6 @@ struct TCCState {
|
||||||
Section *verneed_section;
|
Section *verneed_section;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef TCC_IS_NATIVE
|
|
||||||
const char *run_main; /* entry for tcc_run() */
|
|
||||||
void *run_ptr; /* runtime_memory */
|
|
||||||
unsigned run_size; /* size of runtime_memory */
|
|
||||||
#ifdef _WIN64
|
|
||||||
void *run_function_table; /* unwind data */
|
|
||||||
#endif
|
|
||||||
struct TCCState *next;
|
|
||||||
struct rt_context *rc; /* pointer to backtrace info block */
|
|
||||||
void *run_lj, *run_jb; /* sj/lj for tcc_setjmp()/tcc_run() */
|
|
||||||
TCCBtFunc *bt_func;
|
|
||||||
void *bt_data;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_TCC_BACKTRACE
|
|
||||||
int rt_num_callers;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* benchmark info */
|
/* benchmark info */
|
||||||
int total_idents;
|
int total_idents;
|
||||||
int total_lines;
|
int total_lines;
|
||||||
|
@ -1079,9 +974,6 @@ ST_DATA void** stk_data;
|
||||||
ST_DATA int nb_stk_data;
|
ST_DATA int nb_stk_data;
|
||||||
|
|
||||||
/* public functions currently used by the tcc main function */
|
/* public functions currently used by the tcc main function */
|
||||||
ST_FUNC char *pstrcpy(char *buf, size_t buf_size, const char *s);
|
|
||||||
ST_FUNC char *pstrcat(char *buf, size_t buf_size, const char *s);
|
|
||||||
ST_FUNC char *pstrncpy(char *out, const char *in, size_t num);
|
|
||||||
PUB_FUNC char *tcc_basename(const char *name);
|
PUB_FUNC char *tcc_basename(const char *name);
|
||||||
PUB_FUNC char *tcc_fileextension (const char *name);
|
PUB_FUNC char *tcc_fileextension (const char *name);
|
||||||
|
|
||||||
|
@ -1153,10 +1045,10 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
|
||||||
#define AFF_TYPE_LIB 8
|
#define AFF_TYPE_LIB 8
|
||||||
#define AFF_TYPE_MASK (15 | AFF_TYPE_BIN)
|
#define AFF_TYPE_MASK (15 | AFF_TYPE_BIN)
|
||||||
/* values from tcc_object_type(...) */
|
/* values from tcc_object_type(...) */
|
||||||
#define AFF_BINTYPE_REL 1
|
#define AFF_BINTYPE_REL 1
|
||||||
#define AFF_BINTYPE_DYN 2
|
#define AFF_BINTYPE_DYN 2
|
||||||
#define AFF_BINTYPE_AR 3
|
#define AFF_BINTYPE_AR 3
|
||||||
#define AFF_BINTYPE_C67 4
|
#define AFF_BINTYPE_COFF 4
|
||||||
|
|
||||||
/* return value of tcc_add_file_internal(): 0, -1, or FILE_NOT_FOUND */
|
/* return value of tcc_add_file_internal(): 0, -1, or FILE_NOT_FOUND */
|
||||||
#define FILE_NOT_FOUND -2
|
#define FILE_NOT_FOUND -2
|
||||||
|
@ -1166,12 +1058,7 @@ ST_FUNC int tcc_add_crt(TCCState *s, const char *filename);
|
||||||
#endif
|
#endif
|
||||||
ST_FUNC int tcc_add_dll(TCCState *s, const char *filename, int flags);
|
ST_FUNC int tcc_add_dll(TCCState *s, const char *filename, int flags);
|
||||||
ST_FUNC int tcc_add_support(TCCState *s1, const char *filename);
|
ST_FUNC int tcc_add_support(TCCState *s1, const char *filename);
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
|
||||||
ST_FUNC void tcc_add_bcheck(TCCState *s1);
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_TCC_BACKTRACE
|
|
||||||
ST_FUNC void tcc_add_btstub(TCCState *s1);
|
|
||||||
#endif
|
|
||||||
ST_FUNC void tcc_add_pragma_libs(TCCState *s1);
|
ST_FUNC void tcc_add_pragma_libs(TCCState *s1);
|
||||||
PUB_FUNC int tcc_add_library_err(TCCState *s, const char *f);
|
PUB_FUNC int tcc_add_library_err(TCCState *s, const char *f);
|
||||||
PUB_FUNC void tcc_print_stats(TCCState *s, unsigned total_time);
|
PUB_FUNC void tcc_print_stats(TCCState *s, unsigned total_time);
|
||||||
|
@ -1353,9 +1240,6 @@ ST_FUNC void vpop(void);
|
||||||
#if PTR_SIZE == 4
|
#if PTR_SIZE == 4
|
||||||
ST_FUNC void lexpand(void);
|
ST_FUNC void lexpand(void);
|
||||||
#endif
|
#endif
|
||||||
#ifdef TCC_TARGET_ARM
|
|
||||||
ST_FUNC int get_reg_ex(int rc, int rc2);
|
|
||||||
#endif
|
|
||||||
ST_FUNC void save_reg(int r);
|
ST_FUNC void save_reg(int r);
|
||||||
ST_FUNC void save_reg_upstack(int r, int n);
|
ST_FUNC void save_reg_upstack(int r, int n);
|
||||||
ST_FUNC int get_reg(int rc);
|
ST_FUNC int get_reg(int rc);
|
||||||
|
@ -1374,23 +1258,12 @@ ST_FUNC void indir(void);
|
||||||
ST_FUNC void unary(void);
|
ST_FUNC void unary(void);
|
||||||
ST_FUNC void gexpr(void);
|
ST_FUNC void gexpr(void);
|
||||||
ST_FUNC int expr_const(void);
|
ST_FUNC int expr_const(void);
|
||||||
#if defined CONFIG_TCC_BCHECK || defined TCC_TARGET_C67
|
|
||||||
ST_FUNC Sym *get_sym_ref(CType *type, Section *sec, unsigned long offset, unsigned long size);
|
|
||||||
#endif
|
|
||||||
#if defined TCC_TARGET_X86_64 && !defined TCC_TARGET_PE
|
|
||||||
ST_FUNC int classify_x86_64_va_arg(CType *ty);
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
|
||||||
ST_FUNC void gbound_args(int nb_args);
|
|
||||||
ST_DATA int func_bound_add_epilog;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* ------------ tccelf.c ------------ */
|
/* ------------ tccelf.c ------------ */
|
||||||
|
|
||||||
#define TCC_OUTPUT_FORMAT_ELF 0 /* default output format: ELF */
|
#define TCC_OUTPUT_FORMAT_ELF 0 /* default output format: ELF */
|
||||||
#define TCC_OUTPUT_FORMAT_BINARY 1 /* binary image output */
|
#define TCC_OUTPUT_FORMAT_BINARY 1 /* binary image output */
|
||||||
#define TCC_OUTPUT_FORMAT_COFF 2 /* COFF */
|
#define TCC_OUTPUT_FORMAT_COFF 2 /* COFF */
|
||||||
#define TCC_OUTPUT_DYN TCC_OUTPUT_DLL
|
|
||||||
|
|
||||||
#define ARMAG "!<arch>\n" /* For COFF and a.out archives */
|
#define ARMAG "!<arch>\n" /* For COFF and a.out archives */
|
||||||
|
|
||||||
|
@ -1455,9 +1328,11 @@ ST_FUNC void tccelf_add_crtend(TCCState *s1);
|
||||||
ST_FUNC void tcc_add_runtime(TCCState *s1);
|
ST_FUNC void tcc_add_runtime(TCCState *s1);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
int coff_load_file(TCCState *s1, int fd, const char *fname);
|
||||||
|
|
||||||
/* ------------ xxx-link.c ------------ */
|
/* ------------ xxx-link.c ------------ */
|
||||||
|
|
||||||
#if !defined ELF_OBJ_ONLY || defined TCC_TARGET_MACHO
|
#if !defined ELF_OBJ_ONLY
|
||||||
ST_FUNC int code_reloc (int reloc_type);
|
ST_FUNC int code_reloc (int reloc_type);
|
||||||
ST_FUNC int gotplt_entry_type (int reloc_type);
|
ST_FUNC int gotplt_entry_type (int reloc_type);
|
||||||
/* Whether to generate a GOT/PLT entry and when. NO_GOTPLT_ENTRY is first so
|
/* Whether to generate a GOT/PLT entry and when. NO_GOTPLT_ENTRY is first so
|
||||||
|
@ -1470,13 +1345,11 @@ enum gotplt_entry {
|
||||||
};
|
};
|
||||||
#define NEED_RELOC_TYPE
|
#define NEED_RELOC_TYPE
|
||||||
|
|
||||||
#if !defined TCC_TARGET_MACHO || defined TCC_IS_NATIVE
|
|
||||||
ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr);
|
ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr);
|
||||||
ST_FUNC void relocate_plt(TCCState *s1);
|
ST_FUNC void relocate_plt(TCCState *s1);
|
||||||
ST_FUNC void build_got_entries(TCCState *s1, int got_sym); /* in tccelf.c */
|
ST_FUNC void build_got_entries(TCCState *s1, int got_sym); /* in tccelf.c */
|
||||||
#define NEED_BUILD_GOT
|
#define NEED_BUILD_GOT
|
||||||
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val);
|
ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val);
|
||||||
|
@ -1504,9 +1377,7 @@ ST_FUNC void gen_cvt_ftoi(int t);
|
||||||
ST_FUNC void gen_cvt_itof(int t);
|
ST_FUNC void gen_cvt_itof(int t);
|
||||||
ST_FUNC void gen_cvt_ftof(int t);
|
ST_FUNC void gen_cvt_ftof(int t);
|
||||||
ST_FUNC void ggoto(void);
|
ST_FUNC void ggoto(void);
|
||||||
#ifndef TCC_TARGET_C67
|
|
||||||
ST_FUNC void o(unsigned int c);
|
ST_FUNC void o(unsigned int c);
|
||||||
#endif
|
|
||||||
ST_FUNC void gen_vla_sp_save(int addr);
|
ST_FUNC void gen_vla_sp_save(int addr);
|
||||||
ST_FUNC void gen_vla_sp_restore(int addr);
|
ST_FUNC void gen_vla_sp_restore(int addr);
|
||||||
ST_FUNC void gen_vla_alloc(CType *type, int align);
|
ST_FUNC void gen_vla_alloc(CType *type, int align);
|
||||||
|
@ -1584,17 +1455,15 @@ dwarf_read_sleb128(unsigned char **ln, unsigned char *end)
|
||||||
|
|
||||||
|
|
||||||
/* ------------ i386-gen.c ------------ */
|
/* ------------ i386-gen.c ------------ */
|
||||||
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 || defined TCC_TARGET_ARM
|
|
||||||
ST_FUNC void g(int c);
|
ST_FUNC void g(int c);
|
||||||
ST_FUNC void gen_le16(int c);
|
ST_FUNC void gen_le16(int c);
|
||||||
ST_FUNC void gen_le32(int c);
|
ST_FUNC void gen_le32(int c);
|
||||||
#endif
|
|
||||||
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
|
|
||||||
ST_FUNC void gen_addr32(int r, Sym *sym, int c);
|
ST_FUNC void gen_addr32(int r, Sym *sym, int c);
|
||||||
ST_FUNC void gen_addrpc32(int r, Sym *sym, int c);
|
ST_FUNC void gen_addrpc32(int r, Sym *sym, int c);
|
||||||
ST_FUNC void gen_cvt_csti(int t);
|
ST_FUNC void gen_cvt_csti(int t);
|
||||||
ST_FUNC void gen_increment_tcov (SValue *sv);
|
ST_FUNC void gen_increment_tcov (SValue *sv);
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1626,47 +1495,8 @@ ST_FUNC void asm_clobber(uint8_t *clobber_regs, const char *str);
|
||||||
#define ST_ASM_SET 0x04
|
#define ST_ASM_SET 0x04
|
||||||
|
|
||||||
|
|
||||||
/* ------------ tcctools.c ----------------- */
|
|
||||||
#if 0 /* included in tcc.c */
|
|
||||||
ST_FUNC int tcc_tool_ar(TCCState *s, int argc, char **argv);
|
|
||||||
ST_FUNC int tcc_tool_cross(TCCState *s, char **argv, int option);
|
|
||||||
ST_FUNC int gen_makedeps(TCCState *s, const char *target, const char *filename);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* ------------ tccdbg.c ------------ */
|
/* ------------ tccdbg.c ------------ */
|
||||||
|
|
||||||
ST_FUNC void tcc_debug_new(TCCState *s);
|
|
||||||
|
|
||||||
ST_FUNC void tcc_debug_start(TCCState *s1);
|
|
||||||
ST_FUNC void tcc_debug_end(TCCState *s1);
|
|
||||||
ST_FUNC void tcc_debug_bincl(TCCState *s1);
|
|
||||||
ST_FUNC void tcc_debug_eincl(TCCState *s1);
|
|
||||||
ST_FUNC void tcc_debug_newfile(TCCState *s1);
|
|
||||||
|
|
||||||
ST_FUNC void tcc_debug_line(TCCState *s1);
|
|
||||||
ST_FUNC void tcc_add_debug_info(TCCState *s1, int param, Sym *s, Sym *e);
|
|
||||||
ST_FUNC void tcc_debug_funcstart(TCCState *s1, Sym *sym);
|
|
||||||
ST_FUNC void tcc_debug_prolog_epilog(TCCState *s1, int value);
|
|
||||||
ST_FUNC void tcc_debug_funcend(TCCState *s1, int size);
|
|
||||||
ST_FUNC void tcc_debug_extern_sym(TCCState *s1, Sym *sym, int sh_num, int sym_bind, int sym_type);
|
|
||||||
ST_FUNC void tcc_debug_typedef(TCCState *s1, Sym *sym);
|
|
||||||
ST_FUNC void tcc_debug_stabn(TCCState *s1, int type, int value);
|
|
||||||
ST_FUNC void tcc_debug_fix_anon(TCCState *s1, CType *t);
|
|
||||||
|
|
||||||
#if !(defined ELF_OBJ_ONLY || defined TCC_TARGET_ARM || defined TARGETOS_BSD)
|
|
||||||
ST_FUNC void tcc_eh_frame_start(TCCState *s1);
|
|
||||||
ST_FUNC void tcc_eh_frame_end(TCCState *s1);
|
|
||||||
ST_FUNC void tcc_eh_frame_hdr(TCCState *s1, int final);
|
|
||||||
#define TCC_EH_FRAME 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ST_FUNC void tcc_tcov_start(TCCState *s1);
|
|
||||||
ST_FUNC void tcc_tcov_end(TCCState *s1);
|
|
||||||
ST_FUNC void tcc_tcov_check_line(TCCState *s1, int start);
|
|
||||||
ST_FUNC void tcc_tcov_block_end(TCCState *s1, int line);
|
|
||||||
ST_FUNC void tcc_tcov_block_begin(TCCState *s1);
|
|
||||||
ST_FUNC void tcc_tcov_reset_ind(TCCState *s1);
|
|
||||||
|
|
||||||
#define stab_section s1->stab_section
|
#define stab_section s1->stab_section
|
||||||
#define stabstr_section stab_section->link
|
#define stabstr_section stab_section->link
|
||||||
#define tcov_section s1->tcov_section
|
#define tcov_section s1->tcov_section
|
||||||
|
@ -1679,12 +1509,6 @@ ST_FUNC void tcc_tcov_reset_ind(TCCState *s1);
|
||||||
#define dwarf_str_section s1->dwarf_str_section
|
#define dwarf_str_section s1->dwarf_str_section
|
||||||
#define dwarf_line_str_section s1->dwarf_line_str_section
|
#define dwarf_line_str_section s1->dwarf_line_str_section
|
||||||
|
|
||||||
/* default dwarf version for "-gdwarf" */
|
|
||||||
#ifdef TCC_TARGET_MACHO
|
|
||||||
# define DEFAULT_DWARF_VERSION 2
|
|
||||||
#else
|
|
||||||
# define DEFAULT_DWARF_VERSION 5
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* default dwarf version for "-g". use 0 to emit stab debug infos */
|
/* default dwarf version for "-g". use 0 to emit stab debug infos */
|
||||||
#ifndef CONFIG_DWARF_VERSION
|
#ifndef CONFIG_DWARF_VERSION
|
||||||
|
@ -1693,8 +1517,6 @@ ST_FUNC void tcc_tcov_reset_ind(TCCState *s1);
|
||||||
|
|
||||||
#if defined TCC_TARGET_PE
|
#if defined TCC_TARGET_PE
|
||||||
# define R_DATA_32DW 'Z' /* fake code to avoid DLL relocs */
|
# define R_DATA_32DW 'Z' /* fake code to avoid DLL relocs */
|
||||||
#elif defined TCC_TARGET_X86_64
|
|
||||||
# define R_DATA_32DW R_X86_64_32
|
|
||||||
#else
|
#else
|
||||||
# define R_DATA_32DW R_DATA_32
|
# define R_DATA_32DW R_DATA_32
|
||||||
#endif
|
#endif
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
#define USING_GLOBALS
|
#define USING_GLOBALS
|
||||||
#include "tcc.h"
|
#include "tcc.h"
|
||||||
|
#include "utils/string.h"
|
||||||
#ifdef CONFIG_TCC_ASM
|
#ifdef CONFIG_TCC_ASM
|
||||||
|
|
||||||
static Section *last_text_section; /* to handle .previous asm directive */
|
static Section *last_text_section; /* to handle .previous asm directive */
|
||||||
|
@ -958,7 +959,6 @@ static int tcc_assemble_internal(TCCState *s1, int do_preprocess, int global)
|
||||||
next();
|
next();
|
||||||
if (tok == TOK_EOF)
|
if (tok == TOK_EOF)
|
||||||
break;
|
break;
|
||||||
tcc_debug_line(s1);
|
|
||||||
parse_flags |= PARSE_FLAG_LINEFEED; /* XXX: suppress that hack */
|
parse_flags |= PARSE_FLAG_LINEFEED; /* XXX: suppress that hack */
|
||||||
redo:
|
redo:
|
||||||
if (tok == '#') {
|
if (tok == '#') {
|
||||||
|
@ -1009,14 +1009,12 @@ static int tcc_assemble_internal(TCCState *s1, int do_preprocess, int global)
|
||||||
ST_FUNC int tcc_assemble(TCCState *s1, int do_preprocess)
|
ST_FUNC int tcc_assemble(TCCState *s1, int do_preprocess)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
tcc_debug_start(s1);
|
|
||||||
/* default section is text */
|
/* default section is text */
|
||||||
cur_text_section = text_section;
|
cur_text_section = text_section;
|
||||||
ind = cur_text_section->data_offset;
|
ind = cur_text_section->data_offset;
|
||||||
nocode_wanted = 0;
|
nocode_wanted = 0;
|
||||||
ret = tcc_assemble_internal(s1, do_preprocess, 1);
|
ret = tcc_assemble_internal(s1, do_preprocess, 1);
|
||||||
cur_text_section->data_offset = ind;
|
cur_text_section->data_offset = ind;
|
||||||
tcc_debug_end(s1);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,14 +15,29 @@ coff_load_lib(TCCState *s1, int fd)
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
coff_merge_or_create(void)
|
||||||
|
{
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
coff_resolve_symbols(void)
|
||||||
|
{
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
coff_load_obj(TCCState *s1, int fd)
|
coff_load_obj(TCCState *s1, int fd)
|
||||||
{
|
{
|
||||||
FILHDR hdr;
|
FILHDR hdr;
|
||||||
SCNHDR *scns;
|
SCNHDR *scns;
|
||||||
SYMENT *syments;
|
SYMENT *syments;
|
||||||
|
RELOC *relocs;
|
||||||
|
Section *s;
|
||||||
uint16_t i;
|
uint16_t i;
|
||||||
int32_t j;
|
int32_t j;
|
||||||
|
int k;
|
||||||
char buff[9];
|
char buff[9];
|
||||||
|
|
||||||
if (!read_mem(fd, 0, &hdr, FILHSZ))
|
if (!read_mem(fd, 0, &hdr, FILHSZ))
|
||||||
|
@ -31,8 +46,6 @@ coff_load_obj(TCCState *s1, int fd)
|
||||||
if (hdr.f_magic != F_MACH_I386 || hdr.f_flags & F_EXEC)
|
if (hdr.f_magic != F_MACH_I386 || hdr.f_flags & F_EXEC)
|
||||||
return (tcc_error_noabort("invalid coff object file"));
|
return (tcc_error_noabort("invalid coff object file"));
|
||||||
|
|
||||||
/* load symtab */
|
|
||||||
|
|
||||||
/* read sections */
|
/* read sections */
|
||||||
scns = tcc_malloc(SCNHSZ * hdr.f_nscns);
|
scns = tcc_malloc(SCNHSZ * hdr.f_nscns);
|
||||||
if (!read_mem(fd, FILHSZ, scns, SCNHSZ * hdr.f_nscns))
|
if (!read_mem(fd, FILHSZ, scns, SCNHSZ * hdr.f_nscns))
|
||||||
|
@ -46,6 +59,17 @@ coff_load_obj(TCCState *s1, int fd)
|
||||||
memset(buff, 0, 9);
|
memset(buff, 0, 9);
|
||||||
memcpy(buff, scns[i].s_name, 8);
|
memcpy(buff, scns[i].s_name, 8);
|
||||||
printf("sec: %s\n", buff);
|
printf("sec: %s\n", buff);
|
||||||
|
|
||||||
|
for (k = 1; k < s1->nb_sections; k++)
|
||||||
|
{
|
||||||
|
if (strcmp(s1->sections[k]->name, buff) != 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* load symtab */
|
/* load symtab */
|
||||||
|
@ -54,7 +78,7 @@ coff_load_obj(TCCState *s1, int fd)
|
||||||
for (j = 0; j < hdr.f_nsyms; j++)
|
for (j = 0; j < hdr.f_nsyms; j++)
|
||||||
{
|
{
|
||||||
memset(buff, 0, 9);
|
memset(buff, 0, 9);
|
||||||
memcpy(buff, syments[i].n_name, 8);
|
memcpy(buff, syments[j].n_name, 8);
|
||||||
printf("sym: %s\n", buff);
|
printf("sym: %s\n", buff);
|
||||||
}
|
}
|
||||||
|
|
951
libtcc/tcccoff.c_old.c
Normal file
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 "tcc.h"
|
||||||
|
#include "utils/string.h"
|
||||||
|
|
||||||
/* Define this to get some debug output during relocation processing. */
|
/* Define this to get some debug output during relocation processing. */
|
||||||
#undef DEBUG_RELOC
|
#undef DEBUG_RELOC
|
||||||
|
@ -84,26 +85,6 @@ ST_FUNC void tccelf_new(TCCState *s)
|
||||||
".dynhashtab", SHF_PRIVATE);
|
".dynhashtab", SHF_PRIVATE);
|
||||||
get_sym_attr(s, 0, 1);
|
get_sym_attr(s, 0, 1);
|
||||||
|
|
||||||
if (s->do_debug) {
|
|
||||||
/* add debug sections */
|
|
||||||
tcc_debug_new(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if TCC_EH_FRAME
|
|
||||||
if (s->output_format != TCC_OUTPUT_FORMAT_ELF)
|
|
||||||
s->unwind_tables = 0;
|
|
||||||
tcc_eh_frame_start(s);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
|
||||||
if (s->do_bounds_check) {
|
|
||||||
/* if bound checking, then add corresponding sections */
|
|
||||||
/* (make ro after relocation done with GNU_RELRO) */
|
|
||||||
bounds_section = new_section(s, ".bounds", SHT_PROGBITS, shf_RELRO);
|
|
||||||
lbounds_section = new_section(s, ".lbounds", SHT_PROGBITS, shf_RELRO);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_TARGET_PE
|
||||||
/* to make sure that -ltcc1 -Wl,-e,_start will grab the startup code
|
/* to make sure that -ltcc1 -Wl,-e,_start will grab the startup code
|
||||||
from libtcc1.a (unless _start defined) */
|
from libtcc1.a (unless _start defined) */
|
||||||
|
@ -158,10 +139,6 @@ ST_FUNC void tccelf_begin_file(TCCState *s1)
|
||||||
}
|
}
|
||||||
/* disable symbol hashing during compilation */
|
/* disable symbol hashing during compilation */
|
||||||
s = s1->symtab, s->reloc = s->hash, s->hash = NULL;
|
s = s1->symtab, s->reloc = s->hash, s->hash = NULL;
|
||||||
#if defined TCC_TARGET_X86_64 && defined TCC_TARGET_PE
|
|
||||||
s1->uw_sym = 0;
|
|
||||||
s1->uw_offs = 0;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void update_relocs(TCCState *s1, Section *s, int *old_to_new_syms, int first_sym);
|
static void update_relocs(TCCState *s1, Section *s, int *old_to_new_syms, int first_sym);
|
||||||
|
@ -520,7 +497,7 @@ ST_FUNC addr_t get_sym_addr(TCCState *s1, const char *name, int err, int forc)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return elf symbol value */
|
/* return elf symbol value */
|
||||||
LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name)
|
void *tcc_get_symbol(TCCState *s, const char *name)
|
||||||
{
|
{
|
||||||
addr_t addr = get_sym_addr(s, name, 0, 1);
|
addr_t addr = get_sym_addr(s, name, 0, 1);
|
||||||
return addr == -1 ? NULL : (void*)(uintptr_t)addr;
|
return addr == -1 ? NULL : (void*)(uintptr_t)addr;
|
||||||
|
@ -551,7 +528,7 @@ ST_FUNC void list_elf_symbols(TCCState *s, void *ctx,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* list elf symbol names and values */
|
/* list elf symbol names and values */
|
||||||
LIBTCCAPI void tcc_list_symbols(TCCState *s, void *ctx,
|
void tcc_list_symbols(TCCState *s, void *ctx,
|
||||||
void (*symbol_cb)(void *ctx, const char *name, const void *val))
|
void (*symbol_cb)(void *ctx, const char *name, const void *val))
|
||||||
{
|
{
|
||||||
list_elf_symbols(s, ctx, symbol_cb);
|
list_elf_symbols(s, ctx, symbol_cb);
|
||||||
|
@ -1056,25 +1033,6 @@ ST_FUNC void relocate_syms(TCCState *s1, Section *symtab, int do_resolve)
|
||||||
name = (char *) s1->symtab->link->data + sym->st_name;
|
name = (char *) s1->symtab->link->data + sym->st_name;
|
||||||
/* Use ld.so to resolve symbol for us (for tcc -run) */
|
/* Use ld.so to resolve symbol for us (for tcc -run) */
|
||||||
if (do_resolve) {
|
if (do_resolve) {
|
||||||
#if defined TCC_IS_NATIVE && !defined TCC_TARGET_PE
|
|
||||||
/* dlsym() needs the undecorated name. */
|
|
||||||
void *addr = dlsym(RTLD_DEFAULT, &name[s1->leading_underscore]);
|
|
||||||
#if TARGETOS_OpenBSD || TARGETOS_FreeBSD || TARGETOS_NetBSD || TARGETOS_ANDROID
|
|
||||||
if (addr == NULL) {
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < s1->nb_loaded_dlls; i++)
|
|
||||||
if ((addr = dlsym(s1->loaded_dlls[i]->handle, name)))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (addr) {
|
|
||||||
sym->st_value = (addr_t) addr;
|
|
||||||
#ifdef DEBUG_RELOC
|
|
||||||
printf ("relocate_sym: %s -> 0x%lx\n", name, sym->st_value);
|
|
||||||
#endif
|
|
||||||
goto found;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
/* if dynamic symbol exist, it will be used in relocate_section */
|
/* if dynamic symbol exist, it will be used in relocate_section */
|
||||||
} else if (s1->dynsym && find_elf_sym(s1->dynsym, name))
|
} else if (s1->dynsym && find_elf_sym(s1->dynsym, name))
|
||||||
goto found;
|
goto found;
|
||||||
|
@ -1107,7 +1065,6 @@ static void relocate_section(TCCState *s1, Section *s, Section *sr)
|
||||||
int type, sym_index;
|
int type, sym_index;
|
||||||
unsigned char *ptr;
|
unsigned char *ptr;
|
||||||
addr_t tgt, addr;
|
addr_t tgt, addr;
|
||||||
int is_dwarf = s->sh_num >= s1->dwlo && s->sh_num < s1->dwhi;
|
|
||||||
|
|
||||||
qrel = (ElfW_Rel *)sr->data;
|
qrel = (ElfW_Rel *)sr->data;
|
||||||
for_each_elem(sr, 0, rel, ElfW_Rel) {
|
for_each_elem(sr, 0, rel, ElfW_Rel) {
|
||||||
|
@ -1119,12 +1076,6 @@ static void relocate_section(TCCState *s1, Section *s, Section *sr)
|
||||||
#if SHT_RELX == SHT_RELA
|
#if SHT_RELX == SHT_RELA
|
||||||
tgt += rel->r_addend;
|
tgt += rel->r_addend;
|
||||||
#endif
|
#endif
|
||||||
if (is_dwarf && type == R_DATA_32DW
|
|
||||||
&& sym->st_shndx >= s1->dwlo && sym->st_shndx < s1->dwhi) {
|
|
||||||
/* dwarf section relocation to each other */
|
|
||||||
add32le(ptr, tgt - s1->sections[sym->st_shndx]->sh_addr);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
addr = s->sh_addr + rel->r_offset;
|
addr = s->sh_addr + rel->r_offset;
|
||||||
relocate(s1, rel, type, ptr, addr, tgt);
|
relocate(s1, rel, type, ptr, addr, tgt);
|
||||||
}
|
}
|
||||||
|
@ -1132,17 +1083,6 @@ static void relocate_section(TCCState *s1, Section *s, Section *sr)
|
||||||
/* if the relocation is allocated, we change its symbol table */
|
/* if the relocation is allocated, we change its symbol table */
|
||||||
if (sr->sh_flags & SHF_ALLOC) {
|
if (sr->sh_flags & SHF_ALLOC) {
|
||||||
sr->link = s1->dynsym;
|
sr->link = s1->dynsym;
|
||||||
if (s1->output_type & TCC_OUTPUT_DYN) {
|
|
||||||
size_t r = (uint8_t*)qrel - sr->data;
|
|
||||||
if (sizeof ((Stab_Sym*)0)->n_value < PTR_SIZE
|
|
||||||
&& 0 == strcmp(s->name, ".stab"))
|
|
||||||
r = 0; /* cannot apply 64bit relocation to 32bit value */
|
|
||||||
sr->data_offset = sr->sh_size = r;
|
|
||||||
#ifdef CONFIG_TCC_PIE
|
|
||||||
if (r && (s->sh_flags & SHF_EXECINSTR))
|
|
||||||
tcc_warning("%d relocations to %s", (unsigned)(r / sizeof *qrel), s->name);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -1158,11 +1098,9 @@ ST_FUNC void relocate_sections(TCCState *s1)
|
||||||
if (sr->sh_type != SHT_RELX)
|
if (sr->sh_type != SHT_RELX)
|
||||||
continue;
|
continue;
|
||||||
s = s1->sections[sr->sh_info];
|
s = s1->sections[sr->sh_info];
|
||||||
#ifndef TCC_TARGET_MACHO
|
|
||||||
if (s != s1->got
|
if (s != s1->got
|
||||||
|| s1->static_link
|
|| s1->static_link
|
||||||
|| s1->output_type == TCC_OUTPUT_MEMORY)
|
|| s1->output_type == TCC_OUTPUT_MEMORY)
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
relocate_section(s1, s, sr);
|
relocate_section(s1, s, sr);
|
||||||
}
|
}
|
||||||
|
@ -1183,15 +1121,13 @@ ST_FUNC void relocate_sections(TCCState *s1)
|
||||||
static int prepare_dynamic_rel(TCCState *s1, Section *sr)
|
static int prepare_dynamic_rel(TCCState *s1, Section *sr)
|
||||||
{
|
{
|
||||||
int count = 0;
|
int count = 0;
|
||||||
#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64) || \
|
|
||||||
defined(TCC_TARGET_ARM) || defined(TCC_TARGET_ARM64) || \
|
|
||||||
defined(TCC_TARGET_RISCV64)
|
|
||||||
ElfW_Rel *rel;
|
ElfW_Rel *rel;
|
||||||
for_each_elem(sr, 0, rel, ElfW_Rel) {
|
for_each_elem(sr, 0, rel, ElfW_Rel) {
|
||||||
int sym_index = ELFW(R_SYM)(rel->r_info);
|
int sym_index = ELFW(R_SYM)(rel->r_info);
|
||||||
int type = ELFW(R_TYPE)(rel->r_info);
|
int type = ELFW(R_TYPE)(rel->r_info);
|
||||||
switch(type) {
|
switch(type) {
|
||||||
#if defined(TCC_TARGET_I386)
|
|
||||||
case R_386_32:
|
case R_386_32:
|
||||||
if (!get_sym_attr(s1, sym_index, 0)->dyn_index
|
if (!get_sym_attr(s1, sym_index, 0)->dyn_index
|
||||||
&& ((ElfW(Sym)*)symtab_section->data + sym_index)->st_shndx == SHN_UNDEF) {
|
&& ((ElfW(Sym)*)symtab_section->data + sym_index)->st_shndx == SHN_UNDEF) {
|
||||||
|
@ -1199,42 +1135,9 @@ static int prepare_dynamic_rel(TCCState *s1, Section *sr)
|
||||||
rel->r_info = ELFW(R_INFO)(sym_index, R_386_RELATIVE);
|
rel->r_info = ELFW(R_INFO)(sym_index, R_386_RELATIVE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#elif defined(TCC_TARGET_X86_64)
|
|
||||||
case R_X86_64_32:
|
|
||||||
case R_X86_64_32S:
|
|
||||||
case R_X86_64_64:
|
|
||||||
#elif defined(TCC_TARGET_ARM)
|
|
||||||
case R_ARM_ABS32:
|
|
||||||
case R_ARM_TARGET1:
|
|
||||||
#elif defined(TCC_TARGET_ARM64)
|
|
||||||
case R_AARCH64_ABS32:
|
|
||||||
case R_AARCH64_ABS64:
|
|
||||||
#elif defined(TCC_TARGET_RISCV64)
|
|
||||||
case R_RISCV_32:
|
|
||||||
case R_RISCV_64:
|
|
||||||
#endif
|
|
||||||
count++;
|
count++;
|
||||||
break;
|
break;
|
||||||
#if defined(TCC_TARGET_I386)
|
|
||||||
case R_386_PC32:
|
case R_386_PC32:
|
||||||
#elif defined(TCC_TARGET_X86_64)
|
|
||||||
case R_X86_64_PC32:
|
|
||||||
{
|
|
||||||
ElfW(Sym) *sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
|
||||||
/* Hidden defined symbols can and must be resolved locally.
|
|
||||||
We're misusing a PLT32 reloc for this, as that's always
|
|
||||||
resolved to its address even in shared libs. */
|
|
||||||
if (sym->st_shndx != SHN_UNDEF &&
|
|
||||||
ELFW(ST_VISIBILITY)(sym->st_other) == STV_HIDDEN) {
|
|
||||||
rel->r_info = ELFW(R_INFO)(sym_index, R_X86_64_PLT32);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#elif defined(TCC_TARGET_ARM64)
|
|
||||||
case R_AARCH64_PREL32:
|
|
||||||
#endif
|
|
||||||
if (s1->output_type != TCC_OUTPUT_DLL)
|
|
||||||
break;
|
|
||||||
if (get_sym_attr(s1, sym_index, 0)->dyn_index)
|
if (get_sym_attr(s1, sym_index, 0)->dyn_index)
|
||||||
count++;
|
count++;
|
||||||
break;
|
break;
|
||||||
|
@ -1242,7 +1145,7 @@ static int prepare_dynamic_rel(TCCState *s1, Section *sr)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1399,9 +1302,7 @@ redo:
|
||||||
if (sym->st_shndx == SHN_UNDEF) {
|
if (sym->st_shndx == SHN_UNDEF) {
|
||||||
ElfW(Sym) *esym;
|
ElfW(Sym) *esym;
|
||||||
int dynindex;
|
int dynindex;
|
||||||
if (!PCRELATIVE_DLLPLT
|
|
||||||
&& (s1->output_type & TCC_OUTPUT_DYN))
|
|
||||||
continue;
|
|
||||||
/* Relocations for UNDEF symbols would normally need
|
/* Relocations for UNDEF symbols would normally need
|
||||||
to be transferred into the executable or shared object.
|
to be transferred into the executable or shared object.
|
||||||
If that were done AUTO_GOTPLT_ENTRY wouldn't exist.
|
If that were done AUTO_GOTPLT_ENTRY wouldn't exist.
|
||||||
|
@ -1425,28 +1326,14 @@ redo:
|
||||||
} else if (sym->st_shndx == SHN_ABS) {
|
} else if (sym->st_shndx == SHN_ABS) {
|
||||||
if (sym->st_value == 0) /* from tcc_add_btstub() */
|
if (sym->st_value == 0) /* from tcc_add_btstub() */
|
||||||
continue;
|
continue;
|
||||||
#ifndef TCC_TARGET_ARM
|
|
||||||
if (PTR_SIZE != 8)
|
if (PTR_SIZE != 8)
|
||||||
continue;
|
continue;
|
||||||
#endif
|
|
||||||
/* from tcc_add_symbol(): on 64 bit platforms these
|
/* from tcc_add_symbol(): on 64 bit platforms these
|
||||||
need to go through .got */
|
need to go through .got */
|
||||||
} else
|
} else
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TCC_TARGET_X86_64
|
|
||||||
if ((type == R_X86_64_PLT32 || type == R_X86_64_PC32) &&
|
|
||||||
sym->st_shndx != SHN_UNDEF &&
|
|
||||||
(ELFW(ST_VISIBILITY)(sym->st_other) != STV_DEFAULT ||
|
|
||||||
ELFW(ST_BIND)(sym->st_info) == STB_LOCAL ||
|
|
||||||
s1->output_type & TCC_OUTPUT_EXE)) {
|
|
||||||
if (pass != 0)
|
|
||||||
continue;
|
|
||||||
rel->r_info = ELFW(R_INFO)(sym_index, R_X86_64_PC32);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
reloc_type = code_reloc(type);
|
reloc_type = code_reloc(type);
|
||||||
if (reloc_type == -1) {
|
if (reloc_type == -1) {
|
||||||
tcc_error_noabort ("Unknown relocation type: %d", type);
|
tcc_error_noabort ("Unknown relocation type: %d", type);
|
||||||
|
@ -1523,15 +1410,6 @@ ST_FUNC void add_array (TCCState *s1, const char *sec, int c)
|
||||||
section_ptr_add(s, PTR_SIZE);
|
section_ptr_add(s, PTR_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
|
||||||
ST_FUNC void tcc_add_bcheck(TCCState *s1)
|
|
||||||
{
|
|
||||||
if (0 == s1->do_bounds_check)
|
|
||||||
return;
|
|
||||||
section_ptr_add(bounds_section, sizeof(addr_t));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* set symbol to STB_LOCAL and resolve. The point is to not export it as
|
/* set symbol to STB_LOCAL and resolve. The point is to not export it as
|
||||||
a dynamic symbol to allow so's to have one each with a different value. */
|
a dynamic symbol to allow so's to have one each with a different value. */
|
||||||
static void set_local_sym(TCCState *s1, const char *name, Section *s, int offset)
|
static void set_local_sym(TCCState *s1, const char *name, Section *s, int offset)
|
||||||
|
@ -1548,209 +1426,23 @@ static void set_local_sym(TCCState *s1, const char *name, Section *s, int offset
|
||||||
/* avoid generating debug/test_coverage code for stub functions */
|
/* avoid generating debug/test_coverage code for stub functions */
|
||||||
static void tcc_compile_string_no_debug(TCCState *s, const char *str)
|
static void tcc_compile_string_no_debug(TCCState *s, const char *str)
|
||||||
{
|
{
|
||||||
int save_do_debug = s->do_debug;
|
|
||||||
int save_test_coverage = s->test_coverage;
|
|
||||||
|
|
||||||
s->do_debug = 0;
|
|
||||||
s->test_coverage = 0;
|
|
||||||
tcc_compile_string(s, str);
|
tcc_compile_string(s, str);
|
||||||
s->do_debug = save_do_debug;
|
|
||||||
s->test_coverage = save_test_coverage;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_TCC_BACKTRACE
|
|
||||||
static void put_ptr(TCCState *s1, Section *s, int offs)
|
|
||||||
{
|
|
||||||
int c;
|
|
||||||
c = set_global_sym(s1, NULL, s, offs);
|
|
||||||
s = data_section;
|
|
||||||
put_elf_reloc (s1->symtab, s, s->data_offset, R_DATA_PTR, c);
|
|
||||||
section_ptr_add(s, PTR_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
ST_FUNC void tcc_add_btstub(TCCState *s1)
|
#if !defined TCC_TARGET_PE
|
||||||
{
|
|
||||||
Section *s;
|
|
||||||
int n, o, *p;
|
|
||||||
CString cstr;
|
|
||||||
const char *__rt_info = &"___rt_info"[!s1->leading_underscore];
|
|
||||||
|
|
||||||
s = data_section;
|
|
||||||
/* Align to PTR_SIZE */
|
|
||||||
section_ptr_add(s, -s->data_offset & (PTR_SIZE - 1));
|
|
||||||
o = s->data_offset;
|
|
||||||
/* create a struct rt_context (see tccrun.c) */
|
|
||||||
if (s1->dwarf) {
|
|
||||||
put_ptr(s1, dwarf_line_section, 0);
|
|
||||||
put_ptr(s1, dwarf_line_section, -1);
|
|
||||||
if (s1->dwarf >= 5)
|
|
||||||
put_ptr(s1, dwarf_line_str_section, 0);
|
|
||||||
else
|
|
||||||
put_ptr(s1, dwarf_str_section, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
put_ptr(s1, stab_section, 0);
|
|
||||||
put_ptr(s1, stab_section, -1);
|
|
||||||
put_ptr(s1, stab_section->link, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* skip esym_start/esym_end/elf_str (not loaded) */
|
|
||||||
section_ptr_add(s, 3 * PTR_SIZE);
|
|
||||||
|
|
||||||
if (s1->output_type == TCC_OUTPUT_MEMORY && 0 == s1->dwarf) {
|
|
||||||
put_ptr(s1, text_section, 0);
|
|
||||||
} else {
|
|
||||||
/* prog_base : local nameless symbol with offset 0 at SHN_ABS */
|
|
||||||
put_ptr(s1, NULL, 0);
|
|
||||||
#if defined TCC_TARGET_MACHO
|
|
||||||
/* adjust for __PAGEZERO */
|
|
||||||
if (s1->dwarf == 0 && s1->output_type == TCC_OUTPUT_EXE)
|
|
||||||
write64le(data_section->data + data_section->data_offset - PTR_SIZE,
|
|
||||||
(uint64_t)1 << 32);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
n = 3 * PTR_SIZE;
|
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
|
||||||
if (s1->do_bounds_check) {
|
|
||||||
put_ptr(s1, bounds_section, 0);
|
|
||||||
n -= PTR_SIZE;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
section_ptr_add(s, n);
|
|
||||||
p = section_ptr_add(s, 2 * sizeof (int));
|
|
||||||
p[0] = s1->rt_num_callers;
|
|
||||||
p[1] = s1->dwarf;
|
|
||||||
// if (s->data_offset - o != 10*PTR_SIZE + 2*sizeof (int)) exit(99);
|
|
||||||
|
|
||||||
if (s1->output_type == TCC_OUTPUT_MEMORY) {
|
|
||||||
set_global_sym(s1, __rt_info, s, o);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cstr_new(&cstr);
|
|
||||||
cstr_printf(&cstr,
|
|
||||||
"extern void __bt_init(),__bt_exit(),__bt_init_dll();"
|
|
||||||
"static void *__rt_info[];"
|
|
||||||
"__attribute__((constructor)) static void __bt_init_rt(){");
|
|
||||||
#ifdef TCC_TARGET_PE
|
|
||||||
if (s1->output_type == TCC_OUTPUT_DLL)
|
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
|
||||||
cstr_printf(&cstr, "__bt_init_dll(%d);", s1->do_bounds_check);
|
|
||||||
#else
|
|
||||||
cstr_printf(&cstr, "__bt_init_dll(0);");
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
cstr_printf(&cstr, "__bt_init(__rt_info,%d);}",
|
|
||||||
s1->output_type != TCC_OUTPUT_DLL);
|
|
||||||
/* In case dlcose is called by application */
|
|
||||||
cstr_printf(&cstr,
|
|
||||||
"__attribute__((destructor)) static void __bt_exit_rt(){"
|
|
||||||
"__bt_exit(__rt_info);}");
|
|
||||||
tcc_compile_string_no_debug(s1, cstr.data);
|
|
||||||
cstr_free(&cstr);
|
|
||||||
set_local_sym(s1, __rt_info, s, o);
|
|
||||||
}
|
|
||||||
#endif /* def CONFIG_TCC_BACKTRACE */
|
|
||||||
|
|
||||||
static void tcc_tcov_add_file(TCCState *s1, const char *filename)
|
|
||||||
{
|
|
||||||
CString cstr;
|
|
||||||
void *ptr;
|
|
||||||
char wd[1024];
|
|
||||||
|
|
||||||
if (tcov_section == NULL)
|
|
||||||
return;
|
|
||||||
section_ptr_add(tcov_section, 1);
|
|
||||||
write32le (tcov_section->data, tcov_section->data_offset);
|
|
||||||
|
|
||||||
cstr_new (&cstr);
|
|
||||||
if (filename[0] == '/')
|
|
||||||
cstr_printf (&cstr, "%s.tcov", filename);
|
|
||||||
else {
|
|
||||||
getcwd (wd, sizeof(wd));
|
|
||||||
cstr_printf (&cstr, "%s/%s.tcov", wd, filename);
|
|
||||||
}
|
|
||||||
ptr = section_ptr_add(tcov_section, cstr.size + 1);
|
|
||||||
strcpy((char *)ptr, cstr.data);
|
|
||||||
unlink((char *)ptr);
|
|
||||||
#ifdef _WIN32
|
|
||||||
normalize_slashes((char *)ptr);
|
|
||||||
#endif
|
|
||||||
cstr_free (&cstr);
|
|
||||||
|
|
||||||
cstr_new(&cstr);
|
|
||||||
cstr_printf(&cstr,
|
|
||||||
"extern char *__tcov_data[];"
|
|
||||||
"extern void __store_test_coverage ();"
|
|
||||||
"__attribute__((destructor)) static void __tcov_exit() {"
|
|
||||||
"__store_test_coverage(__tcov_data);"
|
|
||||||
"}");
|
|
||||||
tcc_compile_string_no_debug(s1, cstr.data);
|
|
||||||
cstr_free(&cstr);
|
|
||||||
set_local_sym(s1, &"___tcov_data"[!s1->leading_underscore], tcov_section, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined TCC_TARGET_PE && !defined TCC_TARGET_MACHO
|
|
||||||
/* add libc crt1/crti objects */
|
/* add libc crt1/crti objects */
|
||||||
ST_FUNC void tccelf_add_crtbegin(TCCState *s1)
|
ST_FUNC void tccelf_add_crtbegin(TCCState *s1)
|
||||||
{
|
{
|
||||||
#if TARGETOS_OpenBSD
|
tcc_add_crt(s1, "crt1.o");
|
||||||
if (s1->output_type != TCC_OUTPUT_DLL)
|
|
||||||
tcc_add_crt(s1, "crt0.o");
|
|
||||||
if (s1->output_type == TCC_OUTPUT_DLL)
|
|
||||||
tcc_add_crt(s1, "crtbeginS.o");
|
|
||||||
else
|
|
||||||
tcc_add_crt(s1, "crtbegin.o");
|
|
||||||
#elif TARGETOS_FreeBSD || TARGETOS_NetBSD
|
|
||||||
if (s1->output_type != TCC_OUTPUT_DLL)
|
|
||||||
#if TARGETOS_FreeBSD
|
|
||||||
tcc_add_crt(s1, "crt1.o");
|
|
||||||
#else
|
|
||||||
tcc_add_crt(s1, "crt0.o");
|
|
||||||
#endif
|
|
||||||
tcc_add_crt(s1, "crti.o");
|
tcc_add_crt(s1, "crti.o");
|
||||||
if (s1->static_link)
|
|
||||||
tcc_add_crt(s1, "crtbeginT.o");
|
|
||||||
else if (s1->output_type == TCC_OUTPUT_DLL)
|
|
||||||
tcc_add_crt(s1, "crtbeginS.o");
|
|
||||||
else
|
|
||||||
tcc_add_crt(s1, "crtbegin.o");
|
|
||||||
#elif TARGETOS_ANDROID
|
|
||||||
if (s1->output_type == TCC_OUTPUT_DLL)
|
|
||||||
tcc_add_crt(s1, "crtbegin_so.o");
|
|
||||||
else
|
|
||||||
tcc_add_crt(s1, "crtbegin_dynamic.o");
|
|
||||||
#else
|
|
||||||
if (s1->output_type != TCC_OUTPUT_DLL)
|
|
||||||
tcc_add_crt(s1, "crt1.o");
|
|
||||||
tcc_add_crt(s1, "crti.o");
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void tccelf_add_crtend(TCCState *s1)
|
ST_FUNC void tccelf_add_crtend(TCCState *s1)
|
||||||
{
|
{
|
||||||
#if TARGETOS_OpenBSD
|
|
||||||
if (s1->output_type == TCC_OUTPUT_DLL)
|
|
||||||
tcc_add_crt(s1, "crtendS.o");
|
|
||||||
else
|
|
||||||
tcc_add_crt(s1, "crtend.o");
|
|
||||||
#elif TARGETOS_FreeBSD || TARGETOS_NetBSD
|
|
||||||
if (s1->output_type == TCC_OUTPUT_DLL)
|
|
||||||
tcc_add_crt(s1, "crtendS.o");
|
|
||||||
else
|
|
||||||
tcc_add_crt(s1, "crtend.o");
|
|
||||||
tcc_add_crt(s1, "crtn.o");
|
tcc_add_crt(s1, "crtn.o");
|
||||||
#elif TARGETOS_ANDROID
|
|
||||||
if (s1->output_type == TCC_OUTPUT_DLL)
|
|
||||||
tcc_add_crt(s1, "crtend_so.o");
|
|
||||||
else
|
|
||||||
tcc_add_crt(s1, "crtend_android.o");
|
|
||||||
#else
|
|
||||||
tcc_add_crt(s1, "crtn.o");
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
#endif /* !defined TCC_TARGET_PE && !defined TCC_TARGET_MACHO */
|
#endif /* !defined TCC_TARGET_PE */
|
||||||
|
|
||||||
#ifndef TCC_TARGET_PE
|
#ifndef TCC_TARGET_PE
|
||||||
/* add tcc runtime libraries */
|
/* add tcc runtime libraries */
|
||||||
|
@ -1758,34 +1450,12 @@ ST_FUNC void tcc_add_runtime(TCCState *s1)
|
||||||
{
|
{
|
||||||
s1->filetype = 0;
|
s1->filetype = 0;
|
||||||
|
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
|
||||||
tcc_add_bcheck(s1);
|
|
||||||
#endif
|
|
||||||
tcc_add_pragma_libs(s1);
|
tcc_add_pragma_libs(s1);
|
||||||
|
|
||||||
/* add libc */
|
/* add libc */
|
||||||
if (!s1->nostdlib) {
|
if (!s1->nostdlib) {
|
||||||
int lpthread = s1->option_pthread;
|
int lpthread = s1->option_pthread;
|
||||||
|
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
|
||||||
if (s1->do_bounds_check && s1->output_type != TCC_OUTPUT_DLL) {
|
|
||||||
tcc_add_support(s1, "bcheck.o");
|
|
||||||
# if !(TARGETOS_OpenBSD || TARGETOS_NetBSD)
|
|
||||||
tcc_add_library(s1, "dl");
|
|
||||||
# endif
|
|
||||||
lpthread = 1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_TCC_BACKTRACE
|
|
||||||
if (s1->do_backtrace) {
|
|
||||||
if (s1->output_type & TCC_OUTPUT_EXE)
|
|
||||||
tcc_add_support(s1, "bt-exe.o");
|
|
||||||
if (s1->output_type != TCC_OUTPUT_DLL)
|
|
||||||
tcc_add_support(s1, "bt-log.o");
|
|
||||||
tcc_add_btstub(s1);
|
|
||||||
lpthread = 1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (lpthread)
|
if (lpthread)
|
||||||
tcc_add_library(s1, "pthread");
|
tcc_add_library(s1, "pthread");
|
||||||
tcc_add_library(s1, "c");
|
tcc_add_library(s1, "c");
|
||||||
|
@ -1797,15 +1467,11 @@ ST_FUNC void tcc_add_runtime(TCCState *s1)
|
||||||
tcc_add_dll(s1, TCC_LIBGCC, AFF_PRINT_ERROR);
|
tcc_add_dll(s1, TCC_LIBGCC, AFF_PRINT_ERROR);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if defined TCC_TARGET_ARM && TARGETOS_FreeBSD
|
|
||||||
tcc_add_library(s1, "gcc_s"); // unwind code
|
|
||||||
#endif
|
|
||||||
if (TCC_LIBTCC1[0])
|
if (TCC_LIBTCC1[0])
|
||||||
tcc_add_support(s1, TCC_LIBTCC1);
|
tcc_add_support(s1, TCC_LIBTCC1);
|
||||||
#ifndef TCC_TARGET_MACHO
|
|
||||||
if (s1->output_type != TCC_OUTPUT_MEMORY)
|
if (s1->output_type != TCC_OUTPUT_MEMORY)
|
||||||
tccelf_add_crtend(s1);
|
tccelf_add_crtend(s1);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* ndef TCC_TARGET_PE */
|
#endif /* ndef TCC_TARGET_PE */
|
||||||
|
@ -1822,13 +1488,7 @@ static void tcc_add_linker_symbols(TCCState *s1)
|
||||||
set_global_sym(s1, "_etext", text_section, -1);
|
set_global_sym(s1, "_etext", text_section, -1);
|
||||||
set_global_sym(s1, "_edata", data_section, -1);
|
set_global_sym(s1, "_edata", data_section, -1);
|
||||||
set_global_sym(s1, "_end", bss_section, -1);
|
set_global_sym(s1, "_end", bss_section, -1);
|
||||||
#if TARGETOS_OpenBSD
|
|
||||||
set_global_sym(s1, "__executable_start", NULL, ELF_START_ADDR);
|
|
||||||
#endif
|
|
||||||
#ifdef TCC_TARGET_RISCV64
|
|
||||||
/* XXX should be .sdata+0x800, not .data+0x800 */
|
|
||||||
set_global_sym(s1, "__global_pointer$", data_section, 0x800);
|
|
||||||
#endif
|
|
||||||
/* horrible new standard ldscript defines */
|
/* horrible new standard ldscript defines */
|
||||||
add_init_array_defines(s1, ".preinit_array");
|
add_init_array_defines(s1, ".preinit_array");
|
||||||
add_init_array_defines(s1, ".init_array");
|
add_init_array_defines(s1, ".init_array");
|
||||||
|
@ -2097,33 +1757,10 @@ static int set_sec_sizes(TCCState *s1)
|
||||||
if (s->sh_type == SHT_RELX && !(s->sh_flags & SHF_ALLOC)) {
|
if (s->sh_type == SHT_RELX && !(s->sh_flags & SHF_ALLOC)) {
|
||||||
/* when generating a DLL, we include relocations but
|
/* when generating a DLL, we include relocations but
|
||||||
we may patch them */
|
we may patch them */
|
||||||
if ((file_type & TCC_OUTPUT_DYN)
|
} else if ((s->sh_flags & SHF_ALLOC)) {
|
||||||
&& (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)) {
|
|
||||||
int count = prepare_dynamic_rel(s1, s);
|
|
||||||
if (count) {
|
|
||||||
/* allocate the section */
|
|
||||||
s->sh_flags |= SHF_ALLOC;
|
|
||||||
s->sh_size = count * sizeof(ElfW_Rel);
|
|
||||||
if (s1->sections[s->sh_info]->sh_flags & SHF_EXECINSTR)
|
|
||||||
textrel += count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if ((s->sh_flags & SHF_ALLOC)
|
|
||||||
#ifdef TCC_TARGET_ARM
|
|
||||||
|| s->sh_type == SHT_ARM_ATTRIBUTES
|
|
||||||
#endif
|
|
||||||
|| s1->do_debug) {
|
|
||||||
s->sh_size = s->data_offset;
|
s->sh_size = s->data_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TCC_TARGET_ARM
|
|
||||||
/* XXX: Suppress stack unwinding section. */
|
|
||||||
if (s->sh_type == SHT_ARM_EXIDX) {
|
|
||||||
s->sh_flags = 0;
|
|
||||||
s->sh_size = 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
}
|
||||||
return textrel;
|
return textrel;
|
||||||
}
|
}
|
||||||
|
@ -2313,8 +1950,6 @@ static int layout_sections(TCCState *s1, int *sec_order, struct dyn_inf *d)
|
||||||
s_align = s1->section_align;
|
s_align = s1->section_align;
|
||||||
|
|
||||||
addr = ELF_START_ADDR;
|
addr = ELF_START_ADDR;
|
||||||
if (s1->output_type & TCC_OUTPUT_DYN)
|
|
||||||
addr = 0;
|
|
||||||
|
|
||||||
if (s1->has_text_addr) {
|
if (s1->has_text_addr) {
|
||||||
addr = s1->text_addr;
|
addr = s1->text_addr;
|
||||||
|
@ -2509,8 +2144,6 @@ static void fill_dynamic(TCCState *s1, struct dyn_inf *dyninf)
|
||||||
if (s && s->data_offset) {
|
if (s && s->data_offset) {
|
||||||
put_dt(dynamic, DT_FINI, s->sh_addr);
|
put_dt(dynamic, DT_FINI, s->sh_addr);
|
||||||
}
|
}
|
||||||
if (s1->do_debug)
|
|
||||||
put_dt(dynamic, DT_DEBUG, 0);
|
|
||||||
put_dt(dynamic, DT_NULL, 0);
|
put_dt(dynamic, DT_NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2574,26 +2207,10 @@ static int tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr)
|
||||||
ehdr.e_ident[5] = ELFDATA2LSB;
|
ehdr.e_ident[5] = ELFDATA2LSB;
|
||||||
ehdr.e_ident[6] = EV_CURRENT;
|
ehdr.e_ident[6] = EV_CURRENT;
|
||||||
|
|
||||||
#if TARGETOS_FreeBSD || TARGETOS_FreeBSD_kernel
|
|
||||||
ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
|
|
||||||
#elif defined TCC_TARGET_ARM && defined TCC_ARM_EABI
|
|
||||||
ehdr.e_flags = EF_ARM_EABI_VER5;
|
|
||||||
ehdr.e_flags |= s1->float_abi == ARM_HARD_FLOAT
|
|
||||||
? EF_ARM_VFP_FLOAT : EF_ARM_SOFT_FLOAT;
|
|
||||||
#elif defined TCC_TARGET_ARM
|
|
||||||
ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
|
|
||||||
#elif defined TCC_TARGET_RISCV64
|
|
||||||
/* XXX should be configurable */
|
|
||||||
ehdr.e_flags = EF_RISCV_FLOAT_ABI_DOUBLE;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (file_type == TCC_OUTPUT_OBJ) {
|
if (file_type == TCC_OUTPUT_OBJ) {
|
||||||
ehdr.e_type = ET_REL;
|
ehdr.e_type = ET_REL;
|
||||||
} else {
|
} else {
|
||||||
if (file_type & TCC_OUTPUT_DYN)
|
ehdr.e_type = ET_EXEC;
|
||||||
ehdr.e_type = ET_DYN;
|
|
||||||
else
|
|
||||||
ehdr.e_type = ET_EXEC;
|
|
||||||
if (s1->elf_entryname)
|
if (s1->elf_entryname)
|
||||||
ehdr.e_entry = get_sym_addr(s1, s1->elf_entryname, 1, 0);
|
ehdr.e_entry = get_sym_addr(s1, s1->elf_entryname, 1, 0);
|
||||||
else
|
else
|
||||||
|
@ -2752,63 +2369,6 @@ static void reorder_sections(TCCState *s1, int *sec_order)
|
||||||
tcc_free(backmap);
|
tcc_free(backmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TCC_TARGET_ARM
|
|
||||||
static void create_arm_attribute_section(TCCState *s1)
|
|
||||||
{
|
|
||||||
// Needed for DLL support.
|
|
||||||
static const unsigned char arm_attr[] = {
|
|
||||||
0x41, // 'A'
|
|
||||||
0x2c, 0x00, 0x00, 0x00, // size 0x2c
|
|
||||||
'a', 'e', 'a', 'b', 'i', 0x00, // "aeabi"
|
|
||||||
0x01, 0x22, 0x00, 0x00, 0x00, // 'File Attributes', size 0x22
|
|
||||||
0x05, 0x36, 0x00, // 'CPU_name', "6"
|
|
||||||
0x06, 0x06, // 'CPU_arch', 'v6'
|
|
||||||
0x08, 0x01, // 'ARM_ISA_use', 'Yes'
|
|
||||||
0x09, 0x01, // 'THUMB_ISA_use', 'Thumb-1'
|
|
||||||
0x0a, 0x02, // 'FP_arch', 'VFPv2'
|
|
||||||
0x12, 0x04, // 'ABI_PCS_wchar_t', 4
|
|
||||||
0x14, 0x01, // 'ABI_FP_denormal', 'Needed'
|
|
||||||
0x15, 0x01, // 'ABI_FP_exceptions', 'Needed'
|
|
||||||
0x17, 0x03, // 'ABI_FP_number_model', 'IEEE 754'
|
|
||||||
0x18, 0x01, // 'ABI_align_needed', '8-byte'
|
|
||||||
0x19, 0x01, // 'ABI_align_preserved', '8-byte, except leaf SP'
|
|
||||||
0x1a, 0x02, // 'ABI_enum_size', 'int'
|
|
||||||
0x1c, 0x01, // 'ABI_VFP_args', 'VFP registers'
|
|
||||||
0x22, 0x01 // 'CPU_unaligned_access', 'v6'
|
|
||||||
};
|
|
||||||
Section *attr = new_section(s1, ".ARM.attributes", SHT_ARM_ATTRIBUTES, 0);
|
|
||||||
unsigned char *ptr = section_ptr_add(attr, sizeof(arm_attr));
|
|
||||||
attr->sh_addralign = 1;
|
|
||||||
memcpy(ptr, arm_attr, sizeof(arm_attr));
|
|
||||||
if (s1->float_abi != ARM_HARD_FLOAT) {
|
|
||||||
ptr[26] = 0x00; // 'FP_arch', 'No'
|
|
||||||
ptr[41] = 0x1e; // 'ABI_optimization_goals'
|
|
||||||
ptr[42] = 0x06; // 'Aggressive Debug'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if TARGETOS_OpenBSD || TARGETOS_NetBSD
|
|
||||||
static Section *create_bsd_note_section(TCCState *s1,
|
|
||||||
const char *name,
|
|
||||||
const char *value)
|
|
||||||
{
|
|
||||||
Section *s = find_section (s1, name);
|
|
||||||
|
|
||||||
if (s->data_offset == 0) {
|
|
||||||
char *ptr = section_ptr_add(s, sizeof(ElfW(Nhdr)) + 8 + 4);
|
|
||||||
ElfW(Nhdr) *note = (ElfW(Nhdr) *) ptr;
|
|
||||||
|
|
||||||
s->sh_type = SHT_NOTE;
|
|
||||||
note->n_namesz = 8;
|
|
||||||
note->n_descsz = 4;
|
|
||||||
note->n_type = ELF_NOTE_OS_GNU;
|
|
||||||
strcpy (ptr + sizeof(ElfW(Nhdr)), value);
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void alloc_sec_names(TCCState *s1, int is_obj);
|
static void alloc_sec_names(TCCState *s1, int is_obj);
|
||||||
|
|
||||||
/* Output an elf, coff or binary file */
|
/* Output an elf, coff or binary file */
|
||||||
|
@ -2827,21 +2387,6 @@ static int elf_output_file(TCCState *s1, const char *filename)
|
||||||
sec_order = NULL;
|
sec_order = NULL;
|
||||||
dyninf.roinf = &dyninf._roinf;
|
dyninf.roinf = &dyninf._roinf;
|
||||||
|
|
||||||
#ifdef TCC_TARGET_ARM
|
|
||||||
create_arm_attribute_section (s1);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if TARGETOS_OpenBSD
|
|
||||||
dyninf.note = create_bsd_note_section (s1, ".note.openbsd.ident", "OpenBSD");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if TARGETOS_NetBSD
|
|
||||||
dyninf.note = create_bsd_note_section (s1, ".note.netbsd.ident", "NetBSD");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if TARGETOS_FreeBSD || TARGETOS_NetBSD
|
|
||||||
dyninf.roinf = NULL;
|
|
||||||
#endif
|
|
||||||
/* if linking, also link in runtime libraries (libc, libgcc, etc.) */
|
/* if linking, also link in runtime libraries (libc, libgcc, etc.) */
|
||||||
tcc_add_runtime(s1);
|
tcc_add_runtime(s1);
|
||||||
resolve_common_syms(s1);
|
resolve_common_syms(s1);
|
||||||
|
@ -2876,7 +2421,6 @@ static int elf_output_file(TCCState *s1, const char *filename)
|
||||||
|
|
||||||
got_sym = build_got(s1);
|
got_sym = build_got(s1);
|
||||||
if (file_type & TCC_OUTPUT_EXE) {
|
if (file_type & TCC_OUTPUT_EXE) {
|
||||||
bind_exe_dynsyms(s1, file_type & TCC_OUTPUT_DYN);
|
|
||||||
if (s1->nb_errors)
|
if (s1->nb_errors)
|
||||||
goto the_end;
|
goto the_end;
|
||||||
}
|
}
|
||||||
|
@ -2887,10 +2431,6 @@ static int elf_output_file(TCCState *s1, const char *filename)
|
||||||
/* shared library case: simply export all global symbols */
|
/* shared library case: simply export all global symbols */
|
||||||
export_global_syms(s1);
|
export_global_syms(s1);
|
||||||
}
|
}
|
||||||
#if TCC_EH_FRAME
|
|
||||||
/* fill with initial data */
|
|
||||||
tcc_eh_frame_hdr(s1, 0);
|
|
||||||
#endif
|
|
||||||
dyninf.gnu_hash = create_gnu_hash(s1);
|
dyninf.gnu_hash = create_gnu_hash(s1);
|
||||||
} else {
|
} else {
|
||||||
build_got_entries(s1, 0);
|
build_got_entries(s1, 0);
|
||||||
|
@ -2912,16 +2452,6 @@ static int elf_output_file(TCCState *s1, const char *filename)
|
||||||
put_elf_str(dynstr, s1->rpath));
|
put_elf_str(dynstr, s1->rpath));
|
||||||
|
|
||||||
dt_flags_1 = DF_1_NOW;
|
dt_flags_1 = DF_1_NOW;
|
||||||
if (file_type & TCC_OUTPUT_DYN) {
|
|
||||||
if (s1->soname)
|
|
||||||
put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
|
|
||||||
/* XXX: currently, since we do not handle PIC code, we
|
|
||||||
must relocate the readonly segments */
|
|
||||||
if (textrel)
|
|
||||||
put_dt(dynamic, DT_TEXTREL, 0);
|
|
||||||
if (file_type & TCC_OUTPUT_EXE)
|
|
||||||
dt_flags_1 = DF_1_NOW | DF_1_PIE;
|
|
||||||
}
|
|
||||||
put_dt(dynamic, DT_FLAGS, DF_BIND_NOW);
|
put_dt(dynamic, DT_FLAGS, DF_BIND_NOW);
|
||||||
put_dt(dynamic, DT_FLAGS_1, dt_flags_1);
|
put_dt(dynamic, DT_FLAGS_1, dt_flags_1);
|
||||||
if (s1->symbolic)
|
if (s1->symbolic)
|
||||||
|
@ -2946,8 +2476,7 @@ static int elf_output_file(TCCState *s1, const char *filename)
|
||||||
if (dynamic) {
|
if (dynamic) {
|
||||||
/* put in GOT the dynamic section address and relocate PLT */
|
/* put in GOT the dynamic section address and relocate PLT */
|
||||||
write32le(s1->got->data, dynamic->sh_addr);
|
write32le(s1->got->data, dynamic->sh_addr);
|
||||||
if (file_type == TCC_OUTPUT_EXE
|
if (file_type == TCC_OUTPUT_EXE)
|
||||||
|| (RELOCATE_DLLPLT && (file_type & TCC_OUTPUT_DYN)))
|
|
||||||
relocate_plt(s1);
|
relocate_plt(s1);
|
||||||
/* relocate symbols in .dynsym now that final addresses are known */
|
/* relocate symbols in .dynsym now that final addresses are known */
|
||||||
relocate_syms(s1, s1->dynsym, 2);
|
relocate_syms(s1, s1->dynsym, 2);
|
||||||
|
@ -2974,10 +2503,7 @@ static int elf_output_file(TCCState *s1, const char *filename)
|
||||||
update_gnu_hash(s1, dyninf.gnu_hash);
|
update_gnu_hash(s1, dyninf.gnu_hash);
|
||||||
|
|
||||||
reorder_sections(s1, sec_order);
|
reorder_sections(s1, sec_order);
|
||||||
#if TCC_EH_FRAME
|
|
||||||
/* fill with final data */
|
|
||||||
tcc_eh_frame_hdr(s1, 1);
|
|
||||||
#endif
|
|
||||||
/* Create the ELF file with name 'filename' */
|
/* Create the ELF file with name 'filename' */
|
||||||
ret = tcc_write_elf_file(s1, filename, dyninf.phnum, dyninf.phdr);
|
ret = tcc_write_elf_file(s1, filename, dyninf.phnum, dyninf.phdr);
|
||||||
the_end:
|
the_end:
|
||||||
|
@ -3027,16 +2553,12 @@ static int elf_output_obj(TCCState *s1, const char *filename)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename)
|
int tcc_output_file(TCCState *s, const char *filename)
|
||||||
{
|
{
|
||||||
if (s->test_coverage)
|
|
||||||
tcc_tcov_add_file(s, filename);
|
|
||||||
if (s->output_type == TCC_OUTPUT_OBJ)
|
if (s->output_type == TCC_OUTPUT_OBJ)
|
||||||
return elf_output_obj(s, filename);
|
return elf_output_obj(s, filename);
|
||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_TARGET_PE
|
||||||
return pe_output_file(s, filename);
|
return pe_output_file(s, filename);
|
||||||
#elif defined TCC_TARGET_MACHO
|
|
||||||
return macho_output_file(s, filename);
|
|
||||||
#else
|
#else
|
||||||
return elf_output_file(s, filename);
|
return elf_output_file(s, filename);
|
||||||
#endif
|
#endif
|
||||||
|
@ -3082,10 +2604,8 @@ ST_FUNC int tcc_object_type(int fd, ElfW(Ehdr) *h)
|
||||||
} else if (size >= 8) {
|
} else if (size >= 8) {
|
||||||
if (0 == memcmp(h, ARMAG, 8))
|
if (0 == memcmp(h, ARMAG, 8))
|
||||||
return AFF_BINTYPE_AR;
|
return AFF_BINTYPE_AR;
|
||||||
#ifdef TCC_TARGET_COFF
|
else if (((FILHDR *)h)->f_magic == F_MACH_I386)
|
||||||
if (((struct filehdr*)h)->f_magic == COFF_C67_MAGIC)
|
return (AFF_BINTYPE_COFF);
|
||||||
return AFF_BINTYPE_C67;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -3167,7 +2687,7 @@ invalid:
|
||||||
sh_name = strsec + sh->sh_name;
|
sh_name = strsec + sh->sh_name;
|
||||||
if (0 == strncmp(sh_name, ".debug_", 7)
|
if (0 == strncmp(sh_name, ".debug_", 7)
|
||||||
|| 0 == strncmp(sh_name, ".stab", 5)) {
|
|| 0 == strncmp(sh_name, ".stab", 5)) {
|
||||||
if (!s1->do_debug || seencompressed)
|
if (seencompressed)
|
||||||
continue;
|
continue;
|
||||||
} else
|
} else
|
||||||
if (sh->sh_type != SHT_PROGBITS &&
|
if (sh->sh_type != SHT_PROGBITS &&
|
||||||
|
@ -3202,12 +2722,6 @@ invalid:
|
||||||
sm_table[i].link_once = 1;
|
sm_table[i].link_once = 1;
|
||||||
goto next;
|
goto next;
|
||||||
}
|
}
|
||||||
if (stab_section) {
|
|
||||||
if (s == stab_section)
|
|
||||||
stab_index = i;
|
|
||||||
if (s == stab_section->link)
|
|
||||||
stabstr_index = i;
|
|
||||||
}
|
|
||||||
goto found;
|
goto found;
|
||||||
}
|
}
|
||||||
/* not found: create new section */
|
/* not found: create new section */
|
||||||
|
@ -3335,12 +2849,6 @@ invalid:
|
||||||
sym_index = old_to_new_syms[sym_index];
|
sym_index = old_to_new_syms[sym_index];
|
||||||
/* ignore link_once in rel section. */
|
/* ignore link_once in rel section. */
|
||||||
if (!sym_index && !sm_table[sh->sh_info].link_once
|
if (!sym_index && !sm_table[sh->sh_info].link_once
|
||||||
#ifdef TCC_TARGET_ARM
|
|
||||||
&& type != R_ARM_V4BX
|
|
||||||
#elif defined TCC_TARGET_RISCV64
|
|
||||||
&& type != R_RISCV_ALIGN
|
|
||||||
&& type != R_RISCV_RELAX
|
|
||||||
#endif
|
|
||||||
) {
|
) {
|
||||||
invalid_reloc:
|
invalid_reloc:
|
||||||
tcc_error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
|
tcc_error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
|
||||||
|
@ -3350,18 +2858,6 @@ invalid:
|
||||||
rel->r_info = ELFW(R_INFO)(sym_index, type);
|
rel->r_info = ELFW(R_INFO)(sym_index, type);
|
||||||
/* offset the relocation offset */
|
/* offset the relocation offset */
|
||||||
rel->r_offset += offseti;
|
rel->r_offset += offseti;
|
||||||
#ifdef TCC_TARGET_ARM
|
|
||||||
/* Jumps and branches from a Thumb code to a PLT entry need
|
|
||||||
special handling since PLT entries are ARM code.
|
|
||||||
Unconditional bl instructions referencing PLT entries are
|
|
||||||
handled by converting these instructions into blx
|
|
||||||
instructions. Other case of instructions referencing a PLT
|
|
||||||
entry require to add a Thumb stub before the PLT entry to
|
|
||||||
switch to ARM mode. We set bit plt_thumb_stub of the
|
|
||||||
attribute of a symbol to indicate such a case. */
|
|
||||||
if (type == R_ARM_THM_JUMP24)
|
|
||||||
get_sym_attr(s1, sym_index, 1)->plt_thumb_stub = 1;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
#define USING_GLOBALS
|
#define USING_GLOBALS
|
||||||
#include "tcc.h"
|
#include "tcc.h"
|
||||||
|
#include "utils/string.h"
|
||||||
|
|
||||||
/********************************************************/
|
/********************************************************/
|
||||||
/* global variables */
|
/* global variables */
|
||||||
|
@ -43,7 +44,6 @@ static int nb_sym_pools;
|
||||||
|
|
||||||
static Sym *all_cleanups, *pending_gotos;
|
static Sym *all_cleanups, *pending_gotos;
|
||||||
static int local_scope;
|
static int local_scope;
|
||||||
ST_DATA char debug_modes;
|
|
||||||
|
|
||||||
ST_DATA SValue *vtop;
|
ST_DATA SValue *vtop;
|
||||||
static SValue _vstack[1 + VSTACK_SIZE];
|
static SValue _vstack[1 + VSTACK_SIZE];
|
||||||
|
@ -176,8 +176,6 @@ static int gind()
|
||||||
{
|
{
|
||||||
int t = ind;
|
int t = ind;
|
||||||
CODE_ON();
|
CODE_ON();
|
||||||
if (debug_modes)
|
|
||||||
tcc_tcov_block_begin(tcc_state);
|
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,13 +231,6 @@ static int R_RET(int t)
|
||||||
{
|
{
|
||||||
if (!is_float(t))
|
if (!is_float(t))
|
||||||
return REG_IRET;
|
return REG_IRET;
|
||||||
#ifdef TCC_TARGET_X86_64
|
|
||||||
if ((t & VT_BTYPE) == VT_LDOUBLE)
|
|
||||||
return TREG_ST0;
|
|
||||||
#elif defined TCC_TARGET_RISCV64
|
|
||||||
if ((t & VT_BTYPE) == VT_LDOUBLE)
|
|
||||||
return REG_IRET;
|
|
||||||
#endif
|
|
||||||
return REG_FRET;
|
return REG_FRET;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,14 +241,6 @@ static int R2_RET(int t)
|
||||||
#if PTR_SIZE == 4
|
#if PTR_SIZE == 4
|
||||||
if (t == VT_LLONG)
|
if (t == VT_LLONG)
|
||||||
return REG_IRE2;
|
return REG_IRE2;
|
||||||
#elif defined TCC_TARGET_X86_64
|
|
||||||
if (t == VT_QLONG)
|
|
||||||
return REG_IRE2;
|
|
||||||
if (t == VT_QFLOAT)
|
|
||||||
return REG_FRE2;
|
|
||||||
#elif defined TCC_TARGET_RISCV64
|
|
||||||
if (t == VT_LDOUBLE)
|
|
||||||
return REG_IRE2;
|
|
||||||
#endif
|
#endif
|
||||||
return VT_CONST;
|
return VT_CONST;
|
||||||
}
|
}
|
||||||
|
@ -282,15 +265,6 @@ static int RC_TYPE(int t)
|
||||||
{
|
{
|
||||||
if (!is_float(t))
|
if (!is_float(t))
|
||||||
return RC_INT;
|
return RC_INT;
|
||||||
#ifdef TCC_TARGET_X86_64
|
|
||||||
if ((t & VT_BTYPE) == VT_LDOUBLE)
|
|
||||||
return RC_ST0;
|
|
||||||
if ((t & VT_BTYPE) == VT_QFLOAT)
|
|
||||||
return RC_FRET;
|
|
||||||
#elif defined TCC_TARGET_RISCV64
|
|
||||||
if ((t & VT_BTYPE) == VT_LDOUBLE)
|
|
||||||
return RC_INT;
|
|
||||||
#endif
|
|
||||||
return RC_FLOAT;
|
return RC_FLOAT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -323,10 +297,7 @@ ST_FUNC int ieee_finite(double d)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* compiling intel long double natively */
|
/* compiling intel long double natively */
|
||||||
#if (defined __i386__ || defined __x86_64__) \
|
|
||||||
&& (defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64)
|
|
||||||
# define TCC_IS_NATIVE_387
|
# define TCC_IS_NATIVE_387
|
||||||
#endif
|
|
||||||
|
|
||||||
ST_FUNC void test_lvalue(void)
|
ST_FUNC void test_lvalue(void)
|
||||||
{
|
{
|
||||||
|
@ -386,13 +357,7 @@ ST_FUNC int tccgen_compile(TCCState *s1)
|
||||||
func_ind = -1;
|
func_ind = -1;
|
||||||
anon_sym = SYM_FIRST_ANOM;
|
anon_sym = SYM_FIRST_ANOM;
|
||||||
nocode_wanted = DATA_ONLY_WANTED; /* no code outside of functions */
|
nocode_wanted = DATA_ONLY_WANTED; /* no code outside of functions */
|
||||||
debug_modes = (s1->do_debug ? 1 : 0) | s1->test_coverage << 1;
|
|
||||||
|
|
||||||
tcc_debug_start(s1);
|
|
||||||
tcc_tcov_start (s1);
|
|
||||||
#ifdef TCC_TARGET_ARM
|
|
||||||
arm_init(s1);
|
|
||||||
#endif
|
|
||||||
#ifdef INC_DEBUG
|
#ifdef INC_DEBUG
|
||||||
printf("%s: **** new file\n", file->filename);
|
printf("%s: **** new file\n", file->filename);
|
||||||
#endif
|
#endif
|
||||||
|
@ -402,17 +367,12 @@ ST_FUNC int tccgen_compile(TCCState *s1)
|
||||||
gen_inline_functions(s1);
|
gen_inline_functions(s1);
|
||||||
check_vstack();
|
check_vstack();
|
||||||
/* end of translation unit info */
|
/* end of translation unit info */
|
||||||
#if TCC_EH_FRAME
|
|
||||||
tcc_eh_frame_end(s1);
|
|
||||||
#endif
|
|
||||||
tcc_debug_end(s1);
|
|
||||||
tcc_tcov_end(s1);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void tccgen_finish(TCCState *s1)
|
ST_FUNC void tccgen_finish(TCCState *s1)
|
||||||
{
|
{
|
||||||
tcc_debug_end(s1); /* just in case of errors: free memory */
|
|
||||||
free_inline_functions(s1);
|
free_inline_functions(s1);
|
||||||
sym_pop(&global_stack, NULL, 0);
|
sym_pop(&global_stack, NULL, 0);
|
||||||
sym_pop(&local_stack, NULL, 0);
|
sym_pop(&local_stack, NULL, 0);
|
||||||
|
@ -546,9 +506,6 @@ ST_FUNC void put_extern_sym2(Sym *sym, int sh_num,
|
||||||
info = ELFW(ST_INFO)(sym_bind, sym_type);
|
info = ELFW(ST_INFO)(sym_bind, sym_type);
|
||||||
sym->c = put_elf_sym(symtab_section, value, size, info, other, sh_num, name);
|
sym->c = put_elf_sym(symtab_section, value, size, info, other, sh_num, name);
|
||||||
|
|
||||||
if (debug_modes)
|
|
||||||
tcc_debug_extern_sym(tcc_state, sym, sh_num, sym_bind, sym_type);
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
esym = elfsym(sym);
|
esym = elfsym(sym);
|
||||||
esym->st_value = value;
|
esym->st_value = value;
|
||||||
|
@ -882,13 +839,10 @@ ST_FUNC void vpop(void)
|
||||||
{
|
{
|
||||||
int v;
|
int v;
|
||||||
v = vtop->r & VT_VALMASK;
|
v = vtop->r & VT_VALMASK;
|
||||||
#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
|
|
||||||
/* for x86, we need to pop the FP stack */
|
/* for x86, we need to pop the FP stack */
|
||||||
if (v == TREG_ST0) {
|
if (v == TREG_ST0) {
|
||||||
o(0xd8dd); /* fstp %st(0) */
|
o(0xd8dd); /* fstp %st(0) */
|
||||||
} else
|
} else if (v == VT_CMP) {
|
||||||
#endif
|
|
||||||
if (v == VT_CMP) {
|
|
||||||
/* need to put correct jump if && or || without test */
|
/* need to put correct jump if && or || without test */
|
||||||
gsym(vtop->jtrue);
|
gsym(vtop->jtrue);
|
||||||
gsym(vtop->jfalse);
|
gsym(vtop->jfalse);
|
||||||
|
@ -1375,12 +1329,10 @@ ST_FUNC void save_reg_upstack(int r, int n)
|
||||||
sv.r = VT_LOCAL | VT_LVAL;
|
sv.r = VT_LOCAL | VT_LVAL;
|
||||||
sv.c.i = l;
|
sv.c.i = l;
|
||||||
store(p->r & VT_VALMASK, &sv);
|
store(p->r & VT_VALMASK, &sv);
|
||||||
#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
|
|
||||||
/* x86 specific: need to pop fp register ST0 if saved */
|
/* x86 specific: need to pop fp register ST0 if saved */
|
||||||
if (r == TREG_ST0) {
|
if (r == TREG_ST0) {
|
||||||
o(0xd8dd); /* fstp %st(0) */
|
o(0xd8dd); /* fstp %st(0) */
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
/* special long long case */
|
/* special long long case */
|
||||||
if (p->r2 < VT_CONST && USING_TWO_WORDS(bt)) {
|
if (p->r2 < VT_CONST && USING_TWO_WORDS(bt)) {
|
||||||
sv.c.i += PTR_SIZE;
|
sv.c.i += PTR_SIZE;
|
||||||
|
@ -1404,31 +1356,6 @@ ST_FUNC void save_reg_upstack(int r, int n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TCC_TARGET_ARM
|
|
||||||
/* find a register of class 'rc2' with at most one reference on stack.
|
|
||||||
* If none, call get_reg(rc) */
|
|
||||||
ST_FUNC int get_reg_ex(int rc, int rc2)
|
|
||||||
{
|
|
||||||
int r;
|
|
||||||
SValue *p;
|
|
||||||
|
|
||||||
for(r=0;r<NB_REGS;r++) {
|
|
||||||
if (reg_classes[r] & rc2) {
|
|
||||||
int n;
|
|
||||||
n=0;
|
|
||||||
for(p = vstack; p <= vtop; p++) {
|
|
||||||
if ((p->r & VT_VALMASK) == r ||
|
|
||||||
p->r2 == r)
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
if (n <= 1)
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return get_reg(rc);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* find a free register of class 'rc'. If none, save one register */
|
/* find a free register of class 'rc'. If none, save one register */
|
||||||
ST_FUNC int get_reg(int rc)
|
ST_FUNC int get_reg(int rc)
|
||||||
{
|
{
|
||||||
|
@ -1536,155 +1463,9 @@ ST_FUNC void gaddrof(void)
|
||||||
vtop->r = (vtop->r & ~VT_VALMASK) | VT_LOCAL | VT_LVAL;
|
vtop->r = (vtop->r & ~VT_VALMASK) | VT_LOCAL | VT_LVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
|
||||||
/* generate a bounded pointer addition */
|
|
||||||
static void gen_bounded_ptr_add(void)
|
|
||||||
{
|
|
||||||
int save = (vtop[-1].r & VT_VALMASK) == VT_LOCAL;
|
|
||||||
if (save) {
|
|
||||||
vpushv(&vtop[-1]);
|
|
||||||
vrott(3);
|
|
||||||
}
|
|
||||||
vpush_helper_func(TOK___bound_ptr_add);
|
|
||||||
vrott(3);
|
|
||||||
gfunc_call(2);
|
|
||||||
vtop -= save;
|
|
||||||
vpushi(0);
|
|
||||||
/* returned pointer is in REG_IRET */
|
|
||||||
vtop->r = REG_IRET | VT_BOUNDED;
|
|
||||||
if (nocode_wanted)
|
|
||||||
return;
|
|
||||||
/* relocation offset of the bounding function call point */
|
|
||||||
vtop->c.i = (cur_text_section->reloc->data_offset - sizeof(ElfW_Rel));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* patch pointer addition in vtop so that pointer dereferencing is
|
|
||||||
also tested */
|
|
||||||
static void gen_bounded_ptr_deref(void)
|
|
||||||
{
|
|
||||||
addr_t func;
|
|
||||||
int size, align;
|
|
||||||
ElfW_Rel *rel;
|
|
||||||
Sym *sym;
|
|
||||||
|
|
||||||
if (nocode_wanted)
|
|
||||||
return;
|
|
||||||
|
|
||||||
size = type_size(&vtop->type, &align);
|
|
||||||
switch(size) {
|
|
||||||
case 1: func = TOK___bound_ptr_indir1; break;
|
|
||||||
case 2: func = TOK___bound_ptr_indir2; break;
|
|
||||||
case 4: func = TOK___bound_ptr_indir4; break;
|
|
||||||
case 8: func = TOK___bound_ptr_indir8; break;
|
|
||||||
case 12: func = TOK___bound_ptr_indir12; break;
|
|
||||||
case 16: func = TOK___bound_ptr_indir16; break;
|
|
||||||
default:
|
|
||||||
/* may happen with struct member access */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
sym = external_helper_sym(func);
|
|
||||||
if (!sym->c)
|
|
||||||
put_extern_sym(sym, NULL, 0, 0);
|
|
||||||
/* patch relocation */
|
|
||||||
/* XXX: find a better solution ? */
|
|
||||||
rel = (ElfW_Rel *)(cur_text_section->reloc->data + vtop->c.i);
|
|
||||||
rel->r_info = ELFW(R_INFO)(sym->c, ELFW(R_TYPE)(rel->r_info));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* generate lvalue bound code */
|
|
||||||
static void gbound(void)
|
|
||||||
{
|
|
||||||
CType type1;
|
|
||||||
|
|
||||||
vtop->r &= ~VT_MUSTBOUND;
|
|
||||||
/* if lvalue, then use checking code before dereferencing */
|
|
||||||
if (vtop->r & VT_LVAL) {
|
|
||||||
/* if not VT_BOUNDED value, then make one */
|
|
||||||
if (!(vtop->r & VT_BOUNDED)) {
|
|
||||||
/* must save type because we must set it to int to get pointer */
|
|
||||||
type1 = vtop->type;
|
|
||||||
vtop->type.t = VT_PTR;
|
|
||||||
gaddrof();
|
|
||||||
vpushi(0);
|
|
||||||
gen_bounded_ptr_add();
|
|
||||||
vtop->r |= VT_LVAL;
|
|
||||||
vtop->type = type1;
|
|
||||||
}
|
|
||||||
/* then check for dereferencing */
|
|
||||||
gen_bounded_ptr_deref();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* we need to call __bound_ptr_add before we start to load function
|
|
||||||
args into registers */
|
|
||||||
ST_FUNC void gbound_args(int nb_args)
|
|
||||||
{
|
|
||||||
int i, v;
|
|
||||||
SValue *sv;
|
|
||||||
|
|
||||||
for (i = 1; i <= nb_args; ++i)
|
|
||||||
if (vtop[1 - i].r & VT_MUSTBOUND) {
|
|
||||||
vrotb(i);
|
|
||||||
gbound();
|
|
||||||
vrott(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
sv = vtop - nb_args;
|
|
||||||
if (sv->r & VT_SYM) {
|
|
||||||
v = sv->sym->v;
|
|
||||||
if (v == TOK_setjmp
|
|
||||||
|| v == TOK__setjmp
|
|
||||||
#ifndef TCC_TARGET_PE
|
|
||||||
|| v == TOK_sigsetjmp
|
|
||||||
|| v == TOK___sigsetjmp
|
|
||||||
#endif
|
|
||||||
) {
|
|
||||||
vpush_helper_func(TOK___bound_setjmp);
|
|
||||||
vpushv(sv + 1);
|
|
||||||
gfunc_call(1);
|
|
||||||
func_bound_add_epilog = 1;
|
|
||||||
}
|
|
||||||
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
|
|
||||||
if (v == TOK_alloca)
|
|
||||||
func_bound_add_epilog = 1;
|
|
||||||
#endif
|
|
||||||
#if TARGETOS_NetBSD
|
|
||||||
if (v == TOK_longjmp) /* undo rename to __longjmp14 */
|
|
||||||
sv->sym->asm_label = TOK___bound_longjmp;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add bounds for local symbols from S to E (via ->prev) */
|
|
||||||
static void add_local_bounds(Sym *s, Sym *e)
|
|
||||||
{
|
|
||||||
for (; s != e; s = s->prev) {
|
|
||||||
if (!s->v || (s->r & VT_VALMASK) != VT_LOCAL)
|
|
||||||
continue;
|
|
||||||
/* Add arrays/structs/unions because we always take address */
|
|
||||||
if ((s->type.t & VT_ARRAY)
|
|
||||||
|| (s->type.t & VT_BTYPE) == VT_STRUCT
|
|
||||||
|| s->a.addrtaken) {
|
|
||||||
/* add local bound info */
|
|
||||||
int align, size = type_size(&s->type, &align);
|
|
||||||
addr_t *bounds_ptr = section_ptr_add(lbounds_section,
|
|
||||||
2 * sizeof(addr_t));
|
|
||||||
bounds_ptr[0] = s->c;
|
|
||||||
bounds_ptr[1] = size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Wrapper around sym_pop, that potentially also registers local bounds. */
|
/* Wrapper around sym_pop, that potentially also registers local bounds. */
|
||||||
static void pop_local_syms(Sym *b, int keep)
|
static void pop_local_syms(Sym *b, int keep)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
|
||||||
if (tcc_state->do_bounds_check && !keep && (local_scope || !func_var))
|
|
||||||
add_local_bounds(local_stack, b);
|
|
||||||
#endif
|
|
||||||
if (debug_modes)
|
|
||||||
tcc_add_debug_info (tcc_state, !local_scope, local_stack, b);
|
|
||||||
sym_pop(&local_stack, b, keep);
|
sym_pop(&local_stack, b, keep);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1846,18 +1627,9 @@ ST_FUNC int gv(int rc)
|
||||||
init_putv(&p, &vtop->type, offset);
|
init_putv(&p, &vtop->type, offset);
|
||||||
vtop->r |= VT_LVAL;
|
vtop->r |= VT_LVAL;
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
|
||||||
if (vtop->r & VT_MUSTBOUND)
|
|
||||||
gbound();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bt = vtop->type.t & VT_BTYPE;
|
bt = vtop->type.t & VT_BTYPE;
|
||||||
|
|
||||||
#ifdef TCC_TARGET_RISCV64
|
|
||||||
/* XXX mega hack */
|
|
||||||
if (bt == VT_LDOUBLE && rc == RC_FLOAT)
|
|
||||||
rc = RC_INT;
|
|
||||||
#endif
|
|
||||||
rc2 = RC2_TYPE(bt, rc);
|
rc2 = RC2_TYPE(bt, rc);
|
||||||
|
|
||||||
/* need to reload if:
|
/* need to reload if:
|
||||||
|
@ -1932,11 +1704,6 @@ ST_FUNC int gv(int rc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vtop->r = r;
|
vtop->r = r;
|
||||||
#ifdef TCC_TARGET_C67
|
|
||||||
/* uses register pairs for doubles */
|
|
||||||
if (bt == VT_DOUBLE)
|
|
||||||
vtop->r2 = r+1;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -2066,10 +1833,6 @@ static void gen_opl(int op)
|
||||||
case TOK_UMOD:
|
case TOK_UMOD:
|
||||||
func = TOK___umoddi3;
|
func = TOK___umoddi3;
|
||||||
gen_mod_func:
|
gen_mod_func:
|
||||||
#ifdef TCC_ARM_EABI
|
|
||||||
reg_iret = TREG_R2;
|
|
||||||
reg_lret = TREG_R3;
|
|
||||||
#endif
|
|
||||||
gen_func:
|
gen_func:
|
||||||
/* call generic long long function */
|
/* call generic long long function */
|
||||||
vpush_helper_func(func);
|
vpush_helper_func(func);
|
||||||
|
@ -2445,38 +2208,8 @@ static void gen_opic(int op)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined TCC_TARGET_X86_64 || defined TCC_TARGET_I386
|
#define gen_negf gen_opf
|
||||||
# define gen_negf gen_opf
|
|
||||||
#elif defined TCC_TARGET_ARM
|
|
||||||
void gen_negf(int op)
|
|
||||||
{
|
|
||||||
/* arm will detect 0-x and replace by vneg */
|
|
||||||
vpushi(0), vswap(), gen_op('-');
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
/* XXX: implement in gen_opf() for other backends too */
|
|
||||||
void gen_negf(int op)
|
|
||||||
{
|
|
||||||
/* In IEEE negate(x) isn't subtract(0,x). Without NaNs it's
|
|
||||||
subtract(-0, x), but with them it's really a sign flip
|
|
||||||
operation. We implement this with bit manipulation and have
|
|
||||||
to do some type reinterpretation for this, which TCC can do
|
|
||||||
only via memory. */
|
|
||||||
|
|
||||||
int align, size, bt;
|
|
||||||
|
|
||||||
size = type_size(&vtop->type, &align);
|
|
||||||
bt = vtop->type.t & VT_BTYPE;
|
|
||||||
save_reg(gv(RC_TYPE(bt)));
|
|
||||||
vdup();
|
|
||||||
incr_bf_adr(size - 1);
|
|
||||||
vdup();
|
|
||||||
vpushi(0x80); /* flip sign */
|
|
||||||
gen_op('^');
|
|
||||||
vstore();
|
|
||||||
vpop();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* generate a floating point operation with constant propagation */
|
/* generate a floating point operation with constant propagation */
|
||||||
static void gen_opif(int op)
|
static void gen_opif(int op)
|
||||||
|
@ -3037,21 +2770,7 @@ op_err:
|
||||||
type1 = vtop[-1].type;
|
type1 = vtop[-1].type;
|
||||||
vpush_type_size(pointed_type(&vtop[-1].type), &align);
|
vpush_type_size(pointed_type(&vtop[-1].type), &align);
|
||||||
gen_op('*');
|
gen_op('*');
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
gen_opic(op);
|
||||||
if (tcc_state->do_bounds_check && !CONST_WANTED) {
|
|
||||||
/* if bounded pointers, we generate a special code to
|
|
||||||
test bounds */
|
|
||||||
if (op == '-') {
|
|
||||||
vpushi(0);
|
|
||||||
vswap();
|
|
||||||
gen_op('-');
|
|
||||||
}
|
|
||||||
gen_bounded_ptr_add();
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
gen_opic(op);
|
|
||||||
}
|
|
||||||
type1.t &= ~(VT_ARRAY|VT_VLA);
|
type1.t &= ~(VT_ARRAY|VT_VLA);
|
||||||
/* put again type if gen_opic() swaped operands */
|
/* put again type if gen_opic() swaped operands */
|
||||||
vtop->type = type1;
|
vtop->type = type1;
|
||||||
|
@ -3107,9 +2826,6 @@ op_err:
|
||||||
gv(is_float(vtop->type.t & VT_BTYPE) ? RC_FLOAT : RC_INT);
|
gv(is_float(vtop->type.t & VT_BTYPE) ? RC_FLOAT : RC_INT);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined TCC_TARGET_ARM64 || defined TCC_TARGET_RISCV64 || defined TCC_TARGET_ARM
|
|
||||||
#define gen_cvt_itof1 gen_cvt_itof
|
|
||||||
#else
|
|
||||||
/* generic itof for unsigned long long case */
|
/* generic itof for unsigned long long case */
|
||||||
static void gen_cvt_itof1(int t)
|
static void gen_cvt_itof1(int t)
|
||||||
{
|
{
|
||||||
|
@ -3132,11 +2848,7 @@ static void gen_cvt_itof1(int t)
|
||||||
gen_cvt_itof(t);
|
gen_cvt_itof(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined TCC_TARGET_ARM64 || defined TCC_TARGET_RISCV64
|
|
||||||
#define gen_cvt_ftoi1 gen_cvt_ftoi
|
|
||||||
#else
|
|
||||||
/* generic ftoi for unsigned long long case */
|
/* generic ftoi for unsigned long long case */
|
||||||
static void gen_cvt_ftoi1(int t)
|
static void gen_cvt_ftoi1(int t)
|
||||||
{
|
{
|
||||||
|
@ -3160,7 +2872,6 @@ static void gen_cvt_ftoi1(int t)
|
||||||
gen_cvt_ftoi(t);
|
gen_cvt_ftoi(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/* special delayed cast for char/short */
|
/* special delayed cast for char/short */
|
||||||
static void force_charshort_cast(void)
|
static void force_charshort_cast(void)
|
||||||
|
@ -3217,7 +2928,7 @@ error:
|
||||||
}
|
}
|
||||||
|
|
||||||
c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
|
c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
|
||||||
#if !defined TCC_IS_NATIVE && !defined TCC_IS_NATIVE_387
|
#if !defined TCC_IS_NATIVE_387
|
||||||
/* don't try to convert to ldouble when cross-compiling
|
/* don't try to convert to ldouble when cross-compiling
|
||||||
(except when it's '0' which is needed for arm:gen_negf()) */
|
(except when it's '0' which is needed for arm:gen_negf()) */
|
||||||
if (dbt_bt == VT_LDOUBLE && !nocode_wanted && (sf || vtop->c.i != 0))
|
if (dbt_bt == VT_LDOUBLE && !nocode_wanted && (sf || vtop->c.i != 0))
|
||||||
|
@ -3373,13 +3084,7 @@ error:
|
||||||
if (ds == 8) {
|
if (ds == 8) {
|
||||||
/* need to convert from 32bit to 64bit */
|
/* need to convert from 32bit to 64bit */
|
||||||
if (sbt & VT_UNSIGNED) {
|
if (sbt & VT_UNSIGNED) {
|
||||||
#if defined(TCC_TARGET_RISCV64)
|
|
||||||
/* RISC-V keeps 32bit vals in registers sign-extended.
|
|
||||||
So here we need a zero-extension. */
|
|
||||||
trunc = 32;
|
|
||||||
#else
|
|
||||||
goto done;
|
goto done;
|
||||||
#endif
|
|
||||||
} else {
|
} else {
|
||||||
gen_cvt_sxtw();
|
gen_cvt_sxtw();
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -3389,9 +3094,7 @@ error:
|
||||||
/* RISC-V keeps 32bit vals in registers sign-extended.
|
/* RISC-V keeps 32bit vals in registers sign-extended.
|
||||||
So here we need a sign-extension for signed types and
|
So here we need a sign-extension for signed types and
|
||||||
zero-extension. for unsigned types. */
|
zero-extension. for unsigned types. */
|
||||||
#if !defined(TCC_TARGET_RISCV64)
|
|
||||||
trunc = 32; /* zero upper 32 bits for non RISC-V targets */
|
trunc = 32; /* zero upper 32 bits for non RISC-V targets */
|
||||||
#endif
|
|
||||||
} else {
|
} else {
|
||||||
ss = 4;
|
ss = 4;
|
||||||
}
|
}
|
||||||
|
@ -3399,12 +3102,10 @@ error:
|
||||||
|
|
||||||
if (ds >= ss)
|
if (ds >= ss)
|
||||||
goto done;
|
goto done;
|
||||||
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 || defined TCC_TARGET_ARM64
|
|
||||||
if (ss == 4) {
|
if (ss == 4) {
|
||||||
gen_cvt_csti(dbt);
|
gen_cvt_csti(dbt);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
bits = (ss - ds) * 8;
|
bits = (ss - ds) * 8;
|
||||||
/* for unsigned, gen_op will convert SAR to SHR */
|
/* for unsigned, gen_op will convert SAR to SHR */
|
||||||
vtop->type.t = (ss == 8 ? VT_LLONG : VT_INT) | (dbt & VT_UNSIGNED);
|
vtop->type.t = (ss == 8 ? VT_LLONG : VT_INT) | (dbt & VT_UNSIGNED);
|
||||||
|
@ -3451,8 +3152,7 @@ ST_FUNC int type_size(CType *type, int *a)
|
||||||
*a = LDOUBLE_ALIGN;
|
*a = LDOUBLE_ALIGN;
|
||||||
return LDOUBLE_SIZE;
|
return LDOUBLE_SIZE;
|
||||||
} else if (bt == VT_DOUBLE || bt == VT_LLONG) {
|
} else if (bt == VT_DOUBLE || bt == VT_LLONG) {
|
||||||
#if (defined TCC_TARGET_I386 && !defined TCC_TARGET_PE) \
|
#if (defined TCC_TARGET_I386 && !defined TCC_TARGET_PE)
|
||||||
|| (defined TCC_TARGET_ARM && !defined TCC_ARM_EABI)
|
|
||||||
*a = 4;
|
*a = 4;
|
||||||
#else
|
#else
|
||||||
*a = 8;
|
*a = 8;
|
||||||
|
@ -3632,27 +3332,16 @@ ST_FUNC void vstore(void)
|
||||||
size = type_size(&vtop->type, &align);
|
size = type_size(&vtop->type, &align);
|
||||||
/* destination, keep on stack() as result */
|
/* destination, keep on stack() as result */
|
||||||
vpushv(vtop - 1);
|
vpushv(vtop - 1);
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
|
||||||
if (vtop->r & VT_MUSTBOUND)
|
|
||||||
gbound(); /* check would be wrong after gaddrof() */
|
|
||||||
#endif
|
|
||||||
vtop->type.t = VT_PTR;
|
vtop->type.t = VT_PTR;
|
||||||
gaddrof();
|
gaddrof();
|
||||||
/* source */
|
/* source */
|
||||||
vswap();
|
vswap();
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
|
||||||
if (vtop->r & VT_MUSTBOUND)
|
|
||||||
gbound();
|
|
||||||
#endif
|
|
||||||
vtop->type.t = VT_PTR;
|
vtop->type.t = VT_PTR;
|
||||||
gaddrof();
|
gaddrof();
|
||||||
|
|
||||||
#ifdef TCC_TARGET_NATIVE_STRUCT_COPY
|
#ifdef TCC_TARGET_NATIVE_STRUCT_COPY
|
||||||
if (1
|
if (1) {
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
|
||||||
&& !tcc_state->do_bounds_check
|
|
||||||
#endif
|
|
||||||
) {
|
|
||||||
gen_struct_copy(size);
|
gen_struct_copy(size);
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
|
@ -3660,13 +3349,6 @@ ST_FUNC void vstore(void)
|
||||||
/* type size */
|
/* type size */
|
||||||
vpushi(size);
|
vpushi(size);
|
||||||
/* Use memmove, rather than memcpy, as dest and src may be same: */
|
/* Use memmove, rather than memcpy, as dest and src may be same: */
|
||||||
#ifdef TCC_ARM_EABI
|
|
||||||
if(!(align & 7))
|
|
||||||
vpush_helper_func(TOK_memmove8);
|
|
||||||
else if(!(align & 3))
|
|
||||||
vpush_helper_func(TOK_memmove4);
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
vpush_helper_func(TOK_memmove);
|
vpush_helper_func(TOK_memmove);
|
||||||
vrott(4);
|
vrott(4);
|
||||||
gfunc_call(3);
|
gfunc_call(3);
|
||||||
|
@ -3740,14 +3422,6 @@ ST_FUNC void vstore(void)
|
||||||
gen_cast(&vtop[-1].type);
|
gen_cast(&vtop[-1].type);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
|
||||||
/* bound check case */
|
|
||||||
if (vtop[-1].r & VT_MUSTBOUND) {
|
|
||||||
vswap();
|
|
||||||
gbound();
|
|
||||||
vswap();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
gv(RC_TYPE(dbt)); /* generate value */
|
gv(RC_TYPE(dbt)); /* generate value */
|
||||||
|
|
||||||
if (delayed_cast) {
|
if (delayed_cast) {
|
||||||
|
@ -4283,11 +3957,7 @@ static void struct_layout(CType *type, AttributeDef *ad)
|
||||||
bit_pos = BIT_POS(f->type.t);
|
bit_pos = BIT_POS(f->type.t);
|
||||||
size = type_size(&f->type, &align);
|
size = type_size(&f->type, &align);
|
||||||
|
|
||||||
if (bit_pos + bit_size <= size * 8 && f->c + size <= c
|
if (bit_pos + bit_size <= size * 8 && f->c + size <= c)
|
||||||
#ifdef TCC_TARGET_ARM
|
|
||||||
&& !(f->c & (align - 1))
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* try to access the field using a different type */
|
/* try to access the field using a different type */
|
||||||
|
@ -4313,11 +3983,7 @@ static void struct_layout(CType *type, AttributeDef *ad)
|
||||||
c0 = cx;
|
c0 = cx;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (px + bit_size <= s * 8 && cx + s <= c
|
if (px + bit_size <= s * 8 && cx + s <= c) {
|
||||||
#ifdef TCC_TARGET_ARM
|
|
||||||
&& !(cx & (align - 1))
|
|
||||||
#endif
|
|
||||||
) {
|
|
||||||
/* update offset and bit position */
|
/* update offset and bit position */
|
||||||
f->c = cx;
|
f->c = cx;
|
||||||
bit_pos = px;
|
bit_pos = px;
|
||||||
|
@ -4590,8 +4256,6 @@ do_decl:
|
||||||
check_fields(type, 1);
|
check_fields(type, 1);
|
||||||
check_fields(type, 0);
|
check_fields(type, 0);
|
||||||
struct_layout(type, &ad);
|
struct_layout(type, &ad);
|
||||||
if (debug_modes)
|
|
||||||
tcc_debug_fix_anon(tcc_state, type);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4696,13 +4360,6 @@ static int parse_btype(CType *type, AttributeDef *ad, int ignore_label)
|
||||||
}
|
}
|
||||||
next();
|
next();
|
||||||
break;
|
break;
|
||||||
#ifdef TCC_TARGET_ARM64
|
|
||||||
case TOK_UINT128:
|
|
||||||
/* GCC's __uint128_t appears in some Linux header files. Make it a
|
|
||||||
synonym for long double to get the size and alignment right. */
|
|
||||||
u = VT_LDOUBLE;
|
|
||||||
goto basic_type;
|
|
||||||
#endif
|
|
||||||
case TOK_BOOL:
|
case TOK_BOOL:
|
||||||
u = VT_BOOL;
|
u = VT_BOOL;
|
||||||
goto basic_type;
|
goto basic_type;
|
||||||
|
@ -5222,11 +4879,6 @@ ST_FUNC void indir(void)
|
||||||
if (!(vtop->type.t & (VT_ARRAY | VT_VLA))
|
if (!(vtop->type.t & (VT_ARRAY | VT_VLA))
|
||||||
&& (vtop->type.t & VT_BTYPE) != VT_FUNC) {
|
&& (vtop->type.t & VT_BTYPE) != VT_FUNC) {
|
||||||
vtop->r |= VT_LVAL;
|
vtop->r |= VT_LVAL;
|
||||||
/* if bound checking, the referenced pointer must be checked */
|
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
|
||||||
if (tcc_state->do_bounds_check)
|
|
||||||
vtop->r |= VT_MUSTBOUND;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5487,10 +5139,6 @@ ST_FUNC void unary(void)
|
||||||
Sym *s;
|
Sym *s;
|
||||||
AttributeDef ad;
|
AttributeDef ad;
|
||||||
|
|
||||||
/* generate line number info */
|
|
||||||
if (debug_modes)
|
|
||||||
tcc_debug_line(tcc_state), tcc_tcov_check_line (tcc_state, 1);
|
|
||||||
|
|
||||||
type.ref = NULL;
|
type.ref = NULL;
|
||||||
/* XXX: GCC 2.95.3 does not generate a table although it should be
|
/* XXX: GCC 2.95.3 does not generate a table although it should be
|
||||||
better here */
|
better here */
|
||||||
|
@ -5764,92 +5412,18 @@ ST_FUNC void unary(void)
|
||||||
mk_pointer(&type);
|
mk_pointer(&type);
|
||||||
vset(&type, VT_LOCAL, 0); /* local frame */
|
vset(&type, VT_LOCAL, 0); /* local frame */
|
||||||
while (level--) {
|
while (level--) {
|
||||||
#ifdef TCC_TARGET_RISCV64
|
|
||||||
vpushi(2*PTR_SIZE);
|
|
||||||
gen_op('-');
|
|
||||||
#endif
|
|
||||||
mk_pointer(&vtop->type);
|
mk_pointer(&vtop->type);
|
||||||
indir(); /* -> parent frame */
|
indir(); /* -> parent frame */
|
||||||
}
|
}
|
||||||
if (tok1 == TOK_builtin_return_address) {
|
if (tok1 == TOK_builtin_return_address) {
|
||||||
// assume return address is just above frame pointer on stack
|
// assume return address is just above frame pointer on stack
|
||||||
#ifdef TCC_TARGET_ARM
|
|
||||||
vpushi(2*PTR_SIZE);
|
|
||||||
gen_op('+');
|
|
||||||
#elif defined TCC_TARGET_RISCV64
|
|
||||||
vpushi(PTR_SIZE);
|
|
||||||
gen_op('-');
|
|
||||||
#else
|
|
||||||
vpushi(PTR_SIZE);
|
vpushi(PTR_SIZE);
|
||||||
gen_op('+');
|
gen_op('+');
|
||||||
#endif
|
|
||||||
mk_pointer(&vtop->type);
|
mk_pointer(&vtop->type);
|
||||||
indir();
|
indir();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#ifdef TCC_TARGET_RISCV64
|
|
||||||
case TOK_builtin_va_start:
|
|
||||||
parse_builtin_params(0, "ee");
|
|
||||||
r = vtop->r & VT_VALMASK;
|
|
||||||
if (r == VT_LLOCAL)
|
|
||||||
r = VT_LOCAL;
|
|
||||||
if (r != VT_LOCAL)
|
|
||||||
tcc_error("__builtin_va_start expects a local variable");
|
|
||||||
gen_va_start();
|
|
||||||
vstore();
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
#ifdef TCC_TARGET_X86_64
|
|
||||||
#ifdef TCC_TARGET_PE
|
|
||||||
case TOK_builtin_va_start:
|
|
||||||
parse_builtin_params(0, "ee");
|
|
||||||
r = vtop->r & VT_VALMASK;
|
|
||||||
if (r == VT_LLOCAL)
|
|
||||||
r = VT_LOCAL;
|
|
||||||
if (r != VT_LOCAL)
|
|
||||||
tcc_error("__builtin_va_start expects a local variable");
|
|
||||||
vtop->r = r;
|
|
||||||
vtop->type = char_pointer_type;
|
|
||||||
vtop->c.i += 8;
|
|
||||||
vstore();
|
|
||||||
break;
|
|
||||||
#else
|
|
||||||
case TOK_builtin_va_arg_types:
|
|
||||||
parse_builtin_params(0, "t");
|
|
||||||
vpushi(classify_x86_64_va_arg(&vtop->type));
|
|
||||||
vswap();
|
|
||||||
vpop();
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef TCC_TARGET_ARM64
|
|
||||||
case TOK_builtin_va_start: {
|
|
||||||
parse_builtin_params(0, "ee");
|
|
||||||
//xx check types
|
|
||||||
gen_va_start();
|
|
||||||
vpushi(0);
|
|
||||||
vtop->type.t = VT_VOID;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TOK_builtin_va_arg: {
|
|
||||||
parse_builtin_params(0, "et");
|
|
||||||
type = vtop->type;
|
|
||||||
vpop();
|
|
||||||
//xx check types
|
|
||||||
gen_va_arg(&type);
|
|
||||||
vtop->type = type;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TOK___arm64_clear_cache: {
|
|
||||||
parse_builtin_params(0, "ee");
|
|
||||||
gen_clear_cache();
|
|
||||||
vpushi(0);
|
|
||||||
vtop->type.t = VT_VOID;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* atomic operations */
|
/* atomic operations */
|
||||||
case TOK___atomic_store:
|
case TOK___atomic_store:
|
||||||
|
@ -6066,11 +5640,6 @@ special_math_val:
|
||||||
/* an array is never an lvalue */
|
/* an array is never an lvalue */
|
||||||
if (!(vtop->type.t & VT_ARRAY)) {
|
if (!(vtop->type.t & VT_ARRAY)) {
|
||||||
vtop->r |= VT_LVAL;
|
vtop->r |= VT_LVAL;
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
|
||||||
/* if bound checking, the referenced pointer must be checked */
|
|
||||||
if (tcc_state->do_bounds_check)
|
|
||||||
vtop->r |= VT_MUSTBOUND;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
next();
|
next();
|
||||||
} else if (tok == '[') {
|
} else if (tok == '[') {
|
||||||
|
@ -6113,25 +5682,12 @@ special_math_val:
|
||||||
if (ret_nregs <= 0) {
|
if (ret_nregs <= 0) {
|
||||||
/* get some space for the returned structure */
|
/* get some space for the returned structure */
|
||||||
size = type_size(&s->type, &align);
|
size = type_size(&s->type, &align);
|
||||||
#ifdef TCC_TARGET_ARM64
|
|
||||||
/* On arm64, a small struct is return in registers.
|
|
||||||
It is much easier to write it to memory if we know
|
|
||||||
that we are allowed to write some extra bytes, so
|
|
||||||
round the allocated space up to a power of 2: */
|
|
||||||
if (size < 16)
|
|
||||||
while (size & (size - 1))
|
|
||||||
size = (size | (size - 1)) + 1;
|
|
||||||
#endif
|
|
||||||
loc = (loc - size) & -align;
|
loc = (loc - size) & -align;
|
||||||
ret.type = s->type;
|
ret.type = s->type;
|
||||||
ret.r = VT_LOCAL | VT_LVAL;
|
ret.r = VT_LOCAL | VT_LVAL;
|
||||||
/* pass it as 'int' to avoid structure arg passing
|
/* pass it as 'int' to avoid structure arg passing
|
||||||
problems */
|
problems */
|
||||||
vseti(VT_LOCAL, loc);
|
vseti(VT_LOCAL, loc);
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
|
||||||
if (tcc_state->do_bounds_check)
|
|
||||||
--loc;
|
|
||||||
#endif
|
|
||||||
ret.c = vtop->c;
|
ret.c = vtop->c;
|
||||||
if (ret_nregs < 0)
|
if (ret_nregs < 0)
|
||||||
vtop--;
|
vtop--;
|
||||||
|
@ -6191,9 +5747,6 @@ special_math_val:
|
||||||
|
|
||||||
if (ret_nregs < 0) {
|
if (ret_nregs < 0) {
|
||||||
vsetc(&ret.type, ret.r, &ret.c);
|
vsetc(&ret.type, ret.r, &ret.c);
|
||||||
#ifdef TCC_TARGET_RISCV64
|
|
||||||
arch_transfer_ret_regs(1);
|
|
||||||
#endif
|
|
||||||
} else {
|
} else {
|
||||||
/* return value */
|
/* return value */
|
||||||
n = ret_nregs;
|
n = ret_nregs;
|
||||||
|
@ -6251,8 +5804,6 @@ special_math_val:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (s->f.func_noreturn) {
|
if (s->f.func_noreturn) {
|
||||||
if (debug_modes)
|
|
||||||
tcc_tcov_block_end(tcc_state, -1);
|
|
||||||
CODE_OFF();
|
CODE_OFF();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -6679,7 +6230,7 @@ ST_FUNC int expr_const(void)
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
/* return from function */
|
/* return from function */
|
||||||
|
|
||||||
#ifndef TCC_TARGET_ARM64
|
|
||||||
static void gfunc_return(CType *func_type)
|
static void gfunc_return(CType *func_type)
|
||||||
{
|
{
|
||||||
if ((func_type->t & VT_BTYPE) == VT_STRUCT) {
|
if ((func_type->t & VT_BTYPE) == VT_STRUCT) {
|
||||||
|
@ -6688,9 +6239,6 @@ static void gfunc_return(CType *func_type)
|
||||||
ret_nregs = gfunc_sret(func_type, func_var, &ret_type,
|
ret_nregs = gfunc_sret(func_type, func_var, &ret_type,
|
||||||
&ret_align, ®size);
|
&ret_align, ®size);
|
||||||
if (ret_nregs < 0) {
|
if (ret_nregs < 0) {
|
||||||
#ifdef TCC_TARGET_RISCV64
|
|
||||||
arch_transfer_ret_regs(0);
|
|
||||||
#endif
|
|
||||||
} else if (0 == ret_nregs) {
|
} else if (0 == ret_nregs) {
|
||||||
/* if returning structure, must copy it to implicit
|
/* if returning structure, must copy it to implicit
|
||||||
first pointer arg location */
|
first pointer arg location */
|
||||||
|
@ -6739,7 +6287,6 @@ static void gfunc_return(CType *func_type)
|
||||||
}
|
}
|
||||||
vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
|
vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static void check_func_return(void)
|
static void check_func_return(void)
|
||||||
{
|
{
|
||||||
|
@ -7027,9 +6574,6 @@ again:
|
||||||
goto expr;
|
goto expr;
|
||||||
next();
|
next();
|
||||||
|
|
||||||
if (debug_modes)
|
|
||||||
tcc_tcov_check_line (tcc_state, 0), tcc_tcov_block_begin (tcc_state);
|
|
||||||
|
|
||||||
if (t == TOK_IF) {
|
if (t == TOK_IF) {
|
||||||
new_scope_s(&o);
|
new_scope_s(&o);
|
||||||
skip('(');
|
skip('(');
|
||||||
|
@ -7063,8 +6607,6 @@ again:
|
||||||
prev_scope_s(&o);
|
prev_scope_s(&o);
|
||||||
|
|
||||||
} else if (t == '{') {
|
} else if (t == '{') {
|
||||||
if (debug_modes)
|
|
||||||
tcc_debug_stabn(tcc_state, N_LBRAC, ind - func_ind);
|
|
||||||
new_scope(&o);
|
new_scope(&o);
|
||||||
|
|
||||||
/* handle local labels declarations */
|
/* handle local labels declarations */
|
||||||
|
@ -7089,8 +6631,6 @@ again:
|
||||||
}
|
}
|
||||||
|
|
||||||
prev_scope(&o, flags & STMT_EXPR);
|
prev_scope(&o, flags & STMT_EXPR);
|
||||||
if (debug_modes)
|
|
||||||
tcc_debug_stabn(tcc_state, N_RBRAC, ind - func_ind);
|
|
||||||
if (local_scope)
|
if (local_scope)
|
||||||
next();
|
next();
|
||||||
else if (!nocode_wanted)
|
else if (!nocode_wanted)
|
||||||
|
@ -7118,8 +6658,6 @@ again:
|
||||||
/* jump unless last stmt in top-level block */
|
/* jump unless last stmt in top-level block */
|
||||||
if (tok != '}' || local_scope != 1)
|
if (tok != '}' || local_scope != 1)
|
||||||
rsym = gjmp(rsym);
|
rsym = gjmp(rsym);
|
||||||
if (debug_modes)
|
|
||||||
tcc_tcov_block_end (tcc_state, -1);
|
|
||||||
CODE_OFF();
|
CODE_OFF();
|
||||||
|
|
||||||
} else if (t == TOK_BREAK) {
|
} else if (t == TOK_BREAK) {
|
||||||
|
@ -7332,8 +6870,6 @@ again:
|
||||||
AttributeDef ad_tmp;
|
AttributeDef ad_tmp;
|
||||||
parse_attribute(&ad_tmp);
|
parse_attribute(&ad_tmp);
|
||||||
}
|
}
|
||||||
if (debug_modes)
|
|
||||||
tcc_tcov_reset_ind(tcc_state);
|
|
||||||
vla_restore(cur_scope->vla.loc);
|
vla_restore(cur_scope->vla.loc);
|
||||||
|
|
||||||
if (tok != '}') {
|
if (tok != '}') {
|
||||||
|
@ -7360,9 +6896,6 @@ again:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (debug_modes)
|
|
||||||
tcc_tcov_check_line (tcc_state, 0), tcc_tcov_block_end (tcc_state, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This skips over a stream of tokens containing balanced {} and ()
|
/* This skips over a stream of tokens containing balanced {} and ()
|
||||||
|
@ -7459,9 +6992,6 @@ static void init_putz(init_params *p, unsigned long c, int size)
|
||||||
vseti(VT_LOCAL, c);
|
vseti(VT_LOCAL, c);
|
||||||
vpushi(0);
|
vpushi(0);
|
||||||
vpushs(size);
|
vpushs(size);
|
||||||
#if defined TCC_TARGET_ARM && defined TCC_ARM_EABI
|
|
||||||
vswap(); /* using __aeabi_memset(void*, size_t, int) */
|
|
||||||
#endif
|
|
||||||
gfunc_call(3);
|
gfunc_call(3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7834,10 +7364,6 @@ static void decl_initializer(init_params *p, CType *type, unsigned long c, int f
|
||||||
Sym indexsym;
|
Sym indexsym;
|
||||||
CType *t1;
|
CType *t1;
|
||||||
|
|
||||||
/* generate line number info */
|
|
||||||
if (debug_modes && !(flags & DIF_SIZE_ONLY) && !p->sec)
|
|
||||||
tcc_debug_line(tcc_state), tcc_tcov_check_line (tcc_state, 1);
|
|
||||||
|
|
||||||
if (!(flags & DIF_HAVE_ELEM) && tok != '{' &&
|
if (!(flags & DIF_HAVE_ELEM) && tok != '{' &&
|
||||||
/* In case of strings we have special handling for arrays, so
|
/* In case of strings we have special handling for arrays, so
|
||||||
don't consume them as initializer value (which would commit them
|
don't consume them as initializer value (which would commit them
|
||||||
|
@ -8060,9 +7586,6 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
|
||||||
Sym *flexible_array;
|
Sym *flexible_array;
|
||||||
Sym *sym;
|
Sym *sym;
|
||||||
int saved_nocode_wanted = nocode_wanted;
|
int saved_nocode_wanted = nocode_wanted;
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
|
||||||
int bcheck = tcc_state->do_bounds_check && !NODATA_WANTED;
|
|
||||||
#endif
|
|
||||||
init_params p = {0};
|
init_params p = {0};
|
||||||
|
|
||||||
/* Always allocate static or global variables */
|
/* Always allocate static or global variables */
|
||||||
|
@ -8151,21 +7674,10 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
|
||||||
|
|
||||||
if ((r & VT_VALMASK) == VT_LOCAL) {
|
if ((r & VT_VALMASK) == VT_LOCAL) {
|
||||||
sec = NULL;
|
sec = NULL;
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
|
||||||
if (bcheck && v) {
|
|
||||||
/* add padding between stack variables for bound checking */
|
|
||||||
loc -= align;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
loc = (loc - size) & -align;
|
loc = (loc - size) & -align;
|
||||||
addr = loc;
|
addr = loc;
|
||||||
p.local_offset = addr + size;
|
p.local_offset = addr + size;
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
|
||||||
if (bcheck && v) {
|
|
||||||
/* add padding between stack variables for bound checking */
|
|
||||||
loc -= align;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (v) {
|
if (v) {
|
||||||
/* local variable */
|
/* local variable */
|
||||||
#ifdef CONFIG_TCC_ASM
|
#ifdef CONFIG_TCC_ASM
|
||||||
|
@ -8229,11 +7741,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
|
||||||
|
|
||||||
if (sec) {
|
if (sec) {
|
||||||
addr = section_add(sec, size, align);
|
addr = section_add(sec, size, align);
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
|
||||||
/* add padding if bound check */
|
|
||||||
if (bcheck)
|
|
||||||
section_add(sec, 1, 1);
|
|
||||||
#endif
|
|
||||||
} else {
|
} else {
|
||||||
addr = align; /* SHN_COMMON is special, symbol value is align */
|
addr = align; /* SHN_COMMON is special, symbol value is align */
|
||||||
sec = common_section;
|
sec = common_section;
|
||||||
|
@ -8253,19 +7761,6 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
|
||||||
vtop->r |= r;
|
vtop->r |= r;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
|
||||||
/* handles bounds now because the symbol must be defined
|
|
||||||
before for the relocation */
|
|
||||||
if (bcheck) {
|
|
||||||
addr_t *bounds_ptr;
|
|
||||||
|
|
||||||
greloca(bounds_section, sym, bounds_section->data_offset, R_DATA_PTR, 0);
|
|
||||||
/* then add global bound info */
|
|
||||||
bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(addr_t));
|
|
||||||
bounds_ptr[0] = 0; /* relocated */
|
|
||||||
bounds_ptr[1] = size;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type->t & VT_VLA) {
|
if (type->t & VT_VLA) {
|
||||||
|
@ -8286,11 +7781,6 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
|
||||||
|
|
||||||
vpush_type_size(type, &a);
|
vpush_type_size(type, &a);
|
||||||
gen_vla_alloc(type, a);
|
gen_vla_alloc(type, a);
|
||||||
#if defined TCC_TARGET_PE && defined TCC_TARGET_X86_64
|
|
||||||
/* on _WIN64, because of the function args scratch area, the
|
|
||||||
result of alloca differs from RSP and is returned in RAX. */
|
|
||||||
gen_vla_result(addr), addr = (loc -= PTR_SIZE);
|
|
||||||
#endif
|
|
||||||
gen_vla_sp_save(addr);
|
gen_vla_sp_save(addr);
|
||||||
cur_scope->vla.loc = addr;
|
cur_scope->vla.loc = addr;
|
||||||
cur_scope->vla.num++;
|
cur_scope->vla.num++;
|
||||||
|
@ -8381,15 +7871,12 @@ static void gen_function(Sym *sym)
|
||||||
if (sym->type.ref->f.func_dtor)
|
if (sym->type.ref->f.func_dtor)
|
||||||
add_array (tcc_state, ".fini_array", sym->c);
|
add_array (tcc_state, ".fini_array", sym->c);
|
||||||
|
|
||||||
/* put debug symbol */
|
|
||||||
tcc_debug_funcstart(tcc_state, sym);
|
|
||||||
|
|
||||||
/* push a dummy symbol to enable local sym storage */
|
/* push a dummy symbol to enable local sym storage */
|
||||||
sym_push2(&local_stack, SYM_FIELD, 0, 0);
|
sym_push2(&local_stack, SYM_FIELD, 0, 0);
|
||||||
local_scope = 1; /* for function parameters */
|
local_scope = 1; /* for function parameters */
|
||||||
nb_temp_local_vars = 0;
|
nb_temp_local_vars = 0;
|
||||||
gfunc_prolog(sym);
|
gfunc_prolog(sym);
|
||||||
tcc_debug_prolog_epilog(tcc_state, 0);
|
|
||||||
|
|
||||||
local_scope = 0;
|
local_scope = 0;
|
||||||
rsym = 0;
|
rsym = 0;
|
||||||
|
@ -8400,11 +7887,8 @@ static void gen_function(Sym *sym)
|
||||||
nocode_wanted = 0;
|
nocode_wanted = 0;
|
||||||
/* reset local stack */
|
/* reset local stack */
|
||||||
pop_local_syms(NULL, 0);
|
pop_local_syms(NULL, 0);
|
||||||
tcc_debug_prolog_epilog(tcc_state, 1);
|
|
||||||
gfunc_epilog();
|
gfunc_epilog();
|
||||||
|
|
||||||
/* end of function */
|
|
||||||
tcc_debug_funcend(tcc_state, ind - func_ind);
|
|
||||||
|
|
||||||
/* patch symbol size */
|
/* patch symbol size */
|
||||||
elfsym(sym)->st_size = ind - func_ind;
|
elfsym(sym)->st_size = ind - func_ind;
|
||||||
|
@ -8691,8 +8175,6 @@ static int decl(int l)
|
||||||
sym->a = ad.a;
|
sym->a = ad.a;
|
||||||
if ((type.t & VT_BTYPE) == VT_FUNC)
|
if ((type.t & VT_BTYPE) == VT_FUNC)
|
||||||
merge_funcattr(&sym->type.ref->f, &ad.f);
|
merge_funcattr(&sym->type.ref->f, &ad.f);
|
||||||
if (debug_modes)
|
|
||||||
tcc_debug_typedef (tcc_state, sym);
|
|
||||||
} else if ((type.t & VT_BTYPE) == VT_VOID
|
} else if ((type.t & VT_BTYPE) == VT_VOID
|
||||||
&& !(type.t & VT_EXTERN)) {
|
&& !(type.t & VT_EXTERN)) {
|
||||||
tcc_error("declaration of void object");
|
tcc_error("declaration of void object");
|
|
@ -20,6 +20,8 @@
|
||||||
|
|
||||||
#include "tcc.h"
|
#include "tcc.h"
|
||||||
|
|
||||||
|
#define TCC_OUTPUT_DLL 666
|
||||||
|
|
||||||
#define PE_MERGE_DATA 1
|
#define PE_MERGE_DATA 1
|
||||||
#define PE_PRINT_SECTIONS 0
|
#define PE_PRINT_SECTIONS 0
|
||||||
|
|
||||||
|
@ -1880,22 +1882,6 @@ static void pe_add_runtime(TCCState *s1, struct pe_info *pe)
|
||||||
++start_symbol;
|
++start_symbol;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_TCC_BACKTRACE
|
|
||||||
if (s1->do_backtrace) {
|
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
|
||||||
if (s1->do_bounds_check && s1->output_type != TCC_OUTPUT_DLL)
|
|
||||||
tcc_add_support(s1, "bcheck.o");
|
|
||||||
#endif
|
|
||||||
if (s1->output_type == TCC_OUTPUT_EXE)
|
|
||||||
tcc_add_support(s1, "bt-exe.o");
|
|
||||||
if (s1->output_type == TCC_OUTPUT_DLL)
|
|
||||||
tcc_add_support(s1, "bt-dll.o");
|
|
||||||
if (s1->output_type != TCC_OUTPUT_DLL)
|
|
||||||
tcc_add_support(s1, "bt-log.o");
|
|
||||||
tcc_add_btstub(s1);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* grab the startup code from libtcc1.a */
|
/* grab the startup code from libtcc1.a */
|
||||||
#ifdef TCC_IS_NATIVE
|
#ifdef TCC_IS_NATIVE
|
||||||
if (TCC_OUTPUT_MEMORY != s1->output_type || s1->run_main)
|
if (TCC_OUTPUT_MEMORY != s1->output_type || s1->run_main)
|
||||||
|
@ -1982,9 +1968,6 @@ ST_FUNC int pe_output_file(TCCState *s1, const char *filename)
|
||||||
pe.s1 = s1;
|
pe.s1 = s1;
|
||||||
s1->filetype = 0;
|
s1->filetype = 0;
|
||||||
|
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
|
||||||
tcc_add_bcheck(s1);
|
|
||||||
#endif
|
|
||||||
tcc_add_pragma_libs(s1);
|
tcc_add_pragma_libs(s1);
|
||||||
pe_add_runtime(s1, &pe);
|
pe_add_runtime(s1, &pe);
|
||||||
resolve_common_syms(s1);
|
resolve_common_syms(s1);
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
#define USING_GLOBALS
|
#define USING_GLOBALS
|
||||||
#include "tcc.h"
|
#include "tcc.h"
|
||||||
|
#include "utils/string.h"
|
||||||
|
|
||||||
/* #define to 1 to enable (see parse_pp_string()) */
|
/* #define to 1 to enable (see parse_pp_string()) */
|
||||||
#define ACCEPT_LF_IN_STRINGS 0
|
#define ACCEPT_LF_IN_STRINGS 0
|
||||||
|
@ -946,12 +947,8 @@ redo_start:
|
||||||
else if (parse_flags & PARSE_FLAG_ASM_FILE)
|
else if (parse_flags & PARSE_FLAG_ASM_FILE)
|
||||||
p = parse_line_comment(p - 1);
|
p = parse_line_comment(p - 1);
|
||||||
}
|
}
|
||||||
#if !defined(TCC_TARGET_ARM)
|
|
||||||
else if (parse_flags & PARSE_FLAG_ASM_FILE)
|
else if (parse_flags & PARSE_FLAG_ASM_FILE)
|
||||||
p = parse_line_comment(p - 1);
|
p = parse_line_comment(p - 1);
|
||||||
#else
|
|
||||||
/* ARM assembly uses '#' for constants */
|
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
_default:
|
_default:
|
||||||
default:
|
default:
|
||||||
|
@ -1326,8 +1323,8 @@ static void maybe_run_test(TCCState *s)
|
||||||
p = get_tok_str(tok, NULL);
|
p = get_tok_str(tok, NULL);
|
||||||
if (0 != memcmp(p, "test_", 5))
|
if (0 != memcmp(p, "test_", 5))
|
||||||
return;
|
return;
|
||||||
if (0 != --s->run_test)
|
/*if (0 != --s->run_test)
|
||||||
return;
|
return;*/
|
||||||
fprintf(s->ppfp, &"\n[%s]\n"[!(s->dflag & 32)], p), fflush(s->ppfp);
|
fprintf(s->ppfp, &"\n[%s]\n"[!(s->dflag & 32)], p), fflush(s->ppfp);
|
||||||
define_push(tok, MACRO_OBJ, NULL, NULL);
|
define_push(tok, MACRO_OBJ, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
@ -1446,8 +1443,6 @@ static int parse_include(TCCState *s1, int do_next, int test)
|
||||||
dynarray_add(&s1->target_deps, &s1->nb_target_deps,
|
dynarray_add(&s1->target_deps, &s1->nb_target_deps,
|
||||||
tcc_strdup(buf));
|
tcc_strdup(buf));
|
||||||
}
|
}
|
||||||
/* add include file debug info */
|
|
||||||
tcc_debug_bincl(s1);
|
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -1479,8 +1474,6 @@ static int expr_preprocess(TCCState *s1)
|
||||||
parse_flags |= PARSE_FLAG_PREPROCESS;
|
parse_flags |= PARSE_FLAG_PREPROCESS;
|
||||||
if (tok < TOK_IDENT)
|
if (tok < TOK_IDENT)
|
||||||
expect("identifier after 'defined'");
|
expect("identifier after 'defined'");
|
||||||
if (s1->run_test)
|
|
||||||
maybe_run_test(s1);
|
|
||||||
c = 0;
|
c = 0;
|
||||||
if (define_find(tok)
|
if (define_find(tok)
|
||||||
|| tok == TOK___HAS_INCLUDE
|
|| tok == TOK___HAS_INCLUDE
|
||||||
|
@ -1806,7 +1799,6 @@ ST_FUNC void tccpp_putfile(const char *filename)
|
||||||
if (file->true_filename == file->filename)
|
if (file->true_filename == file->filename)
|
||||||
file->true_filename = tcc_strdup(file->filename);
|
file->true_filename = tcc_strdup(file->filename);
|
||||||
pstrcpy(file->filename, sizeof file->filename, buf);
|
pstrcpy(file->filename, sizeof file->filename, buf);
|
||||||
tcc_debug_newfile(tcc_state);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* is_bof is true if first non space token at beginning of file */
|
/* is_bof is true if first non space token at beginning of file */
|
||||||
|
@ -2615,8 +2607,6 @@ static void next_nomacro(void)
|
||||||
tok_flags &= ~TOK_FLAG_ENDIF;
|
tok_flags &= ~TOK_FLAG_ENDIF;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add end of include file debug info */
|
|
||||||
tcc_debug_eincl(tcc_state);
|
|
||||||
/* pop include stack */
|
/* pop include stack */
|
||||||
tcc_close();
|
tcc_close();
|
||||||
s1->include_stack_ptr--;
|
s1->include_stack_ptr--;
|
||||||
|
@ -2653,12 +2643,10 @@ maybe_newline:
|
||||||
p++;
|
p++;
|
||||||
tok = TOK_TWOSHARPS;
|
tok = TOK_TWOSHARPS;
|
||||||
} else {
|
} else {
|
||||||
#if !defined(TCC_TARGET_ARM)
|
|
||||||
if (parse_flags & PARSE_FLAG_ASM_FILE) {
|
if (parse_flags & PARSE_FLAG_ASM_FILE) {
|
||||||
p = parse_line_comment(p - 1);
|
p = parse_line_comment(p - 1);
|
||||||
goto redo_no_start;
|
goto redo_no_start;
|
||||||
} else
|
} else
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
tok = '#';
|
tok = '#';
|
||||||
}
|
}
|
||||||
|
@ -3576,24 +3564,12 @@ static void tcc_predefs(TCCState *s1, CString *cs, int is_asm)
|
||||||
putdefs(cs, target_machine_defs);
|
putdefs(cs, target_machine_defs);
|
||||||
putdefs(cs, target_os_defs);
|
putdefs(cs, target_os_defs);
|
||||||
|
|
||||||
#ifdef TCC_TARGET_ARM
|
|
||||||
if (s1->float_abi == ARM_HARD_FLOAT)
|
|
||||||
putdef(cs, "__ARM_PCS_VFP");
|
|
||||||
#endif
|
|
||||||
if (is_asm)
|
if (is_asm)
|
||||||
putdef(cs, "__ASSEMBLER__");
|
putdef(cs, "__ASSEMBLER__");
|
||||||
if (s1->output_type == TCC_OUTPUT_PREPROCESS)
|
if (s1->output_type == TCC_OUTPUT_PREPROCESS)
|
||||||
putdef(cs, "__TCC_PP__");
|
putdef(cs, "__TCC_PP__");
|
||||||
if (s1->output_type == TCC_OUTPUT_MEMORY)
|
if (s1->output_type == TCC_OUTPUT_MEMORY)
|
||||||
putdef(cs, "__TCC_RUN__");
|
putdef(cs, "__TCC_RUN__");
|
||||||
#ifdef CONFIG_TCC_BACKTRACE
|
|
||||||
if (s1->do_backtrace)
|
|
||||||
putdef(cs, "__TCC_BACKTRACE__");
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
|
||||||
if (s1->do_bounds_check)
|
|
||||||
putdef(cs, "__TCC_BCHECK__");
|
|
||||||
#endif
|
|
||||||
if (s1->char_is_unsigned)
|
if (s1->char_is_unsigned)
|
||||||
putdef(cs, "__CHAR_UNSIGNED__");
|
putdef(cs, "__CHAR_UNSIGNED__");
|
||||||
if (s1->optimize > 0)
|
if (s1->optimize > 0)
|
|
@ -68,10 +68,6 @@
|
||||||
DEF(TOK_TYPEOF3, "__typeof__")
|
DEF(TOK_TYPEOF3, "__typeof__")
|
||||||
DEF(TOK_LABEL, "__label__")
|
DEF(TOK_LABEL, "__label__")
|
||||||
|
|
||||||
#ifdef TCC_TARGET_ARM64
|
|
||||||
DEF(TOK_UINT128, "__uint128_t")
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*********************************************************************/
|
/*********************************************************************/
|
||||||
/* the following are not keywords. They are included to ease parsing */
|
/* the following are not keywords. They are included to ease parsing */
|
||||||
/* preprocessor only */
|
/* preprocessor only */
|
||||||
|
@ -105,10 +101,6 @@
|
||||||
DEF(TOK___NAN__, "__nan__")
|
DEF(TOK___NAN__, "__nan__")
|
||||||
DEF(TOK___SNAN__, "__snan__")
|
DEF(TOK___SNAN__, "__snan__")
|
||||||
DEF(TOK___INF__, "__inf__")
|
DEF(TOK___INF__, "__inf__")
|
||||||
#if defined TCC_TARGET_X86_64
|
|
||||||
DEF(TOK___mzerosf, "__mzerosf") /* -0.0 */
|
|
||||||
DEF(TOK___mzerodf, "__mzerodf") /* -0.0 */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* attribute identifiers */
|
/* attribute identifiers */
|
||||||
/* XXX: handle all tokens generically since speed is not critical */
|
/* XXX: handle all tokens generically since speed is not critical */
|
||||||
|
@ -173,16 +165,6 @@
|
||||||
DEF(TOK_builtin_expect, "__builtin_expect")
|
DEF(TOK_builtin_expect, "__builtin_expect")
|
||||||
DEF(TOK_builtin_unreachable, "__builtin_unreachable")
|
DEF(TOK_builtin_unreachable, "__builtin_unreachable")
|
||||||
/*DEF(TOK_builtin_va_list, "__builtin_va_list")*/
|
/*DEF(TOK_builtin_va_list, "__builtin_va_list")*/
|
||||||
#if defined TCC_TARGET_PE && defined TCC_TARGET_X86_64
|
|
||||||
DEF(TOK_builtin_va_start, "__builtin_va_start")
|
|
||||||
#elif defined TCC_TARGET_X86_64
|
|
||||||
DEF(TOK_builtin_va_arg_types, "__builtin_va_arg_types")
|
|
||||||
#elif defined TCC_TARGET_ARM64
|
|
||||||
DEF(TOK_builtin_va_start, "__builtin_va_start")
|
|
||||||
DEF(TOK_builtin_va_arg, "__builtin_va_arg")
|
|
||||||
#elif defined TCC_TARGET_RISCV64
|
|
||||||
DEF(TOK_builtin_va_start, "__builtin_va_start")
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* atomic operations */
|
/* atomic operations */
|
||||||
#define DEF_ATOMIC(ID) DEF(TOK_##__##ID, "__"#ID)
|
#define DEF_ATOMIC(ID) DEF(TOK_##__##ID, "__"#ID)
|
||||||
|
@ -205,13 +187,6 @@
|
||||||
|
|
||||||
/* pragma */
|
/* pragma */
|
||||||
DEF(TOK_pack, "pack")
|
DEF(TOK_pack, "pack")
|
||||||
#if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_X86_64) && \
|
|
||||||
!defined(TCC_TARGET_ARM) && !defined(TCC_TARGET_ARM64) && \
|
|
||||||
!defined(TCC_TARGET_RISCV64)
|
|
||||||
/* already defined for assembler */
|
|
||||||
DEF(TOK_ASM_push, "push")
|
|
||||||
DEF(TOK_ASM_pop, "pop")
|
|
||||||
#endif
|
|
||||||
DEF(TOK_comment, "comment")
|
DEF(TOK_comment, "comment")
|
||||||
DEF(TOK_lib, "lib")
|
DEF(TOK_lib, "lib")
|
||||||
DEF(TOK_push_macro, "push_macro")
|
DEF(TOK_push_macro, "push_macro")
|
||||||
|
@ -220,7 +195,6 @@
|
||||||
DEF(TOK_option, "option")
|
DEF(TOK_option, "option")
|
||||||
|
|
||||||
/* builtin functions or variables */
|
/* builtin functions or variables */
|
||||||
#ifndef TCC_ARM_EABI
|
|
||||||
DEF(TOK_memcpy, "memcpy")
|
DEF(TOK_memcpy, "memcpy")
|
||||||
DEF(TOK_memmove, "memmove")
|
DEF(TOK_memmove, "memmove")
|
||||||
DEF(TOK_memset, "memset")
|
DEF(TOK_memset, "memset")
|
||||||
|
@ -233,134 +207,16 @@
|
||||||
DEF(TOK___ashldi3, "__ashldi3")
|
DEF(TOK___ashldi3, "__ashldi3")
|
||||||
DEF(TOK___floatundisf, "__floatundisf")
|
DEF(TOK___floatundisf, "__floatundisf")
|
||||||
DEF(TOK___floatundidf, "__floatundidf")
|
DEF(TOK___floatundidf, "__floatundidf")
|
||||||
# ifndef TCC_ARM_VFP
|
|
||||||
DEF(TOK___floatundixf, "__floatundixf")
|
DEF(TOK___floatundixf, "__floatundixf")
|
||||||
DEF(TOK___fixunsxfdi, "__fixunsxfdi")
|
DEF(TOK___fixunsxfdi, "__fixunsxfdi")
|
||||||
# endif
|
|
||||||
DEF(TOK___fixunssfdi, "__fixunssfdi")
|
DEF(TOK___fixunssfdi, "__fixunssfdi")
|
||||||
DEF(TOK___fixunsdfdi, "__fixunsdfdi")
|
DEF(TOK___fixunsdfdi, "__fixunsdfdi")
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined TCC_TARGET_ARM
|
|
||||||
# ifdef TCC_ARM_EABI
|
|
||||||
DEF(TOK_memcpy, "__aeabi_memcpy")
|
|
||||||
DEF(TOK_memmove, "__aeabi_memmove")
|
|
||||||
DEF(TOK_memmove4, "__aeabi_memmove4")
|
|
||||||
DEF(TOK_memmove8, "__aeabi_memmove8")
|
|
||||||
DEF(TOK_memset, "__aeabi_memset")
|
|
||||||
DEF(TOK___aeabi_ldivmod, "__aeabi_ldivmod")
|
|
||||||
DEF(TOK___aeabi_uldivmod, "__aeabi_uldivmod")
|
|
||||||
DEF(TOK___aeabi_idivmod, "__aeabi_idivmod")
|
|
||||||
DEF(TOK___aeabi_uidivmod, "__aeabi_uidivmod")
|
|
||||||
DEF(TOK___divsi3, "__aeabi_idiv")
|
|
||||||
DEF(TOK___udivsi3, "__aeabi_uidiv")
|
|
||||||
DEF(TOK___floatdisf, "__aeabi_l2f")
|
|
||||||
DEF(TOK___floatdidf, "__aeabi_l2d")
|
|
||||||
DEF(TOK___fixsfdi, "__aeabi_f2lz")
|
|
||||||
DEF(TOK___fixdfdi, "__aeabi_d2lz")
|
|
||||||
DEF(TOK___ashrdi3, "__aeabi_lasr")
|
|
||||||
DEF(TOK___lshrdi3, "__aeabi_llsr")
|
|
||||||
DEF(TOK___ashldi3, "__aeabi_llsl")
|
|
||||||
DEF(TOK___floatundisf, "__aeabi_ul2f")
|
|
||||||
DEF(TOK___floatundidf, "__aeabi_ul2d")
|
|
||||||
DEF(TOK___fixunssfdi, "__aeabi_f2ulz")
|
|
||||||
DEF(TOK___fixunsdfdi, "__aeabi_d2ulz")
|
|
||||||
# else
|
|
||||||
DEF(TOK___modsi3, "__modsi3")
|
|
||||||
DEF(TOK___umodsi3, "__umodsi3")
|
|
||||||
DEF(TOK___divsi3, "__divsi3")
|
|
||||||
DEF(TOK___udivsi3, "__udivsi3")
|
|
||||||
DEF(TOK___floatdisf, "__floatdisf")
|
|
||||||
DEF(TOK___floatdidf, "__floatdidf")
|
|
||||||
# ifndef TCC_ARM_VFP
|
|
||||||
DEF(TOK___floatdixf, "__floatdixf")
|
|
||||||
DEF(TOK___fixunssfsi, "__fixunssfsi")
|
|
||||||
DEF(TOK___fixunsdfsi, "__fixunsdfsi")
|
|
||||||
DEF(TOK___fixunsxfsi, "__fixunsxfsi")
|
|
||||||
DEF(TOK___fixxfdi, "__fixxfdi")
|
|
||||||
# endif
|
|
||||||
DEF(TOK___fixsfdi, "__fixsfdi")
|
|
||||||
DEF(TOK___fixdfdi, "__fixdfdi")
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined TCC_TARGET_C67
|
|
||||||
DEF(TOK__divi, "_divi")
|
|
||||||
DEF(TOK__divu, "_divu")
|
|
||||||
DEF(TOK__divf, "_divf")
|
|
||||||
DEF(TOK__divd, "_divd")
|
|
||||||
DEF(TOK__remi, "_remi")
|
|
||||||
DEF(TOK__remu, "_remu")
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined TCC_TARGET_I386
|
|
||||||
DEF(TOK___fixsfdi, "__fixsfdi")
|
DEF(TOK___fixsfdi, "__fixsfdi")
|
||||||
DEF(TOK___fixdfdi, "__fixdfdi")
|
DEF(TOK___fixdfdi, "__fixdfdi")
|
||||||
DEF(TOK___fixxfdi, "__fixxfdi")
|
DEF(TOK___fixxfdi, "__fixxfdi")
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
|
|
||||||
DEF(TOK_alloca, "alloca")
|
DEF(TOK_alloca, "alloca")
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined TCC_TARGET_PE
|
|
||||||
DEF(TOK___chkstk, "__chkstk")
|
|
||||||
#endif
|
|
||||||
#if defined TCC_TARGET_ARM64 || defined TCC_TARGET_RISCV64
|
|
||||||
DEF(TOK___arm64_clear_cache, "__arm64_clear_cache")
|
|
||||||
DEF(TOK___addtf3, "__addtf3")
|
|
||||||
DEF(TOK___subtf3, "__subtf3")
|
|
||||||
DEF(TOK___multf3, "__multf3")
|
|
||||||
DEF(TOK___divtf3, "__divtf3")
|
|
||||||
DEF(TOK___extendsftf2, "__extendsftf2")
|
|
||||||
DEF(TOK___extenddftf2, "__extenddftf2")
|
|
||||||
DEF(TOK___trunctfsf2, "__trunctfsf2")
|
|
||||||
DEF(TOK___trunctfdf2, "__trunctfdf2")
|
|
||||||
DEF(TOK___fixtfsi, "__fixtfsi")
|
|
||||||
DEF(TOK___fixtfdi, "__fixtfdi")
|
|
||||||
DEF(TOK___fixunstfsi, "__fixunstfsi")
|
|
||||||
DEF(TOK___fixunstfdi, "__fixunstfdi")
|
|
||||||
DEF(TOK___floatsitf, "__floatsitf")
|
|
||||||
DEF(TOK___floatditf, "__floatditf")
|
|
||||||
DEF(TOK___floatunsitf, "__floatunsitf")
|
|
||||||
DEF(TOK___floatunditf, "__floatunditf")
|
|
||||||
DEF(TOK___eqtf2, "__eqtf2")
|
|
||||||
DEF(TOK___netf2, "__netf2")
|
|
||||||
DEF(TOK___lttf2, "__lttf2")
|
|
||||||
DEF(TOK___letf2, "__letf2")
|
|
||||||
DEF(TOK___gttf2, "__gttf2")
|
|
||||||
DEF(TOK___getf2, "__getf2")
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* bound checking symbols */
|
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
|
||||||
DEF(TOK___bound_ptr_add, "__bound_ptr_add")
|
|
||||||
DEF(TOK___bound_ptr_indir1, "__bound_ptr_indir1")
|
|
||||||
DEF(TOK___bound_ptr_indir2, "__bound_ptr_indir2")
|
|
||||||
DEF(TOK___bound_ptr_indir4, "__bound_ptr_indir4")
|
|
||||||
DEF(TOK___bound_ptr_indir8, "__bound_ptr_indir8")
|
|
||||||
DEF(TOK___bound_ptr_indir12, "__bound_ptr_indir12")
|
|
||||||
DEF(TOK___bound_ptr_indir16, "__bound_ptr_indir16")
|
|
||||||
DEF(TOK___bound_main_arg, "__bound_main_arg")
|
|
||||||
DEF(TOK___bound_local_new, "__bound_local_new")
|
|
||||||
DEF(TOK___bound_local_delete, "__bound_local_delete")
|
|
||||||
DEF(TOK___bound_setjmp, "__bound_setjmp")
|
|
||||||
DEF(TOK___bound_longjmp, "__bound_longjmp")
|
|
||||||
DEF(TOK___bound_new_region, "__bound_new_region")
|
|
||||||
# ifdef TCC_TARGET_PE
|
|
||||||
# ifdef TCC_TARGET_X86_64
|
|
||||||
DEF(TOK___bound_alloca_nr, "__bound_alloca_nr")
|
|
||||||
# endif
|
|
||||||
# else
|
|
||||||
DEF(TOK_sigsetjmp, "sigsetjmp")
|
|
||||||
DEF(TOK___sigsetjmp, "__sigsetjmp")
|
|
||||||
DEF(TOK_siglongjmp, "siglongjmp")
|
|
||||||
# endif
|
|
||||||
DEF(TOK_setjmp, "setjmp")
|
|
||||||
DEF(TOK__setjmp, "_setjmp")
|
|
||||||
DEF(TOK_longjmp, "longjmp")
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*********************************************************************/
|
/*********************************************************************/
|
||||||
/* Tiny Assembler */
|
/* Tiny Assembler */
|
||||||
|
@ -401,28 +257,12 @@
|
||||||
DEF_ASMDIR(endr)
|
DEF_ASMDIR(endr)
|
||||||
DEF_ASMDIR(org)
|
DEF_ASMDIR(org)
|
||||||
DEF_ASMDIR(quad)
|
DEF_ASMDIR(quad)
|
||||||
#if defined(TCC_TARGET_I386)
|
|
||||||
DEF_ASMDIR(code16)
|
DEF_ASMDIR(code16)
|
||||||
DEF_ASMDIR(code32)
|
DEF_ASMDIR(code32)
|
||||||
#elif defined(TCC_TARGET_X86_64)
|
|
||||||
DEF_ASMDIR(code64)
|
|
||||||
#elif defined(TCC_TARGET_RISCV64)
|
|
||||||
DEF_ASMDIR(option)
|
|
||||||
#endif
|
|
||||||
DEF_ASMDIR(short)
|
DEF_ASMDIR(short)
|
||||||
DEF_ASMDIR(long)
|
DEF_ASMDIR(long)
|
||||||
DEF_ASMDIR(int)
|
DEF_ASMDIR(int)
|
||||||
DEF_ASMDIR(symver)
|
DEF_ASMDIR(symver)
|
||||||
DEF_ASMDIR(section) /* must be last directive */
|
DEF_ASMDIR(section) /* must be last directive */
|
||||||
|
|
||||||
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
|
#include "i386/tok.h"
|
||||||
#include "i386-tok.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined TCC_TARGET_ARM || defined TCC_TARGET_ARM64
|
|
||||||
#include "arm-tok.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined TCC_TARGET_RISCV64
|
|
||||||
#include "riscv64-tok.h"
|
|
||||||
#endif
|
|
47
libtcc/utils/string.h
Normal file
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.
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "tcc.h"
|
#include "libtcc/tcc.h"
|
||||||
|
|
||||||
//#define ARMAG "!<arch>\n"
|
//#define ARMAG "!<arch>\n"
|
||||||
#define ARFMAG "`\n"
|
#define ARFMAG "`\n"
|
10
tcc/tcctools.h
Normal file
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