diff --git a/Makefile.am b/Makefile.am index d53d090e..63cdd78f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,3 +1 @@ -AM_CFLAGS = - -SUBDIRS = libtcc tcc +SUBDIRS = libtcc tcc libtcc1 diff --git a/compile_flags.txt b/compile_flags.txt index 3f2296c6..cb70eca4 100644 --- a/compile_flags.txt +++ b/compile_flags.txt @@ -1,3 +1,4 @@ -I. -DHAVE_CONFIG_H +-Ilibtcc/include -Ilibtcc \ No newline at end of file diff --git a/configure.ac b/configure.ac index 96555617..8d46a549 100644 --- a/configure.ac +++ b/configure.ac @@ -10,7 +10,8 @@ AC_CONFIG_HEADERS([config.h]) AC_CONFIG_FILES([ Makefile libtcc/Makefile - tcc/Makefile]) + tcc/Makefile + libtcc1/Makefile]) AC_LANG([C]) AC_PROG_CC @@ -18,6 +19,7 @@ AC_PROG_CPP AC_PROG_CC_C_O AC_PROG_RANLIB AM_PROG_AR +AM_PROG_AS AC_CHECK_INCLUDES_DEFAULT AC_C_CONST diff --git a/libtcc/Makefile.am b/libtcc/Makefile.am index 8f07c714..d71779c9 100644 --- a/libtcc/Makefile.am +++ b/libtcc/Makefile.am @@ -3,4 +3,4 @@ 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 \ No newline at end of file +libtcc_a_CPPFLAGS = -I$(top_srcdir) -I$(srcdir) -I$(srcdir)/include \ No newline at end of file diff --git a/libtcc/i386/asm.c b/libtcc/i386/asm.c index 6f101b8c..af159a49 100644 --- a/libtcc/i386/asm.c +++ b/libtcc/i386/asm.c @@ -21,6 +21,7 @@ #define USING_GLOBALS #include "tcc.h" +#include "token.h" #define MAX_OPERANDS 3 @@ -201,7 +202,7 @@ static const ASMInstr asm_instrs[] = { #define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) { TOK_ASM_ ## name, O(opcode), T(opcode, instr_type, group), 2, { op0, op1 }}, #define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) { TOK_ASM_ ## name, O(opcode), T(opcode, instr_type, group), 3, { op0, op1, op2 }}, -#include "asm.h" +#include "asm.inc" /* last operation */ { 0, }, }; @@ -213,7 +214,7 @@ static const uint16_t op0_codes[] = { #define DEF_ASM_OP1(name, opcode, group, instr_type, op0) #define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) #define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) -#include "asm.h" +#include "asm.inc" }; static inline int get_reg_shift(TCCState *s1) @@ -382,7 +383,7 @@ static void parse_operand(TCCState *s1, Operand *op) } /* XXX: unify with C code output ? */ -ST_FUNC void gen_expr32(ExprValue *pe) +void gen_expr32(ExprValue *pe) { if (pe->pcrel) /* If PC-relative, always set VT_SYM, even without symbol, @@ -501,7 +502,7 @@ static void maybe_print_stats (void) } } -ST_FUNC void asm_opcode(TCCState *s1, int opcode) +void asm_opcode(TCCState *s1, int opcode) { const ASMInstr *pa; int i, modrm_index, modreg_index, reg, v, op1, seg_prefix, pc, p; @@ -962,7 +963,7 @@ static const char *skip_constraint_modifiers(const char *p) /* If T (a token) is of the form "%reg" returns the register number and type, otherwise return -1. */ -ST_FUNC int asm_parse_regvar (int t) +int asm_parse_regvar (int t) { const char *s; Operand op; @@ -987,7 +988,7 @@ ST_FUNC int asm_parse_regvar (int t) #define is_reg_allocated(reg) (regs_allocated[reg] & reg_mask) -ST_FUNC void asm_compute_constraints(ASMOperand *operands, +void asm_compute_constraints(ASMOperand *operands, int nb_operands, int nb_outputs, const uint8_t *clobber_regs, int *pout_reg) @@ -1239,7 +1240,7 @@ ST_FUNC void asm_compute_constraints(ASMOperand *operands, #endif } -ST_FUNC void subst_asm_operand(CString *add_str, +void subst_asm_operand(CString *add_str, SValue *sv, int modifier) { int r, reg, size, val; @@ -1328,7 +1329,7 @@ ST_FUNC void subst_asm_operand(CString *add_str, } /* generate prolog and epilog code for asm statement */ -ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands, +void asm_gen_code(ASMOperand *operands, int nb_operands, int nb_outputs, int is_output, uint8_t *clobber_regs, int out_reg) @@ -1425,7 +1426,7 @@ ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands, } } -ST_FUNC void asm_clobber(uint8_t *clobber_regs, const char *str) +void asm_clobber(uint8_t *clobber_regs, const char *str) { int reg; diff --git a/libtcc/i386/asm.h b/libtcc/i386/asm.inc similarity index 100% rename from libtcc/i386/asm.h rename to libtcc/i386/asm.inc diff --git a/libtcc/i386/gen.c b/libtcc/i386/gen.c index f50a422c..f3996cfc 100644 --- a/libtcc/i386/gen.c +++ b/libtcc/i386/gen.c @@ -18,70 +18,11 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef TARGET_DEFS_ONLY - -/* number of available registers */ -#define NB_REGS 5 -#define NB_ASM_REGS 8 -#define CONFIG_TCC_ASM - -/* a register can belong to several classes. The classes must be - sorted from more general to more precise (see gv2() code which does - assumptions on it). */ -#define RC_INT 0x0001 /* generic integer register */ -#define RC_FLOAT 0x0002 /* generic float register */ -#define RC_EAX 0x0004 -#define RC_EDX 0x0008 -#define RC_ECX 0x0010 -#define RC_EBX 0x0020 -#define RC_ST0 0x0040 - -#define RC_IRET RC_EAX /* function return: integer register */ -#define RC_IRE2 RC_EDX /* function return: second integer register */ -#define RC_FRET RC_ST0 /* function return: float register */ - -/* pretty names for the registers */ -enum { - TREG_EAX = 0, - TREG_ECX, - TREG_EDX, - TREG_EBX, - TREG_ST0, - TREG_ESP = 4 -}; - -/* return registers for function */ -#define REG_IRET TREG_EAX /* single word int return register */ -#define REG_IRE2 TREG_EDX /* second word return register (for long long) */ -#define REG_FRET TREG_ST0 /* float return register */ - -/* defined if function parameters must be evaluated in reverse order */ -#define INVERT_FUNC_PARAMS - -/* defined if structures are passed as pointers. Otherwise structures - are directly pushed on stack. */ -/* #define FUNC_STRUCT_PARAM_AS_PTR */ - -/* pointer size, in bytes */ -#define PTR_SIZE 4 - -/* long double size and alignment, in bytes */ -#define LDOUBLE_SIZE 12 -#define LDOUBLE_ALIGN 4 -/* maximum alignment (for aligned attribute support) */ -#define MAX_ALIGN 8 - -/* define if return values need to be extended explicitely - at caller side (for interfacing with non-TCC compilers) */ -#define PROMOTE_RET - -/******************************************************/ -#else /* ! TARGET_DEFS_ONLY */ -/******************************************************/ #define USING_GLOBALS -#include "tcc.h" +#include +#include "token.h" -ST_DATA const char * const target_machine_defs = +const char * const target_machine_defs = "__i386__\0" "__i386\0" ; @@ -89,7 +30,7 @@ ST_DATA const char * const target_machine_defs = /* define to 1/0 to [not] have EBX as 4th register */ #define USE_EBX 0 -ST_DATA const int reg_classes[NB_REGS] = { +const int reg_classes[NB_REGS] = { /* eax */ RC_INT | RC_EAX, /* ecx */ RC_INT | RC_ECX, /* edx */ RC_INT | RC_EDX, @@ -101,7 +42,7 @@ static unsigned long func_sub_sp_offset; static int func_ret_sub; /* XXX: make it faster ? */ -ST_FUNC void g(int c) +void g(int c) { int ind1; if (nocode_wanted) @@ -113,7 +54,7 @@ ST_FUNC void g(int c) ind = ind1; } -ST_FUNC void o(unsigned int c) +void o(unsigned int c) { while (c) { g(c); @@ -121,13 +62,13 @@ ST_FUNC void o(unsigned int c) } } -ST_FUNC void gen_le16(int v) +void gen_le16(int v) { g(v); g(v >> 8); } -ST_FUNC void gen_le32(int c) +void gen_le32(int c) { g(c); g(c >> 8); @@ -136,7 +77,7 @@ ST_FUNC void gen_le32(int c) } /* output a symbol and patch all calls to it */ -ST_FUNC void gsym_addr(int t, int a) +void gsym_addr(int t, int a) { while (t) { unsigned char *ptr = cur_text_section->data + t; @@ -158,7 +99,7 @@ static int oad(int c, int s) return t; } -ST_FUNC void gen_fill_nops(int bytes) +void gen_fill_nops(int bytes) { while (bytes--) g(0x90); @@ -168,14 +109,14 @@ ST_FUNC void gen_fill_nops(int bytes) #define gjmp2(instr,lbl) oad(instr,lbl) /* output constant with relocation if 'r & VT_SYM' is true */ -ST_FUNC void gen_addr32(int r, Sym *sym, int c) +void gen_addr32(int r, Sym *sym, int c) { if (r & VT_SYM) greloc(cur_text_section, sym, ind, R_386_32); gen_le32(c); } -ST_FUNC void gen_addrpc32(int r, Sym *sym, int c) +void gen_addrpc32(int r, Sym *sym, int c) { if (r & VT_SYM) greloc(cur_text_section, sym, ind, R_386_PC32); @@ -206,7 +147,7 @@ static void gen_modrm(int op_reg, int r, Sym *sym, int c) } /* load 'r' from value 'sv' */ -ST_FUNC void load(int r, SValue *sv) +void load(int r, SValue *sv) { int v, t, ft, fc, fr; SValue v1; @@ -281,7 +222,7 @@ ST_FUNC void load(int r, SValue *sv) } /* store register 'r' in lvalue 'v' */ -ST_FUNC void store(int r, SValue *v) +void store(int r, SValue *v) { int fr, bt, ft, fc; @@ -349,7 +290,7 @@ static const uint8_t fastcallw_regs[2] = { TREG_ECX, TREG_EDX }; /* Return the number of registers needed to return the struct, or 0 if returning via struct pointer. */ -ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *regsize) +int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *regsize) { #if defined(TCC_TARGET_PE) || TARGETOS_FreeBSD || TARGETOS_OpenBSD int size, align, nregs; @@ -370,6 +311,10 @@ ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int ret->ref = NULL; return nregs; #else + (void)vt; + (void)variadic; + (void)ret; + (void)regsize; *ret_align = 1; // Never have to re-align return values for x86 return 0; #endif @@ -378,7 +323,7 @@ ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int /* Generate function call. The function address is pushed first, then all the parameters in call order. This functions pops all the parameters and the function address. */ -ST_FUNC void gfunc_call(int nb_args) +void gfunc_call(int nb_args) { int size, align, r, args_size, i, func_call; Sym *func_sym; @@ -488,7 +433,7 @@ ST_FUNC void gfunc_call(int nb_args) #endif /* generate function prolog of type 't' */ -ST_FUNC void gfunc_prolog(Sym *func_sym) +void gfunc_prolog(Sym *func_sym) { CType *func_type = &func_sym->type; int addr, align, size, func_call, fastcall_nb_regs; @@ -571,7 +516,7 @@ ST_FUNC void gfunc_prolog(Sym *func_sym) } /* generate function epilog */ -ST_FUNC void gfunc_epilog(void) +void gfunc_epilog(void) { addr_t v, saved_ind; @@ -612,13 +557,13 @@ ST_FUNC void gfunc_epilog(void) } /* generate a jump to a label */ -ST_FUNC int gjmp(int t) +int gjmp(int t) { return gjmp2(0xe9, t); } /* generate a jump to a fixed address */ -ST_FUNC void gjmp_addr(int a) +void gjmp_addr(int a) { int r; r = a - ind - 2; @@ -632,7 +577,7 @@ ST_FUNC void gjmp_addr(int a) #if 0 /* generate a jump to a fixed address */ -ST_FUNC void gjmp_cond_addr(int a, int op) +void gjmp_cond_addr(int a, int op) { int r = a - ind - 2; if (r == (char)r) @@ -642,7 +587,7 @@ ST_FUNC void gjmp_cond_addr(int a, int op) } #endif -ST_FUNC int gjmp_append(int n, int t) +int gjmp_append(int n, int t) { void *p; /* insert vtop->c jump list in t */ @@ -656,14 +601,14 @@ ST_FUNC int gjmp_append(int n, int t) return t; } -ST_FUNC int gjmp_cond(int op, int t) +int gjmp_cond(int op, int t) { g(0x0f); t = gjmp2(op - 16, t); return t; } -ST_FUNC void gen_opi(int op) +void gen_opi(int op) { int r, fr, opc, c; @@ -802,7 +747,7 @@ ST_FUNC void gen_opi(int op) /* generate a floating point operation 'v = t1 op t2' instruction. The two operands are guaranteed to have the same floating point type */ /* XXX: need to use ST1 too */ -ST_FUNC void gen_opf(int op) +void gen_opf(int op) { int a, ft, fc, swapped, r; @@ -923,7 +868,7 @@ ST_FUNC void gen_opf(int op) /* convert integers to fp 't' type. Must handle 'int', 'unsigned int' and 'long long' cases. */ -ST_FUNC void gen_cvt_itof(int t) +void gen_cvt_itof(void) { save_reg(TREG_ST0); gv(RC_INT); @@ -954,7 +899,7 @@ ST_FUNC void gen_cvt_itof(int t) } /* convert fp to int 't' type */ -ST_FUNC void gen_cvt_ftoi(int t) +void gen_cvt_ftoi(int t) { int bt = vtop->type.t & VT_BTYPE; if (bt == VT_FLOAT) @@ -972,14 +917,14 @@ ST_FUNC void gen_cvt_ftoi(int t) } /* convert from one floating point type to another */ -ST_FUNC void gen_cvt_ftof(int t) +void gen_cvt_ftof(void) { /* all we have to do on i386 is to put the float in a register */ gv(RC_FLOAT); } /* char/short to int conversion */ -ST_FUNC void gen_cvt_csti(int t) +void gen_cvt_csti(int t) { int r, sz, xl; r = gv(RC_INT); @@ -992,7 +937,7 @@ ST_FUNC void gen_cvt_csti(int t) } /* increment tcov counter */ -ST_FUNC void gen_increment_tcov (SValue *sv) +void gen_increment_tcov (SValue *sv) { o(0x0583); /* addl $1, xxx */ greloc(cur_text_section, sv->sym, ind, R_386_32); @@ -1005,27 +950,27 @@ ST_FUNC void gen_increment_tcov (SValue *sv) } /* computed goto support */ -ST_FUNC void ggoto(void) +void ggoto(void) { gcall_or_jmp(1); vtop--; } /* Save the stack pointer onto the stack */ -ST_FUNC void gen_vla_sp_save(int addr) { +void gen_vla_sp_save(int addr) { /* mov %esp,addr(%ebp)*/ o(0x89); gen_modrm(TREG_ESP, VT_LOCAL, NULL, addr); } /* Restore the SP from a location on the stack */ -ST_FUNC void gen_vla_sp_restore(int addr) { +void gen_vla_sp_restore(int addr) { o(0x8b); gen_modrm(TREG_ESP, VT_LOCAL, NULL, addr); } /* Subtract from the stack pointer, and push the resulting value onto the stack */ -ST_FUNC void gen_vla_alloc(CType *type, int align) { +void gen_vla_alloc(CType *type, int align) { int use_call = 0; #ifdef TCC_TARGET_PE /* alloca does more than just adjust %rsp on Windows */ @@ -1051,6 +996,3 @@ ST_FUNC void gen_vla_alloc(CType *type, int align) { } /* end of X86 code generator */ -/*************************************************************/ -#endif -/*************************************************************/ diff --git a/libtcc/i386/link.c b/libtcc/i386/link.c index 005a8ee2..7cf6e56c 100644 --- a/libtcc/i386/link.c +++ b/libtcc/i386/link.c @@ -1,31 +1,9 @@ -#ifdef TARGET_DEFS_ONLY - -#define EM_TCC_TARGET EM_386 - -/* relocation type for 32 bit data relocation */ -#define R_DATA_32 R_386_32 -#define R_DATA_PTR R_386_32 -#define R_JMP_SLOT R_386_JMP_SLOT -#define R_GLOB_DAT R_386_GLOB_DAT -#define R_COPY R_386_COPY -#define R_RELATIVE R_386_RELATIVE - -#define R_NUM R_386_NUM - -#define ELF_START_ADDR 0x08048000 -#define ELF_PAGE_SIZE 0x1000 - -#define PCRELATIVE_DLLPLT 0 -#define RELOCATE_DLLPLT 1 - -#else /* !TARGET_DEFS_ONLY */ - -#include "tcc.h" +#include #ifdef NEED_RELOC_TYPE /* Returns 1 for a code relocation, 0 for a data relocation. For unknown relocations, returns -1. */ -ST_FUNC int code_reloc (int reloc_type) +int code_reloc (int reloc_type) { switch (reloc_type) { case R_386_RELATIVE: @@ -55,7 +33,7 @@ ST_FUNC int code_reloc (int reloc_type) /* Returns an enumerator to describe whether and when the relocation needs a GOT and/or PLT entry to be created. See tcc.h for a description of the different values. */ -ST_FUNC int gotplt_entry_type (int reloc_type) +int gotplt_entry_type (int reloc_type) { switch (reloc_type) { case R_386_RELATIVE: @@ -92,7 +70,7 @@ ST_FUNC int gotplt_entry_type (int reloc_type) } #ifdef NEED_BUILD_GOT -ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr) +unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr) { Section *plt = s1->plt; uint8_t *p; @@ -134,7 +112,7 @@ ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_ /* relocate the PLT: compute addresses and offsets in the PLT now that final address for PLT and GOT are known (see fill_program_header) */ -ST_FUNC void relocate_plt(TCCState *s1) +void relocate_plt(TCCState *s1) { uint8_t *p, *p_end; @@ -167,9 +145,9 @@ ST_FUNC void relocate_plt(TCCState *s1) #endif #endif -ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val) +void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val) { - int sym_index, esym_index; + int sym_index; sym_index = ELFW(R_SYM)(rel->r_info); @@ -295,5 +273,3 @@ ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, return; } } - -#endif /* !TARGET_DEFS_ONLY */ diff --git a/libtcc/i386/tok.h b/libtcc/i386/token.inc similarity index 99% rename from libtcc/i386/tok.h rename to libtcc/i386/token.inc index b1450bdf..e48a5358 100644 --- a/libtcc/i386/tok.h +++ b/libtcc/i386/token.inc @@ -266,7 +266,7 @@ #define DEF_ASM_OP1(name, opcode, group, instr_type, op0) #define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) #define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) -#include "asm.h" +#include "asm.inc" #define ALT(x) #define DEF_ASM_OP0(name, opcode) @@ -274,4 +274,4 @@ #define DEF_ASM_OP1(name, opcode, group, instr_type, op0) DEF_ASM(name) #define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) DEF_ASM(name) #define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) DEF_ASM(name) -#include "asm.h" +#include "asm.inc" diff --git a/libtcc/libtcc.h b/libtcc/include/libtcc.h similarity index 100% rename from libtcc/libtcc.h rename to libtcc/include/libtcc.h diff --git a/libtcc/tcc.h b/libtcc/include/tcc.h similarity index 63% rename from libtcc/tcc.h rename to libtcc/include/tcc.h index 90527855..b26eeda9 100644 --- a/libtcc/tcc.h +++ b/libtcc/include/tcc.h @@ -32,9 +32,8 @@ #ifdef __TINYC__ # undef __attribute__ #endif + #include -#include -#include #include #include #include @@ -68,24 +67,6 @@ extern long double strtold (const char *__nptr, char **__endptr); # define strtoll _strtoi64 # define strtoull _strtoui64 # endif -# ifdef LIBTCC_AS_DLL -# define __declspec(dllexport) -# define PUB_FUNC LIBTCCAPI -# endif -# ifdef _MSC_VER -# pragma warning (disable : 4244) // conversion from 'uint64_t' to 'int', possible loss of data -# pragma warning (disable : 4267) // conversion from 'size_t' to 'int', possible loss of data -# pragma warning (disable : 4996) // The POSIX name for this item is deprecated. Instead, use the ISO C and C++ conformant name -# pragma warning (disable : 4018) // signed/unsigned mismatch -# pragma warning (disable : 4146) // unary minus operator applied to unsigned type, result still unsigned -# define ssize_t intptr_t -# ifdef _X86_ -# define __i386__ 1 -# endif -# ifdef _AMD64_ -# define __x86_64__ 1 -# endif -# endif # ifndef va_copy # define va_copy(a,b) a = b # endif @@ -103,16 +84,6 @@ extern long double strtold (const char *__nptr, char **__endptr); #define countof(tab) (sizeof(tab) / sizeof((tab)[0])) #endif -#ifdef _MSC_VER -# define NORETURN __declspec(noreturn) -# define ALIGNED(x) __declspec(align(x)) -# define PRINTF_LIKE(x,y) -#else -# define NORETURN __attribute__((noreturn)) -# define ALIGNED(x) __attribute__((aligned(x))) -# define PRINTF_LIKE(x,y) __attribute__ ((format (printf, (x), (y)))) -#endif - #ifdef _WIN32 # define IS_DIRSEP(c) (c == '/' || c == '\\') # define IS_ABSPATH(p) (IS_DIRSEP(p[0]) || (p[0] && p[1] == ':' && IS_DIRSEP(p[2]))) @@ -138,8 +109,6 @@ extern long double strtold (const char *__nptr, char **__endptr); /* assembler debug */ /* #define ASM_DEBUG */ -# define TCC_TARGET_I386 - #ifdef CONFIG_TCC_PIE # define CONFIG_TCC_PIC 1 #endif @@ -181,43 +150,20 @@ extern long double strtold (const char *__nptr, char **__endptr); /* system include paths */ #ifndef CONFIG_TCC_SYSINCLUDEPATHS -# if defined TCC_TARGET_PE || defined _WIN32 -# define CONFIG_TCC_SYSINCLUDEPATHS "{B}/include"PATHSEP"{B}/include/winapi" -# else -# define CONFIG_TCC_SYSINCLUDEPATHS \ + +# define CONFIG_TCC_SYSINCLUDEPATHS \ "{B}/include" \ ":" ALSO_TRIPLET(CONFIG_SYSROOT "/usr/local/include") \ ":" ALSO_TRIPLET(CONFIG_SYSROOT CONFIG_USR_INCLUDE) -# endif #endif /* library search paths */ #ifndef CONFIG_TCC_LIBPATHS -# if defined TCC_TARGET_PE || defined _WIN32 -# define CONFIG_TCC_LIBPATHS "{B}/lib" -# else -# define CONFIG_TCC_LIBPATHS \ +# define CONFIG_TCC_LIBPATHS \ "{B}" \ ":" ALSO_TRIPLET(CONFIG_SYSROOT "/usr/" CONFIG_LDDIR) \ ":" ALSO_TRIPLET(CONFIG_SYSROOT "/" CONFIG_LDDIR) \ ":" ALSO_TRIPLET(CONFIG_SYSROOT "/usr/local/" CONFIG_LDDIR) -# endif -#endif - -/* name of ELF interpreter */ -#ifndef CONFIG_TCC_ELFINTERP -# if defined __GNU__ -# define CONFIG_TCC_ELFINTERP "/lib/ld.so" -# elif defined(TCC_TARGET_PE) -# define CONFIG_TCC_ELFINTERP "-" -# else -# define CONFIG_TCC_ELFINTERP "/lib/ld-linux.so.2" -# endif -#endif - -/* var elf_interp dans *-gen.c */ -#ifndef DEFAULT_ELFINTERP -# define DEFAULT_ELFINTERP(s) CONFIG_TCC_ELFINTERP #endif /* (target specific) libtcc1.a */ @@ -225,11 +171,6 @@ extern long double strtold (const char *__nptr, char **__endptr); # define TCC_LIBTCC1 "libtcc1.a" #endif -/* library to use with CONFIG_USE_LIBGCC instead of libtcc1.a */ -#if defined CONFIG_USE_LIBGCC && !defined TCC_LIBGCC -#define TCC_LIBGCC USE_TRIPLET(CONFIG_SYSROOT "/" CONFIG_LDDIR) "/libgcc_s.so.1" -#endif - /* libtcc1.a */ #ifndef CONFIG_TCC_CROSSPREFIX # define CONFIG_TCC_CROSSPREFIX "" @@ -237,9 +178,9 @@ extern long double strtold (const char *__nptr, char **__endptr); /* -------------------------------------------- */ -#include "libtcc.h" -#include "elf.h" -#include "coff.h" +#include +#include +#include /* -------------------------------------------- */ @@ -247,22 +188,10 @@ extern long double strtold (const char *__nptr, char **__endptr); # define PUB_FUNC #endif -#define ST_INLN -#define ST_FUNC -#define ST_DATA extern - -#ifdef TCC_PROFILE /* profile all functions */ -# define static -# define inline -#endif - /* -------------------------------------------- */ /* include the target specific definitions */ - -#define TARGET_DEFS_ONLY -# include "i386/gen.c" -# include "i386/link.c" -#undef TARGET_DEFS_ONLY +# include "tcc/i386/gen.h" +# include "tcc/i386/link.h" # define ELFCLASSW ELFCLASS32 # define ElfW(type) Elf##32##_##type @@ -275,7 +204,7 @@ extern long double strtold (const char *__nptr, char **__endptr); #define addr_t ElfW(Addr) #define ElfSym ElfW(Sym) -# define LONG_SIZE 4 +#define LONG_SIZE 4 /* -------------------------------------------- */ @@ -302,11 +231,7 @@ typedef struct TokenSym { char str[1]; } TokenSym; -#ifdef TCC_TARGET_PE -typedef unsigned short nwchar_t; -#else typedef int nwchar_t; -#endif typedef struct CString { int size; /* size in bytes */ @@ -435,13 +360,6 @@ typedef struct Section { char name[1]; /* section name */ } Section; -typedef struct DLLReference { - int level; - void *handle; - unsigned char found, index; - char name[1]; -} DLLReference; - /* -------------------------------------------------- */ #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */ @@ -546,7 +464,6 @@ typedef struct CachedInclude { #define CACHED_INCLUDES_HASH_SIZE 32 -#ifdef CONFIG_TCC_ASM typedef struct ExprValue { uint64_t v; Sym *sym; @@ -568,7 +485,6 @@ typedef struct ASMOperand { int is_rw; /* for '+' modifier */ int is_label; /* for asm goto */ } ASMOperand; -#endif /* extra symbol attributes (not in symbol table) */ struct sym_attr { @@ -583,8 +499,6 @@ struct TCCState { unsigned char nostdinc; /* if true, no standard headers are added */ unsigned char nostdlib; /* if true, no standard libraries are added */ unsigned char nocommon; /* if true, do not use common symbols for .bss data */ - unsigned char static_link; /* if true, static linking is performed */ - unsigned char rdynamic; /* if true, all symbols are exported */ unsigned char symbolic; /* if true, resolve symbols in the current module first */ unsigned char filetype; /* file type for compilation (NONE,C,ASM) */ unsigned char optimize; /* only to #define __OPTIMIZE__ */ @@ -635,7 +549,6 @@ struct TCCState { int seg_size; /* 32. Can be 16 with i386 assembler (.code16) */ char *tcc_lib_path; /* CONFIG_TCCDIR or -B option */ - char *soname; /* as specified on the command line (-soname) */ char *rpath; /* as specified on the command line (-Wl,-rpath=) */ char *elf_entryname; /* "_start" unless set */ char *init_symbol; /* symbols to call at load-time (not used currently) */ @@ -647,10 +560,6 @@ struct TCCState { /* output format, see TCC_OUTPUT_FORMAT_xxx */ int output_format; - /* array of all loaded dlls (including those referenced by loaded dlls) */ - DLLReference **loaded_dlls; - int nb_loaded_dlls; - /* include paths */ char **include_paths; int nb_include_paths; @@ -721,8 +630,6 @@ struct TCCState { Section *cur_text_section; /* current section where function code is generated */ /* symbol section */ union { Section *symtab_section, *symtab; }; /* historical alias */ - /* temporary dynamic symbol sections (for dll loading) */ - Section *dynsymtab_section; /* exported dynamic symbol section */ Section *dynsym; /* got & plt handling */ @@ -741,15 +648,6 @@ struct TCCState { ElfW_Rel *qrel; #define qrel s1->qrel -#ifdef TCC_TARGET_PE - /* PE info */ - int pe_subsystem; - unsigned pe_characteristics; - unsigned pe_file_align; - unsigned pe_stack_size; - addr_t pe_imagebase; -#endif - #ifndef ELF_OBJ_ONLY int nb_sym_versions; struct sym_version *sym_versions; @@ -766,9 +664,6 @@ struct TCCState { unsigned int total_bytes; unsigned int total_output[4]; - /* option -dnum (for general development purposes) */ - int g_debug; - /* used by tcc_load_ldscript */ int fd, cc; @@ -871,107 +766,11 @@ struct filespec { #define BFGET(X,M) (((X) & (M)) / BFVAL(M,1)) #define BFSET(X,M,N) ((X) = ((X) & ~(M)) | BFVAL(M,N)) -/* token values */ - -/* conditional ops */ -#define TOK_LAND 0x90 -#define TOK_LOR 0x91 -/* warning: the following compare tokens depend on i386 asm code */ -#define TOK_ULT 0x92 -#define TOK_UGE 0x93 -#define TOK_EQ 0x94 -#define TOK_NE 0x95 -#define TOK_ULE 0x96 -#define TOK_UGT 0x97 -#define TOK_Nset 0x98 -#define TOK_Nclear 0x99 -#define TOK_LT 0x9c -#define TOK_GE 0x9d -#define TOK_LE 0x9e -#define TOK_GT 0x9f - -#define TOK_ISCOND(t) (t >= TOK_LAND && t <= TOK_GT) - -#define TOK_DEC 0x80 /* -- */ -#define TOK_MID 0x81 /* inc/dec, to void constant */ -#define TOK_INC 0x82 /* ++ */ -#define TOK_UDIV 0x83 /* unsigned division */ -#define TOK_UMOD 0x84 /* unsigned modulo */ -#define TOK_PDIV 0x85 /* fast division with undefined rounding for pointers */ -#define TOK_UMULL 0x86 /* unsigned 32x32 -> 64 mul */ -#define TOK_ADDC1 0x87 /* add with carry generation */ -#define TOK_ADDC2 0x88 /* add with carry use */ -#define TOK_SUBC1 0x89 /* add with carry generation */ -#define TOK_SUBC2 0x8a /* add with carry use */ -#define TOK_SHL '<' /* shift left */ -#define TOK_SAR '>' /* signed shift right */ -#define TOK_SHR 0x8b /* unsigned shift right */ -#define TOK_NEG TOK_MID /* unary minus operation (for floats) */ - -#define TOK_ARROW 0xa0 /* -> */ -#define TOK_DOTS 0xa1 /* three dots */ -#define TOK_TWODOTS 0xa2 /* C++ token ? */ -#define TOK_TWOSHARPS 0xa3 /* ## preprocessing token */ -#define TOK_PLCHLDR 0xa4 /* placeholder token as defined in C99 */ -#define TOK_PPJOIN (TOK_TWOSHARPS | SYM_FIELD) /* A '##' in a macro to mean pasting */ -#define TOK_SOTYPE 0xa7 /* alias of '(' for parsing sizeof (type) */ - -/* assignment operators */ -#define TOK_A_ADD 0xb0 -#define TOK_A_SUB 0xb1 -#define TOK_A_MUL 0xb2 -#define TOK_A_DIV 0xb3 -#define TOK_A_MOD 0xb4 -#define TOK_A_AND 0xb5 -#define TOK_A_OR 0xb6 -#define TOK_A_XOR 0xb7 -#define TOK_A_SHL 0xb8 -#define TOK_A_SAR 0xb9 - -#define TOK_ASSIGN(t) (t >= TOK_A_ADD && t <= TOK_A_SAR) -#define TOK_ASSIGN_OP(t) ("+-*/%&|^<>"[t - TOK_A_ADD]) - -/* tokens that carry values (in additional token string space / tokc) --> */ -#define TOK_CCHAR 0xc0 /* char constant in tokc */ -#define TOK_LCHAR 0xc1 -#define TOK_CINT 0xc2 /* number in tokc */ -#define TOK_CUINT 0xc3 /* unsigned int constant */ -#define TOK_CLLONG 0xc4 /* long long constant */ -#define TOK_CULLONG 0xc5 /* unsigned long long constant */ -#define TOK_CLONG 0xc6 /* long constant */ -#define TOK_CULONG 0xc7 /* unsigned long constant */ -#define TOK_STR 0xc8 /* pointer to string in tokc */ -#define TOK_LSTR 0xc9 -#define TOK_CFLOAT 0xca /* float constant */ -#define TOK_CDOUBLE 0xcb /* double constant */ -#define TOK_CLDOUBLE 0xcc /* long double constant */ -#define TOK_PPNUM 0xcd /* preprocessor number */ -#define TOK_PPSTR 0xce /* preprocessor string */ -#define TOK_LINENUM 0xcf /* line number info */ - -#define TOK_HAS_VALUE(t) (t >= TOK_CCHAR && t <= TOK_LINENUM) - -#define TOK_EOF (-1) /* end of file */ -#define TOK_LINEFEED 10 /* line feed */ - -/* all identifiers and strings have token above that */ -#define TOK_IDENT 256 - -enum tcc_token { - TOK_LAST = TOK_IDENT - 1 -#define DEF(id, str) ,id -#include "tcctok.h" -#undef DEF -}; - -/* keywords: tok >= TOK_IDENT && tok < TOK_UIDENT */ -#define TOK_UIDENT TOK_DEFINE - /* ------------ libtcc.c ------------ */ -ST_DATA struct TCCState *tcc_state; -ST_DATA void** stk_data; -ST_DATA int nb_stk_data; +extern struct TCCState *tcc_state; +extern void** stk_data; +extern int nb_stk_data; /* public functions currently used by the tcc main function */ PUB_FUNC char *tcc_basename(const char *name); @@ -997,32 +796,26 @@ PUB_FUNC void *tcc_realloc_debug(void *ptr, unsigned long size, const char *file PUB_FUNC char *tcc_strdup_debug(const char *str, const char *file, int line); #endif -ST_FUNC void libc_free(void *ptr); -#define free(p) use_tcc_free(p) -#define malloc(s) use_tcc_malloc(s) -#define realloc(p, s) use_tcc_realloc(p, s) -#undef strdup -#define strdup(s) use_tcc_strdup(s) -PUB_FUNC int _tcc_error_noabort(const char *fmt, ...) PRINTF_LIKE(1,2); -PUB_FUNC NORETURN void _tcc_error(const char *fmt, ...) PRINTF_LIKE(1,2); -PUB_FUNC void _tcc_warning(const char *fmt, ...) PRINTF_LIKE(1,2); +PUB_FUNC int _tcc_error_noabort(const char *fmt, ...) __attribute__ ((format (printf, (1), (2)))); +PUB_FUNC __attribute__((noreturn)) void _tcc_error(const char *fmt, ...) __attribute__ ((format (printf, (1), (2)))); +PUB_FUNC void _tcc_warning(const char *fmt, ...) __attribute__ ((format (printf, (1), (2)))); #define tcc_internal_error(msg) \ tcc_error("internal compiler error in %s:%d: %s", __FUNCTION__,__LINE__,msg) /* other utilities */ -ST_FUNC void dynarray_add(void *ptab, int *nb_ptr, void *data); -ST_FUNC void dynarray_reset(void *pp, int *n); -ST_INLN void cstr_ccat(CString *cstr, int ch); -ST_FUNC void cstr_cat(CString *cstr, const char *str, int len); -ST_FUNC void cstr_wccat(CString *cstr, int ch); -ST_FUNC void cstr_new(CString *cstr); -ST_FUNC void cstr_free(CString *cstr); -ST_FUNC int cstr_printf(CString *cs, const char *fmt, ...) PRINTF_LIKE(2,3); -ST_FUNC int cstr_vprintf(CString *cstr, const char *fmt, va_list ap); -ST_FUNC void cstr_reset(CString *cstr); -ST_FUNC void tcc_open_bf(TCCState *s1, const char *filename, int initlen); -ST_FUNC int tcc_open(TCCState *s1, const char *filename); -ST_FUNC void tcc_close(void); +void dynarray_add(void *ptab, int *nb_ptr, void *data); +void dynarray_reset(void *pp, int *n); +void cstr_ccat(CString *cstr, int ch); +void cstr_cat(CString *cstr, const char *str, int len); +void cstr_wccat(CString *cstr, int ch); +void cstr_new(CString *cstr); +void cstr_free(CString *cstr); +int cstr_printf(CString *cs, const char *fmt, ...) __attribute__ ((format (printf, (2), (3)))); +int cstr_vprintf(CString *cstr, const char *fmt, va_list ap); +void cstr_reset(CString *cstr); +void tcc_open_bf(TCCState *s1, const char *filename, int initlen); +int tcc_open(TCCState *s1, const char *filename); +void tcc_close(void); /* mark a memory pointer on stack for cleanup after errors */ #define stk_push(p) dynarray_add(&stk_data, &nb_stk_data, p) @@ -1031,10 +824,9 @@ ST_FUNC void tcc_close(void); #define cstr_new_s(cstr) (cstr_new(cstr), stk_push(&(cstr)->data)) #define cstr_free_s(cstr) (cstr_free(cstr), stk_pop()) -ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags); +int tcc_add_file_internal(TCCState *s1, const char *filename, int flags); /* flags: */ #define AFF_PRINT_ERROR 0x10 /* print error if file not found */ -#define AFF_REFERENCED_DLL 0x20 /* load a referenced dll from another dll */ #define AFF_TYPE_BIN 0x40 /* file to add is binary */ #define AFF_WHOLE_ARCHIVE 0x80 /* load all objects from archive */ /* s->filetype: */ @@ -1054,22 +846,19 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags) #define FILE_NOT_FOUND -2 #ifndef ELF_OBJ_ONLY -ST_FUNC int tcc_add_crt(TCCState *s, const char *filename); +int tcc_add_crt(TCCState *s, const char *filename); #endif -ST_FUNC int tcc_add_dll(TCCState *s, const char *filename, int flags); -ST_FUNC int tcc_add_support(TCCState *s1, const char *filename); +int tcc_add_support(TCCState *s1, const char *filename); -ST_FUNC void tcc_add_pragma_libs(TCCState *s1); +void tcc_add_pragma_libs(TCCState *s1); PUB_FUNC int tcc_add_library_err(TCCState *s, const char *f); PUB_FUNC void tcc_print_stats(TCCState *s, unsigned total_time); PUB_FUNC int tcc_parse_args(TCCState *s, int *argc, char ***argv, int optind); #ifdef _WIN32 -ST_FUNC char *normalize_slashes(char *path); +char *normalize_slashes(char *path); #endif -ST_FUNC DLLReference *tcc_add_dllref(TCCState *s1, const char *dllname, int level); -ST_FUNC char *tcc_load_text(int fd); /* for #pragma once */ -ST_FUNC int normalized_PATHCMP(const char *f1, const char *f2); +int normalized_PATHCMP(const char *f1, const char *f2); /* tcc_parse_args return codes: */ #define OPT_HELP 1 @@ -1078,23 +867,21 @@ ST_FUNC int normalized_PATHCMP(const char *f1, const char *f2); #define OPT_PRINT_DIRS 4 #define OPT_AR 5 #define OPT_IMPDEF 6 -#define OPT_M32 32 -#define OPT_M64 64 /* ------------ tccpp.c ------------ */ -ST_DATA struct BufferedFile *file; -ST_DATA int tok; -ST_DATA CValue tokc; -ST_DATA const int *macro_ptr; -ST_DATA int parse_flags; -ST_DATA int tok_flags; -ST_DATA CString tokcstr; /* current parsed string, if any */ +extern struct BufferedFile *file; +extern int tok; +extern CValue tokc; +extern const int *macro_ptr; +extern int parse_flags; +extern int tok_flags; +extern CString tokcstr; /* current parsed string, if any */ /* display benchmark infos */ -ST_DATA int tok_ident; -ST_DATA TokenSym **table_ident; -ST_DATA int pp_expr; +extern int tok_ident; +extern TokenSym **table_ident; +extern int pp_expr; #define TOK_FLAG_BOL 0x0001 /* beginning of line before */ #define TOK_FLAG_BOF 0x0002 /* beginning of file before */ @@ -1122,36 +909,36 @@ enum line_macro_output_format { LINE_MACRO_OUTPUT_FORMAT_P10 = 11 }; -ST_FUNC TokenSym *tok_alloc(const char *str, int len); -ST_FUNC int tok_alloc_const(const char *str); -ST_FUNC const char *get_tok_str(int v, CValue *cv); -ST_FUNC void begin_macro(TokenString *str, int alloc); -ST_FUNC void end_macro(void); -ST_FUNC int set_idnum(int c, int val); -ST_INLN void tok_str_new(TokenString *s); -ST_FUNC TokenString *tok_str_alloc(void); -ST_FUNC void tok_str_free(TokenString *s); -ST_FUNC void tok_str_free_str(int *str); -ST_FUNC void tok_str_add(TokenString *s, int t); -ST_FUNC void tok_str_add_tok(TokenString *s); -ST_INLN void define_push(int v, int macro_type, int *str, Sym *first_arg); -ST_FUNC void define_undef(Sym *s); -ST_INLN Sym *define_find(int v); -ST_FUNC void free_defines(Sym *b); -ST_FUNC void parse_define(void); -ST_FUNC void skip_to_eol(int warn); -ST_FUNC void preprocess(int is_bof); -ST_FUNC void next(void); -ST_INLN void unget_tok(int last_tok); -ST_FUNC void preprocess_start(TCCState *s1, int filetype); -ST_FUNC void preprocess_end(TCCState *s1); -ST_FUNC void tccpp_new(TCCState *s); -ST_FUNC void tccpp_delete(TCCState *s); -ST_FUNC void tccpp_putfile(const char *filename); -ST_FUNC int tcc_preprocess(TCCState *s1); -ST_FUNC void skip(int c); -ST_FUNC NORETURN void expect(const char *msg); -ST_FUNC void pp_error(CString *cs); +TokenSym *tok_alloc(const char *str, int len); +int tok_alloc_const(const char *str); +const char *get_tok_str(int v, CValue *cv); +void begin_macro(TokenString *str, int alloc); +void end_macro(void); +int set_idnum(int c, int val); +void tok_str_new(TokenString *s); +TokenString *tok_str_alloc(void); +void tok_str_free(TokenString *s); +void tok_str_free_str(int *str); +void tok_str_add(TokenString *s, int t); +void tok_str_add_tok(TokenString *s); +void define_push(int v, int macro_type, int *str, Sym *first_arg); +void define_undef(Sym *s); +Sym *define_find(int v); +void free_defines(Sym *b); +void parse_define(void); +void skip_to_eol(int warn); +void preprocess(int is_bof); +void next(void); +void unget_tok(int last_tok); +void preprocess_start(TCCState *s1, int filetype); +void preprocess_end(TCCState *s1); +void tccpp_new(TCCState *s); +void tccpp_delete(TCCState *s); +void tccpp_putfile(const char *filename); +int tcc_preprocess(TCCState *s1); +void skip(int c); +__attribute__((noreturn)) void expect(const char *msg); +void pp_error(CString *cs); /* space excluding newline */ @@ -1175,89 +962,89 @@ static inline int toup(int c) { #define SYM_POOL_NB (8192 / sizeof(Sym)) -ST_DATA Sym *global_stack; -ST_DATA Sym *local_stack; -ST_DATA Sym *local_label_stack; -ST_DATA Sym *global_label_stack; -ST_DATA Sym *define_stack; -ST_DATA CType int_type, func_old_type, char_pointer_type; -ST_DATA SValue *vtop; -ST_DATA int rsym, anon_sym, ind, loc; -ST_DATA char debug_modes; +extern Sym *global_stack; +extern Sym *local_stack; +extern Sym *local_label_stack; +extern Sym *global_label_stack; +extern Sym *define_stack; +extern CType int_type, func_old_type, char_pointer_type; +extern SValue *vtop; +extern int rsym, anon_sym, ind, loc; +extern char debug_modes; -ST_DATA int nocode_wanted; /* true if no code generation wanted for an expression */ -ST_DATA int global_expr; /* true if compound literals must be allocated globally (used during initializers parsing */ -ST_DATA CType func_vt; /* current function return type (used by return instruction) */ -ST_DATA int func_var; /* true if current function is variadic */ -ST_DATA int func_vc; -ST_DATA int func_ind; -ST_DATA const char *funcname; +extern int nocode_wanted; /* true if no code generation wanted for an expression */ +extern int global_expr; /* true if compound literals must be allocated globally (used during initializers parsing */ +extern CType func_vt; /* current function return type (used by return instruction) */ +extern int func_var; /* true if current function is variadic */ +extern int func_vc; +extern int func_ind; +extern const char *funcname; -ST_FUNC void tccgen_init(TCCState *s1); -ST_FUNC int tccgen_compile(TCCState *s1); -ST_FUNC void tccgen_finish(TCCState *s1); -ST_FUNC void check_vstack(void); +void tccgen_init(TCCState *s1); +int tccgen_compile(TCCState *s1); +void tccgen_finish(TCCState *s1); +void check_vstack(void); -ST_INLN int is_float(int t); -ST_FUNC int ieee_finite(double d); -ST_FUNC int exact_log2p1(int i); -ST_FUNC void test_lvalue(void); +int is_float(int t); +int ieee_finite(double d); +int exact_log2p1(int i); +void test_lvalue(void); -ST_FUNC ElfSym *elfsym(Sym *); -ST_FUNC void update_storage(Sym *sym); -ST_FUNC void put_extern_sym2(Sym *sym, int sh_num, addr_t value, unsigned long size, int can_add_underscore); -ST_FUNC void put_extern_sym(Sym *sym, Section *section, addr_t value, unsigned long size); +ElfSym *elfsym(Sym *); +void update_storage(Sym *sym); +void put_extern_sym2(Sym *sym, int sh_num, addr_t value, unsigned long size, int can_add_underscore); +void put_extern_sym(Sym *sym, Section *section, addr_t value, unsigned long size); #if PTR_SIZE == 4 -ST_FUNC void greloc(Section *s, Sym *sym, unsigned long offset, int type); +void greloc(Section *s, Sym *sym, unsigned long offset, int type); #endif -ST_FUNC void greloca(Section *s, Sym *sym, unsigned long offset, int type, addr_t addend); +void greloca(Section *s, Sym *sym, unsigned long offset, int type, addr_t addend); -ST_INLN void sym_free(Sym *sym); -ST_FUNC Sym *sym_push(int v, CType *type, int r, int c); -ST_FUNC void sym_pop(Sym **ptop, Sym *b, int keep); -ST_FUNC Sym *sym_push2(Sym **ps, int v, int t, int c); -ST_FUNC Sym *sym_find2(Sym *s, int v); -ST_INLN Sym *sym_find(int v); -ST_FUNC Sym *label_find(int v); -ST_FUNC Sym *label_push(Sym **ptop, int v, int flags); -ST_FUNC void label_pop(Sym **ptop, Sym *slast, int keep); -ST_INLN Sym *struct_find(int v); +void sym_free(Sym *sym); +Sym *sym_push(int v, CType *type, int r, int c); +void sym_pop(Sym **ptop, Sym *b, int keep); +Sym *sym_push2(Sym **ps, int v, int t, int c); +Sym *sym_find2(Sym *s, int v); +Sym *sym_find(int v); +Sym *label_find(int v); +Sym *label_push(Sym **ptop, int v, int flags); +void label_pop(Sym **ptop, Sym *slast, int keep); +Sym *struct_find(int v); -ST_FUNC Sym *global_identifier_push(int v, int t, int c); -ST_FUNC Sym *external_global_sym(int v, CType *type); -ST_FUNC Sym *external_helper_sym(int v); -ST_FUNC void vpush_helper_func(int v); -ST_FUNC void vset(CType *type, int r, int v); -ST_FUNC void vset_VT_CMP(int op); -ST_FUNC void vpushi(int v); -ST_FUNC void vpushv(SValue *v); -ST_FUNC void vpushsym(CType *type, Sym *sym); -ST_FUNC void vswap(void); -ST_FUNC void vrott(int n); -ST_FUNC void vrotb(int n); -ST_FUNC void vrev(int n); -ST_FUNC void vpop(void); +Sym *global_identifier_push(int v, int t, int c); +Sym *external_global_sym(int v, CType *type); +Sym *external_helper_sym(int v); +void vpush_helper_func(int v); +void vset(CType *type, int r, int v); +void vset_VT_CMP(int op); +void vpushi(int v); +void vpushv(SValue *v); +void vpushsym(CType *type, Sym *sym); +void vswap(void); +void vrott(int n); +void vrotb(int n); +void vrev(int n); +void vpop(void); #if PTR_SIZE == 4 -ST_FUNC void lexpand(void); +void lexpand(void); #endif -ST_FUNC void save_reg(int r); -ST_FUNC void save_reg_upstack(int r, int n); -ST_FUNC int get_reg(int rc); -ST_FUNC void save_regs(int n); -ST_FUNC void gaddrof(void); -ST_FUNC int gv(int rc); -ST_FUNC void gv2(int rc1, int rc2); -ST_FUNC void gen_op(int op); -ST_FUNC int type_size(CType *type, int *a); -ST_FUNC void mk_pointer(CType *type); -ST_FUNC void vstore(void); -ST_FUNC void inc(int post, int c); -ST_FUNC CString* parse_mult_str(const char *msg); -ST_FUNC CString* parse_asm_str(void); -ST_FUNC void indir(void); -ST_FUNC void unary(void); -ST_FUNC void gexpr(void); -ST_FUNC int expr_const(void); +void save_reg(int r); +void save_reg_upstack(int r, int n); +int get_reg(int rc); +void save_regs(int n); +void gaddrof(void); +int gv(int rc); +void gv2(int rc1, int rc2); +void gen_op(int op); +int type_size(CType *type, int *a); +void mk_pointer(CType *type); +void vstore(void); +void inc(int post, int c); +CString* parse_mult_str(const char *msg); +CString* parse_asm_str(void); +void indir(void); +void unary(void); +void gexpr(void); +int expr_const(void); /* ------------ tccelf.c ------------ */ @@ -1267,50 +1054,42 @@ ST_FUNC int expr_const(void); #define ARMAG "!\n" /* For COFF and a.out archives */ -typedef struct { - unsigned int n_strx; /* index into string table of name */ - unsigned char n_type; /* type of symbol */ - unsigned char n_other; /* misc info (usually empty) */ - unsigned short n_desc; /* description field */ - unsigned int n_value; /* value of symbol */ -} Stab_Sym; +void tccelf_new(TCCState *s); +void tccelf_delete(TCCState *s); +void tccelf_begin_file(TCCState *s1); +void tccelf_end_file(TCCState *s1); +Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags); +void section_realloc(Section *sec, unsigned long new_size); +size_t section_add(Section *sec, addr_t size, int align); +void *section_ptr_add(Section *sec, addr_t size); +Section *find_section(TCCState *s1, const char *name); +void free_section(Section *s); +Section *new_symtab(TCCState *s1, const char *symtab_name, int sh_type, int sh_flags, const char *strtab_name, const char *hash_name, int hash_sh_flags); +void init_symtab(Section *s); -ST_FUNC void tccelf_new(TCCState *s); -ST_FUNC void tccelf_delete(TCCState *s); -ST_FUNC void tccelf_begin_file(TCCState *s1); -ST_FUNC void tccelf_end_file(TCCState *s1); -ST_FUNC Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags); -ST_FUNC void section_realloc(Section *sec, unsigned long new_size); -ST_FUNC size_t section_add(Section *sec, addr_t size, int align); -ST_FUNC void *section_ptr_add(Section *sec, addr_t size); -ST_FUNC Section *find_section(TCCState *s1, const char *name); -ST_FUNC void free_section(Section *s); -ST_FUNC Section *new_symtab(TCCState *s1, const char *symtab_name, int sh_type, int sh_flags, const char *strtab_name, const char *hash_name, int hash_sh_flags); -ST_FUNC void init_symtab(Section *s); +int put_elf_str(Section *s, const char *sym); +int put_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name); +int set_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name); +int find_elf_sym(Section *s, const char *name); +void put_elf_reloc(Section *symtab, Section *s, unsigned long offset, int type, int symbol); +void put_elf_reloca(Section *symtab, Section *s, unsigned long offset, int type, int symbol, addr_t addend); -ST_FUNC int put_elf_str(Section *s, const char *sym); -ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name); -ST_FUNC int set_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name); -ST_FUNC int find_elf_sym(Section *s, const char *name); -ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset, int type, int symbol); -ST_FUNC void put_elf_reloca(Section *symtab, Section *s, unsigned long offset, int type, int symbol, addr_t addend); +void resolve_common_syms(TCCState *s1); +void relocate_syms(TCCState *s1, Section *symtab, int do_resolve); +void relocate_sections(TCCState *s1); -ST_FUNC void resolve_common_syms(TCCState *s1); -ST_FUNC void relocate_syms(TCCState *s1, Section *symtab, int do_resolve); -ST_FUNC void relocate_sections(TCCState *s1); +ssize_t full_read(int fd, void *buf, size_t count); +void *load_data(int fd, unsigned long file_offset, unsigned long size); +int tcc_object_type(int fd, ElfW(Ehdr) *h); +int tcc_load_object_file(TCCState *s1, int fd, unsigned long file_offset); +int tcc_load_archive(TCCState *s1, int fd, int alacarte); +void add_array(TCCState *s1, const char *sec, int c); -ST_FUNC ssize_t full_read(int fd, void *buf, size_t count); -ST_FUNC void *load_data(int fd, unsigned long file_offset, unsigned long size); -ST_FUNC int tcc_object_type(int fd, ElfW(Ehdr) *h); -ST_FUNC int tcc_load_object_file(TCCState *s1, int fd, unsigned long file_offset); -ST_FUNC int tcc_load_archive(TCCState *s1, int fd, int alacarte); -ST_FUNC void add_array(TCCState *s1, const char *sec, int c); - -ST_FUNC struct sym_attr *get_sym_attr(TCCState *s1, int index, int alloc); -ST_FUNC addr_t get_sym_addr(TCCState *s, const char *name, int err, int forc); -ST_FUNC void list_elf_symbols(TCCState *s, void *ctx, +struct sym_attr *get_sym_attr(TCCState *s1, int index, int alloc); +addr_t get_sym_addr(TCCState *s, const char *name, int err, int forc); +void list_elf_symbols(TCCState *s, void *ctx, void (*symbol_cb)(void *ctx, const char *name, const void *val)); -ST_FUNC int set_global_sym(TCCState *s1, const char *name, Section *sec, addr_t offs); +int set_global_sym(TCCState *s1, const char *name, Section *sec, addr_t offs); /* Browse each elem of type in section starting at elem using variable */ @@ -1319,13 +1098,12 @@ ST_FUNC int set_global_sym(TCCState *s1, const char *name, Section *sec, addr_t elem < (type *) (sec->data + sec->data_offset); elem++) #ifndef ELF_OBJ_ONLY -ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level); -ST_FUNC int tcc_load_ldscript(TCCState *s1, int fd); -ST_FUNC void tccelf_add_crtbegin(TCCState *s1); -ST_FUNC void tccelf_add_crtend(TCCState *s1); +int tcc_load_ldscript(TCCState *s1, int fd); +void tccelf_add_crtbegin(TCCState *s1); +void tccelf_add_crtend(TCCState *s1); #endif #ifndef TCC_TARGET_PE -ST_FUNC void tcc_add_runtime(TCCState *s1); +void tcc_add_runtime(TCCState *s1); #endif int coff_load_file(TCCState *s1, int fd, const char *fname); @@ -1333,8 +1111,8 @@ int coff_load_file(TCCState *s1, int fd, const char *fname); /* ------------ xxx-link.c ------------ */ #if !defined ELF_OBJ_ONLY -ST_FUNC int code_reloc (int reloc_type); -ST_FUNC int gotplt_entry_type (int reloc_type); +int code_reloc (int reloc_type); +int gotplt_entry_type (int reloc_type); /* Whether to generate a GOT/PLT entry and when. NO_GOTPLT_ENTRY is first so that unknown relocation don't create a GOT or PLT entry */ enum gotplt_entry { @@ -1345,42 +1123,42 @@ enum gotplt_entry { }; #define NEED_RELOC_TYPE -ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr); -ST_FUNC void relocate_plt(TCCState *s1); -ST_FUNC void build_got_entries(TCCState *s1, int got_sym); /* in tccelf.c */ +unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr); +void relocate_plt(TCCState *s1); +void build_got_entries(TCCState *s1, int got_sym); /* in tccelf.c */ #define NEED_BUILD_GOT #endif -ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val); +void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val); /* ------------ xxx-gen.c ------------ */ -ST_DATA const char * const target_machine_defs; -ST_DATA const int reg_classes[NB_REGS]; +extern const char * const target_machine_defs; +extern const int reg_classes[NB_REGS]; -ST_FUNC void gsym_addr(int t, int a); -ST_FUNC void gsym(int t); -ST_FUNC void load(int r, SValue *sv); -ST_FUNC void store(int r, SValue *v); -ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *align, int *regsize); -ST_FUNC void gfunc_call(int nb_args); -ST_FUNC void gfunc_prolog(Sym *func_sym); -ST_FUNC void gfunc_epilog(void); -ST_FUNC void gen_fill_nops(int); -ST_FUNC int gjmp(int t); -ST_FUNC void gjmp_addr(int a); -ST_FUNC int gjmp_cond(int op, int t); -ST_FUNC int gjmp_append(int n, int t); -ST_FUNC void gen_opi(int op); -ST_FUNC void gen_opf(int op); -ST_FUNC void gen_cvt_ftoi(int t); -ST_FUNC void gen_cvt_itof(int t); -ST_FUNC void gen_cvt_ftof(int t); -ST_FUNC void ggoto(void); -ST_FUNC void o(unsigned int c); -ST_FUNC void gen_vla_sp_save(int addr); -ST_FUNC void gen_vla_sp_restore(int addr); -ST_FUNC void gen_vla_alloc(CType *type, int align); +void gsym_addr(int t, int a); +void gsym(int t); +void load(int r, SValue *sv); +void store(int r, SValue *v); +int gfunc_sret(CType *vt, int variadic, CType *ret, int *align, int *regsize); +void gfunc_call(int nb_args); +void gfunc_prolog(Sym *func_sym); +void gfunc_epilog(void); +void gen_fill_nops(int); +int gjmp(int t); +void gjmp_addr(int a); +int gjmp_cond(int op, int t); +int gjmp_append(int n, int t); +void gen_opi(int op); +void gen_opf(int op); +void gen_cvt_ftoi(int t); +void gen_cvt_itof(void); +void gen_cvt_ftof(void); +void ggoto(void); +void o(unsigned int c); +void gen_vla_sp_save(int addr); +void gen_vla_sp_restore(int addr); +void gen_vla_alloc(CType *type, int align); static inline uint16_t read16le(unsigned char *p) { return p[0] | (uint16_t)p[1] << 8; @@ -1406,120 +1184,38 @@ static inline void write64le(unsigned char *p, uint64_t x) { static inline void add64le(unsigned char *p, int64_t x) { write64le(p, read64le(p) + x); } -#define DWARF_MAX_128 ((8 * sizeof (int64_t) + 6) / 7) -#define dwarf_read_1(ln,end) \ - ((ln) < (end) ? *(ln)++ : 0) -#define dwarf_read_2(ln,end) \ - ((ln) + 1 < (end) ? (ln) += 2, read16le((ln) - 2) : 0) -#define dwarf_read_4(ln,end) \ - ((ln) + 3 < (end) ? (ln) += 4, read32le((ln) - 4) : 0) -#define dwarf_read_8(ln,end) \ - ((ln) + 7 < (end) ? (ln) += 8, read64le((ln) - 8) : 0) -static inline uint64_t -dwarf_read_uleb128(unsigned char **ln, unsigned char *end) -{ - unsigned char *cp = *ln; - uint64_t retval = 0; - int i; - - for (i = 0; i < DWARF_MAX_128; i++) { - uint64_t byte = dwarf_read_1(cp, end); - - retval |= (byte & 0x7f) << (i * 7); - if ((byte & 0x80) == 0) - break; - } - *ln = cp; - return retval; -} -static inline int64_t -dwarf_read_sleb128(unsigned char **ln, unsigned char *end) -{ - unsigned char *cp = *ln; - int64_t retval = 0; - int i; - - for (i = 0; i < DWARF_MAX_128; i++) { - uint64_t byte = dwarf_read_1(cp, end); - - retval |= (byte & 0x7f) << (i * 7); - if ((byte & 0x80) == 0) { - if ((byte & 0x40) && (i + 1) * 7 < 64) - retval |= -1LL << ((i + 1) * 7); - break; - } - } - *ln = cp; - return retval; -} - /* ------------ i386-gen.c ------------ */ -ST_FUNC void g(int c); -ST_FUNC void gen_le16(int c); -ST_FUNC void gen_le32(int c); +void g(int c); +void gen_le16(int c); +void gen_le32(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_cvt_csti(int t); -ST_FUNC void gen_increment_tcov (SValue *sv); - - - - -/* ------------ tcccoff.c ------------ */ -#ifdef TCC_TARGET_COFF -ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f); -ST_FUNC int tcc_load_coff(TCCState * s1, int fd); -#endif +void gen_addr32(int r, Sym *sym, int c); +void gen_addrpc32(int r, Sym *sym, int c); +void gen_cvt_csti(int t); /* ------------ tccasm.c ------------ */ -ST_FUNC void asm_instr(void); -ST_FUNC void asm_global_instr(void); -ST_FUNC int tcc_assemble(TCCState *s1, int do_preprocess); -#ifdef CONFIG_TCC_ASM -ST_FUNC int find_constraint(ASMOperand *operands, int nb_operands, const char *name, const char **pp); -ST_FUNC Sym* get_asm_sym(int name, Sym *csym); -ST_FUNC void asm_expr(TCCState *s1, ExprValue *pe); -ST_FUNC int asm_int_expr(TCCState *s1); +void asm_instr(void); +void asm_global_instr(void); +int tcc_assemble(TCCState *s1, int do_preprocess); +int find_constraint(ASMOperand *operands, int nb_operands, const char *name, const char **pp); +Sym* get_asm_sym(int name, Sym *csym); +void asm_expr(TCCState *s1, ExprValue *pe); +int asm_int_expr(TCCState *s1); /* ------------ i386-asm.c ------------ */ -ST_FUNC void gen_expr32(ExprValue *pe); -ST_FUNC void asm_opcode(TCCState *s1, int opcode); -ST_FUNC int asm_parse_regvar(int t); -ST_FUNC void asm_compute_constraints(ASMOperand *operands, int nb_operands, int nb_outputs, const uint8_t *clobber_regs, int *pout_reg); -ST_FUNC void subst_asm_operand(CString *add_str, SValue *sv, int modifier); -ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands, int nb_outputs, int is_output, uint8_t *clobber_regs, int out_reg); -ST_FUNC void asm_clobber(uint8_t *clobber_regs, const char *str); -#endif +void gen_expr32(ExprValue *pe); +void asm_opcode(TCCState *s1, int opcode); +int asm_parse_regvar(int t); +void asm_compute_constraints(ASMOperand *operands, int nb_operands, int nb_outputs, const uint8_t *clobber_regs, int *pout_reg); +void subst_asm_operand(CString *add_str, SValue *sv, int modifier); +void asm_gen_code(ASMOperand *operands, int nb_operands, int nb_outputs, int is_output, uint8_t *clobber_regs, int out_reg); +void asm_clobber(uint8_t *clobber_regs, const char *str); #define ST_ASM_SET 0x04 /* ------------ tccdbg.c ------------ */ - -#define stab_section s1->stab_section -#define stabstr_section stab_section->link -#define tcov_section s1->tcov_section -#define eh_frame_section s1->eh_frame_section #define eh_frame_hdr_section s1->eh_frame_hdr_section -#define dwarf_info_section s1->dwarf_info_section -#define dwarf_abbrev_section s1->dwarf_abbrev_section -#define dwarf_line_section s1->dwarf_line_section -#define dwarf_aranges_section s1->dwarf_aranges_section -#define dwarf_str_section s1->dwarf_str_section -#define dwarf_line_str_section s1->dwarf_line_str_section - - -/* default dwarf version for "-g". use 0 to emit stab debug infos */ -#ifndef CONFIG_DWARF_VERSION -# define CONFIG_DWARF_VERSION 0 -#endif - -#if defined TCC_TARGET_PE -# define R_DATA_32DW 'Z' /* fake code to avoid DLL relocs */ -#else -# define R_DATA_32DW R_DATA_32 -#endif /********************************************************/ #if CONFIG_TCC_SEMLOCK @@ -1546,6 +1242,7 @@ static inline void post_sem(TCCSem *p) { } #else #include +#include typedef struct { int init; sem_t sem; } TCCSem; static inline void wait_sem(TCCSem *p) { if (!p->init) @@ -1565,14 +1262,6 @@ static inline void post_sem(TCCSem *p) { #define POST_SEM(p) #endif -/********************************************************/ -#undef ST_DATA -#if ONE_SOURCE -#define ST_DATA static -#else -#define ST_DATA -#endif -/********************************************************/ #define text_section TCC_STATE_VAR(text_section) #define data_section TCC_STATE_VAR(data_section) diff --git a/libtcc/coff.h b/libtcc/include/tcc/coff.h similarity index 100% rename from libtcc/coff.h rename to libtcc/include/tcc/coff.h diff --git a/libtcc/elf.h b/libtcc/include/tcc/elf.h similarity index 100% rename from libtcc/elf.h rename to libtcc/include/tcc/elf.h diff --git a/libtcc/include/tcc/i386/gen.h b/libtcc/include/tcc/i386/gen.h new file mode 100644 index 00000000..436c8fc9 --- /dev/null +++ b/libtcc/include/tcc/i386/gen.h @@ -0,0 +1,60 @@ +#ifndef TCC_I386_GEN_H +# define TCC_I386_GEN_H 1 + +/* number of available registers */ +# define NB_REGS 5 +# define NB_ASM_REGS 8 + +/* a register can belong to several classes. The classes must be + sorted from more general to more precise (see gv2() code which does + assumptions on it). */ +# define RC_INT 0x0001 /* generic integer register */ +# define RC_FLOAT 0x0002 /* generic float register */ +# define RC_EAX 0x0004 +# define RC_EDX 0x0008 +# define RC_ECX 0x0010 +# define RC_EBX 0x0020 +# define RC_ST0 0x0040 + +# define RC_IRET RC_EAX /* function return: integer register */ +# define RC_IRE2 RC_EDX /* function return: second integer register */ +# define RC_FRET RC_ST0 /* function return: float register */ + +/* pretty names for the registers */ +enum { + TREG_EAX = 0, + TREG_ECX, + TREG_EDX, + TREG_EBX, + TREG_ST0, + TREG_ESP = 4 +}; + +/* return registers for function */ +# define REG_IRET TREG_EAX /* single word int return register */ +# define REG_IRE2 TREG_EDX /* second word return register (for long long) */ +# define REG_FRET TREG_ST0 /* float return register */ + +/* defined if function parameters must be evaluated in reverse order */ +# define INVERT_FUNC_PARAMS + +/* defined if structures are passed as pointers. Otherwise structures + are directly pushed on stack. */ +/* #define FUNC_STRUCT_PARAM_AS_PTR */ + +/* pointer size, in bytes */ +# define PTR_SIZE 4 + +/* long double size and alignment, in bytes */ +# define LDOUBLE_SIZE 12 +# define LDOUBLE_ALIGN 4 +/* maximum alignment (for aligned attribute support) */ +# define MAX_ALIGN 8 + +/* define if return values need to be extended explicitely + at caller side (for interfacing with non-TCC compilers) */ +# define PROMOTE_RET + + + +#endif /* !TCC_I386_GEN_H */ \ No newline at end of file diff --git a/libtcc/include/tcc/i386/link.h b/libtcc/include/tcc/i386/link.h new file mode 100644 index 00000000..1a6f7c30 --- /dev/null +++ b/libtcc/include/tcc/i386/link.h @@ -0,0 +1,20 @@ +#ifndef TCC_I386_LINK_H +# define TCC_I386_LINK_H 1 + +/* relocation type for 32 bit data relocation */ +# define R_DATA_32 R_386_32 +# define R_DATA_PTR R_386_32 +# define R_JMP_SLOT R_386_JMP_SLOT +# define R_GLOB_DAT R_386_GLOB_DAT +# define R_COPY R_386_COPY +# define R_RELATIVE R_386_RELATIVE + +# define R_NUM R_386_NUM + +# define ELF_START_ADDR 0x08048000 +# define ELF_PAGE_SIZE 0x1000 + +# define PCRELATIVE_DLLPLT 0 +# define RELOCATE_DLLPLT 1 + +#endif /* !TCC_I386_LINK_H */ \ No newline at end of file diff --git a/libtcc/object/archive.h b/libtcc/include/tcc/object/archive.h similarity index 100% rename from libtcc/object/archive.h rename to libtcc/include/tcc/object/archive.h diff --git a/libtcc/object/coff.h b/libtcc/include/tcc/object/coff.h similarity index 100% rename from libtcc/object/coff.h rename to libtcc/include/tcc/object/coff.h diff --git a/libtcc/include/tcc/option.h b/libtcc/include/tcc/option.h new file mode 100644 index 00000000..2abc2e9d --- /dev/null +++ b/libtcc/include/tcc/option.h @@ -0,0 +1,25 @@ +#ifndef LIBTCC_OPTION_H +# define LIBTCC_OPTION_H 1 + +# include + +# define TCC_OPTION_HAS_ARG 0x0001 +# define TCC_OPTION_NOSEP 0x0002 /** cannot have space before option and arg */ + +# define TCC_OPT_HELP 'h' +# define TCC_OPT_HELP_MORE 'm' +# define TCC_OPT_ARCHIVE 'a' +# define TCC_OPT_VERSION 'V' + +typedef struct TCCOption { + const char *name; + uint16_t index; + uint16_t flags; +} TCCOption; + +typedef struct TCCState TCCState; + +int tcc_parse_args(TCCState *s, int *argc, char ***argv, int optind); +void tcc_add_options(TCCOption *opts); + +#endif /* LIBTCC_OPTION_H */ \ No newline at end of file diff --git a/libtcc/libtcc.c b/libtcc/libtcc.c index a79ead7d..0baa0ca4 100644 --- a/libtcc/libtcc.c +++ b/libtcc/libtcc.c @@ -25,15 +25,15 @@ /* global variables */ /* XXX: get rid of this ASAP (or maybe not) */ -ST_DATA struct TCCState *tcc_state; +struct TCCState *tcc_state; TCC_SEM(static tcc_compile_sem); /* an array of pointers to memory to be free'd after errors */ -ST_DATA void** stk_data; -ST_DATA int nb_stk_data; +void** stk_data; +int nb_stk_data; /********************************************************/ #ifdef _WIN32 -ST_FUNC char *normalize_slashes(char *path) +char *normalize_slashes(char *path) { char *p; for (p = path; *p; ++p) @@ -99,7 +99,7 @@ PUB_FUNC char *tcc_fileextension (const char *name) return e ? e : strchr(b, 0); } -ST_FUNC char *tcc_load_text(int fd) +char *tcc_load_text(int fd) { int len = lseek(fd, 0, SEEK_END); char *buf = load_data(fd, 0, len + 1); @@ -111,10 +111,6 @@ ST_FUNC char *tcc_load_text(int fd) /********************************************************/ /* memory management */ -/* we'll need the actual versions for a minute */ -#undef free -#undef realloc - static void *default_reallocator(void *ptr, unsigned long size) { void *ptr1; @@ -132,14 +128,6 @@ static void *default_reallocator(void *ptr, unsigned long size) return ptr1; } -ST_FUNC void libc_free(void *ptr) -{ - free(ptr); -} - -#define free(p) use_tcc_free(p) -#define realloc(p, s) use_tcc_realloc(p, s) - /* global so that every tcc_alloc()/tcc_free() call doesn't need to be changed */ static void *(*reallocator)(void*, unsigned long) = default_reallocator; @@ -208,7 +196,7 @@ struct mem_debug_header { int line_num; char file_name[MEM_DEBUG_FILE_LEN + 1]; unsigned magic2; - ALIGNED(16) unsigned char magic3[4]; + __attribute__((aligned(16))) unsigned char magic3[4]; }; typedef struct mem_debug_header mem_debug_header_t; @@ -369,16 +357,16 @@ PUB_FUNC void tcc_memcheck(int d) #endif /* for #pragma once */ -ST_FUNC int normalized_PATHCMP(const char *f1, const char *f2) +int normalized_PATHCMP(const char *f1, const char *f2) { char *p1, *p2; int ret = 1; if (!!(p1 = realpath(f1, NULL))) { if (!!(p2 = realpath(f2, NULL))) { ret = PATHCMP(p1, p2); - libc_free(p2); /* realpath() requirement */ + free(p2); /* realpath() requirement */ } - libc_free(p1); + free(p1); } return ret; } @@ -386,7 +374,7 @@ ST_FUNC int normalized_PATHCMP(const char *f1, const char *f2) /********************************************************/ /* dynarrays */ -ST_FUNC void dynarray_add(void *ptab, int *nb_ptr, void *data) +void dynarray_add(void *ptab, int *nb_ptr, void *data) { int nb, nb_alloc; void **pp; @@ -406,7 +394,7 @@ ST_FUNC void dynarray_add(void *ptab, int *nb_ptr, void *data) *nb_ptr = nb; } -ST_FUNC void dynarray_reset(void *pp, int *n) +void dynarray_reset(void *pp, int *n) { void **p; for (p = *(void***)pp; *n; ++p, --*n) @@ -575,7 +563,7 @@ PUB_FUNC void _tcc_warning(const char *fmt, ...) /********************************************************/ /* I/O layer */ -ST_FUNC void tcc_open_bf(TCCState *s1, const char *filename, int initlen) +void tcc_open_bf(TCCState *s1, const char *filename, int initlen) { BufferedFile *bf; int buflen = initlen ? initlen : IO_BUF_SIZE; @@ -598,7 +586,7 @@ ST_FUNC void tcc_open_bf(TCCState *s1, const char *filename, int initlen) tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF; } -ST_FUNC void tcc_close(void) +void tcc_close(void) { TCCState *s1 = tcc_state; BufferedFile *bf = file; @@ -626,7 +614,7 @@ static int _tcc_open(TCCState *s1, const char *filename) return fd; } -ST_FUNC int tcc_open(TCCState *s1, const char *filename) +int tcc_open(TCCState *s1, const char *filename) { int fd = _tcc_open(s1, filename); if (fd < 0) @@ -755,8 +743,7 @@ void tcc_delete(TCCState *s1) dynarray_reset(&s1->include_paths, &s1->nb_include_paths); dynarray_reset(&s1->sysinclude_paths, &s1->nb_sysinclude_paths); - tcc_free(s1->tcc_lib_path); - tcc_free(s1->soname); + tcc_free(s1->tcc_lib_path);; tcc_free(s1->rpath); tcc_free(s1->elf_entryname); tcc_free(s1->init_symbol); @@ -771,8 +758,6 @@ void tcc_delete(TCCState *s1) cstr_free(&s1->cmdline_defs); cstr_free(&s1->cmdline_incl); cstr_free(&s1->linker_arg); - /* free loaded dlls array */ - dynarray_reset(&s1->loaded_dlls, &s1->nb_loaded_dlls); tcc_free(s1); #ifdef MEM_DEBUG tcc_memcheck(-1); @@ -823,35 +808,9 @@ int tcc_add_sysinclude_path(TCCState *s, const char *pathname) return 0; } -/* add/update a 'DLLReference', Just find if level == -1 */ -ST_FUNC DLLReference *tcc_add_dllref(TCCState *s1, const char *dllname, int level) -{ - DLLReference *ref = NULL; - int i; - for (i = 0; i < s1->nb_loaded_dlls; i++) - if (0 == strcmp(s1->loaded_dlls[i]->name, dllname)) { - ref = s1->loaded_dlls[i]; - break; - } - if (level == -1) - return ref; - if (ref) { - if (level < ref->level) - ref->level = level; - ref->found = 1; - return ref; - } - ref = tcc_mallocz(sizeof(DLLReference) + strlen(dllname)); - strcpy(ref->name, dllname); - dynarray_add(&s1->loaded_dlls, &s1->nb_loaded_dlls, ref); - ref->level = level; - ref->index = s1->nb_loaded_dlls; - return ref; -} - static int guess_filetype(const char *filename); -ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags) +int tcc_add_file_internal(TCCState *s1, const char *filename, int flags) { int fd, ret = -1; @@ -893,12 +852,6 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags) ret = coff_load_file(s1, fd, filename); break; - case AFF_BINTYPE_DYN: - if (s1->output_type == TCC_OUTPUT_MEMORY) { - } else - ret = tcc_load_dll(s1, fd, filename, (flags & AFF_REFERENCED_DLL) != 0); - break; - default: /* as GNU ld, consider it is an ld script if not recognized */ ret = tcc_load_ldscript(s1, fd); @@ -970,14 +923,14 @@ static int tcc_add_library_internal(TCCState *s1, const char *fmt, } /* find and load a dll. Return non zero if not found */ -ST_FUNC int tcc_add_dll(TCCState *s, const char *filename, int flags) +int tcc_add_dll(TCCState *s, const char *filename, int flags) { return tcc_add_library_internal(s, "%s/%s", filename, flags, s->library_paths, s->nb_library_paths); } /* find [cross-]libtcc1.a and tcc helper objects in library path */ -ST_FUNC int tcc_add_support(TCCState *s1, const char *filename) +int tcc_add_support(TCCState *s1, const char *filename) { char buf[100]; if (CONFIG_TCC_CROSSPREFIX[0]) @@ -985,13 +938,11 @@ ST_FUNC int tcc_add_support(TCCState *s1, const char *filename) return tcc_add_dll(s1, filename, AFF_PRINT_ERROR); } -#if !defined TCC_TARGET_PE -ST_FUNC int tcc_add_crt(TCCState *s1, const char *filename) +int tcc_add_crt(TCCState *s1, const char *filename) { return tcc_add_library_internal(s1, "%s/%s", filename, AFF_PRINT_ERROR, s1->crt_paths, s1->nb_crt_paths); } -#endif /* the library name is the same as the argument of the '-l' option */ int tcc_add_library(TCCState *s, const char *libraryname) @@ -1010,7 +961,7 @@ int tcc_add_library(TCCState *s, const char *libraryname) } /* handle #pragma comment(lib,) */ -ST_FUNC void tcc_add_pragma_libs(TCCState *s1) +void tcc_add_pragma_libs(TCCState *s1) { int i; for (i = 0; i < s1->nb_pragma_libs; i++) @@ -1184,20 +1135,12 @@ static int tcc_set_linker(TCCState *s, const char *option) ignoring = 1; } else if (link_option(option, "O", &p)) { ignoring = 1; - } else if (link_option(option, "export-all-symbols", &p)) { - s->rdynamic = 1; - } else if (link_option(option, "export-dynamic", &p)) { - s->rdynamic = 1; } else if (link_option(option, "rpath=", &p)) { copy_linker_arg(&s->rpath, p, ':'); } else if (link_option(option, "enable-new-dtags", &p)) { s->enable_new_dtags = 1; } else if (link_option(option, "section-alignment=", &p)) { s->section_align = strtoul(p, &end, 16); - } else if (link_option(option, "soname=", &p)) { - copy_linker_arg(&s->soname, p, 0); - } else if (link_option(option, "install_name=", &p)) { - copy_linker_arg(&s->soname, p, 0); } else if (ret = link_option(option, "?whole-archive", &p), ret) { if (ret > 0) s->filetype |= AFF_WHOLE_ARCHIVE; @@ -1308,10 +1251,7 @@ static const TCCOption tcc_options[] = { { "dumpmachine", TCC_OPTION_dumpmachine, 0}, { "dumpversion", TCC_OPTION_dumpversion, 0}, { "d", TCC_OPTION_d, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, - { "static", TCC_OPTION_static, 0 }, { "std", TCC_OPTION_std, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, - { "shared", TCC_OPTION_shared, 0 }, - { "soname", TCC_OPTION_soname, TCC_OPTION_HAS_ARG }, { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG }, { "pthread", TCC_OPTION_pthread, 0}, { "rdynamic", TCC_OPTION_rdynamic, 0 }, @@ -1346,6 +1286,9 @@ static const TCCOption tcc_options[] = { { "pipe", 0, 0 }, { "s", 0, 0 }, { "traditional", 0, 0 }, + { "static", 0, 0}, + { "shared", 0, 0}, + { "soname", 0, 0}, { NULL, 0, 0 }, }; @@ -1591,21 +1534,13 @@ dorun: s->dflag = 3; else if (*optarg == 'M') s->dflag = 7; - else if (isnum(*optarg)) - s->g_debug |= atoi(optarg); else goto unsupported_option; break; - case TCC_OPTION_static: - s->static_link = 1; - break; case TCC_OPTION_std: if (strcmp(optarg, "=c11") == 0 || strcmp(optarg, "=gnu11") == 0) s->cversion = 201112; break; - case TCC_OPTION_soname: - s->soname = tcc_strdup(optarg); - break; case TCC_OPTION_o: if (s->outfile) { tcc_warning("multiple -o option"); @@ -1655,9 +1590,6 @@ dorun: case TCC_OPTION_w: s->warn_none = 1; break; - case TCC_OPTION_rdynamic: - s->rdynamic = 1; - break; case TCC_OPTION_Wl: if (s->linker_arg.size) ((char*)s->linker_arg.data)[s->linker_arg.size - 1] = ','; @@ -1789,9 +1721,3 @@ PUB_FUNC void tcc_print_stats(TCCState *s1, unsigned total_time) fprintf(stderr, " %d max (bytes)\n", mem_max_size); #endif } - -#if ONE_SOURCE -# undef malloc -# undef realloc -# undef free -#endif diff --git a/libtcc/option.c b/libtcc/option.c index 3091afc8..6ab8fde6 100644 --- a/libtcc/option.c +++ b/libtcc/option.c @@ -1,2 +1,113 @@ -#include "tcc.h" +#include + +#include +#include "utils/cstr.h" + +enum { + OPTION_ignored = 0, + OPTION_I, + OPTION_D, + OPTION_U, + OPTION_P, + OPTION_L, + OPTION_B, + OPTION_l, + OPTION_bench, + OPTION_c, + OPTION_dumpmachine, + OPTION_dumpversion, + OPTION_d, + OPTION_std, + OPTION_o, + OPTION_pthread, + OPTION_r, + OPTION_Wl, + OPTION_Wp, + OPTION_W, + OPTION_O, + OPTION_m, + OPTION_f, + OPTION_isystem, + OPTION_include, + OPTION_nostdinc, + OPTION_nostdlib, + OPTION_print_search_dirs, + OPTION_w, + OPTION_E, + OPTION_M, + OPTION_MF, + OPTION_MD, + OPTION_MM, + OPTION_MMD, + OPTION_MP, + OPTION_x, +}; + +static const TCCOption options[] = { + {"I", OPTION_I, TCC_OPTION_HAS_ARG}, + {"D", OPTION_D, TCC_OPTION_HAS_ARG}, + {"U", OPTION_U, TCC_OPTION_HAS_ARG}, + {"P", OPTION_P, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP}, + {"L", OPTION_L, TCC_OPTION_HAS_ARG}, + {"B", OPTION_B, TCC_OPTION_HAS_ARG}, + {"l", OPTION_l, TCC_OPTION_HAS_ARG}, + {"bench", OPTION_bench, 0}, + {"c", OPTION_c, 0}, + {"dumpmachine", OPTION_dumpmachine, 0}, + {"dumpversion", OPTION_dumpversion, 0}, + {"d", OPTION_d, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP}, + {"std", OPTION_std, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP}, + {"o", OPTION_o, TCC_OPTION_HAS_ARG}, + {"pthread", OPTION_pthread, 0}, + {"r", OPTION_r, 0}, + {"Wl", OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP}, + {"Wp", OPTION_Wp, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP}, + {"W", OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP}, + {"O", OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP}, + {"m", OPTION_m, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP}, + {"f", OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP}, + {"isystem", OPTION_isystem, TCC_OPTION_HAS_ARG}, + {"include", OPTION_include, TCC_OPTION_HAS_ARG}, + {"nostdinc", OPTION_nostdinc, 0}, + {"nostdlib", OPTION_nostdlib, 0}, + {"print-search-dirs", OPTION_print_search_dirs, 0}, + {"w", OPTION_w, 0}, + {"E", OPTION_E, 0}, + {"M", OPTION_M, 0}, + {"MD", OPTION_MD, 0}, + {"MF", OPTION_MF, TCC_OPTION_HAS_ARG}, + {"MM", OPTION_MM, 0}, + {"MMD", OPTION_MMD, 0}, + {"MP", OPTION_MP, 0}, + {"x", OPTION_x, 0}, + + /* ignored (silently, except after -Wunsupported) */ + {"arch", 0, TCC_OPTION_HAS_ARG}, + {"g", 0, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP}, + {"C", 0, 0}, + {"-param", 0, 0}, + {"pedantic", 0, 0}, + {"pipe", 0, 0}, + {"s", 0, 0}, + {"traditional", 0, 0}, + {"shared", 0, 0}, + + {NULL, 0, 0} +}; + +static TCCOption *options_ext = NULL; + +static const char dumpmachine_str[] = "i386-pc-stupidos"; + +void +tcc_add_options(TCCOption *opt) +{ + options_ext = opt; +} + +int +tcc_parse_args(TCCState *s, int *pargc, char ***pargv, int optind) +{ + return (0); +} diff --git a/libtcc/option.h b/libtcc/option.h deleted file mode 100644 index 4539f91a..00000000 --- a/libtcc/option.h +++ /dev/null @@ -1,6 +0,0 @@ -#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 */ \ No newline at end of file diff --git a/libtcc/tcc_internal.h b/libtcc/tcc_internal.h new file mode 100644 index 00000000..48272031 --- /dev/null +++ b/libtcc/tcc_internal.h @@ -0,0 +1,4 @@ +#ifndef TCC_INTERNAL_H +# define TCC_INTERNAL_H 1 + +#endif /* !TCC_INTERNAL_H */ \ No newline at end of file diff --git a/libtcc/tccasm.c b/libtcc/tccasm.c index 907ba5e8..58667ce4 100644 --- a/libtcc/tccasm.c +++ b/libtcc/tccasm.c @@ -21,7 +21,7 @@ #define USING_GLOBALS #include "tcc.h" #include "utils/string.h" -#ifdef CONFIG_TCC_ASM +#include "token.h" static Section *last_text_section; /* to handle .previous asm directive */ static int asmgoto_n; @@ -33,7 +33,7 @@ static int asm_get_prefix_name(TCCState *s1, const char *prefix, unsigned int n) return tok_alloc_const(buf); } -ST_FUNC int asm_get_local_label_name(TCCState *s1, unsigned int n) +int asm_get_local_label_name(TCCState *s1, unsigned int n) { return asm_get_prefix_name(s1, "L..", n); } @@ -101,7 +101,7 @@ static Sym *asm_label_push(int v) are anonymous in C, in this case CSYM can be used to transfer all information from that symbol to the (possibly newly created) asm symbol. */ -ST_FUNC Sym* get_asm_sym(int name, Sym *csym) +Sym* get_asm_sym(int name, Sym *csym) { Sym *sym = asm_label_find(name); if (!sym) { @@ -388,12 +388,12 @@ static inline void asm_expr_cmp(TCCState *s1, ExprValue *pe) } } -ST_FUNC void asm_expr(TCCState *s1, ExprValue *pe) +void asm_expr(TCCState *s1, ExprValue *pe) { asm_expr_cmp(s1, pe); } -ST_FUNC int asm_int_expr(TCCState *s1) +int asm_int_expr(TCCState *s1) { ExprValue e; asm_expr(s1, &e); @@ -1006,7 +1006,7 @@ static int tcc_assemble_internal(TCCState *s1, int do_preprocess, int global) } /* Assemble the current file */ -ST_FUNC int tcc_assemble(TCCState *s1, int do_preprocess) +int tcc_assemble(TCCState *s1, int do_preprocess) { int ret; /* default section is text */ @@ -1043,7 +1043,7 @@ static void tcc_assemble_inline(TCCState *s1, const char *str, int len, int glob /* find a constraint by its number or id (gcc 3 extended syntax). return -1 if not found. Return in *pp in char after the constraint */ -ST_FUNC int find_constraint(ASMOperand *operands, int nb_operands, +int find_constraint(ASMOperand *operands, int nb_operands, const char *name, const char **pp) { int index; @@ -1182,7 +1182,7 @@ static void parse_asm_operands(ASMOperand *operands, int *nb_operands_ptr, } /* parse the GCC asm() instruction */ -ST_FUNC void asm_instr(void) +void asm_instr(void) { CString astr, *astr1; @@ -1330,7 +1330,7 @@ ST_FUNC void asm_instr(void) } -ST_FUNC void asm_global_instr(void) +void asm_global_instr(void) { CString *astr; int saved_nocode_wanted = nocode_wanted; @@ -1361,21 +1361,3 @@ ST_FUNC void asm_global_instr(void) nocode_wanted = saved_nocode_wanted; } - -/********************************************************/ -#else -ST_FUNC int tcc_assemble(TCCState *s1, int do_preprocess) -{ - tcc_error("asm not supported"); -} - -ST_FUNC void asm_instr(void) -{ - tcc_error("inline asm() not supported"); -} - -ST_FUNC void asm_global_instr(void) -{ - tcc_error("inline asm() not supported"); -} -#endif /* CONFIG_TCC_ASM */ diff --git a/libtcc/tcccoff.c b/libtcc/tcccoff.c index 7fd44c96..a6038469 100644 --- a/libtcc/tcccoff.c +++ b/libtcc/tcccoff.c @@ -1,4 +1,4 @@ -#include "coff.h" +#include "tcc/coff.h" #include "tcc.h" diff --git a/libtcc/tcccoff.c_old.c b/libtcc/tcccoff.c_old.c deleted file mode 100644 index 56064cdd..00000000 --- a/libtcc/tcccoff.c_old.c +++ /dev/null @@ -1,951 +0,0 @@ -/* - * 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; -} diff --git a/libtcc/tccelf.c b/libtcc/tccelf.c index 7fe67098..3af03008 100644 --- a/libtcc/tccelf.c +++ b/libtcc/tccelf.c @@ -58,7 +58,7 @@ static const char rdata[] = ".data.ro"; /* ------------------------------------------------------------------------- */ -ST_FUNC void tccelf_new(TCCState *s) +void tccelf_new(TCCState *s) { TCCState *s1 = s; @@ -79,10 +79,6 @@ ST_FUNC void tccelf_new(TCCState *s) ".strtab", ".hashtab", SHF_PRIVATE); - /* private symbol table for dynamic symbols */ - s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE|SHF_DYNSYM, - ".dynstrtab", - ".dynhashtab", SHF_PRIVATE); get_sym_attr(s, 0, 1); #ifdef TCC_TARGET_PE @@ -93,7 +89,7 @@ ST_FUNC void tccelf_new(TCCState *s) #endif } -ST_FUNC void free_section(Section *s) +void free_section(Section *s) { if (!s) return; @@ -102,7 +98,7 @@ ST_FUNC void free_section(Section *s) s->data_allocated = s->data_offset = 0; } -ST_FUNC void tccelf_delete(TCCState *s1) +void tccelf_delete(TCCState *s1) { int i; @@ -130,7 +126,7 @@ ST_FUNC void tccelf_delete(TCCState *s1) } /* save section data state */ -ST_FUNC void tccelf_begin_file(TCCState *s1) +void tccelf_begin_file(TCCState *s1) { Section *s; int i; for (i = 1; i < s1->nb_sections; i++) { @@ -145,7 +141,7 @@ static void update_relocs(TCCState *s1, Section *s, int *old_to_new_syms, int fi /* At the end of compilation, convert any UNDEF syms to global, and merge with previously existing symbols */ -ST_FUNC void tccelf_end_file(TCCState *s1) +void tccelf_end_file(TCCState *s1) { Section *s = s1->symtab; int first_sym, nb_syms, *tr, i; @@ -186,7 +182,7 @@ ST_FUNC void tccelf_end_file(TCCState *s1) } } -ST_FUNC Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags) +Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags) { Section *sec; @@ -228,7 +224,7 @@ ST_FUNC Section *new_section(TCCState *s1, const char *name, int sh_type, int sh return sec; } -ST_FUNC void init_symtab(Section *s) +void init_symtab(Section *s) { int *ptr, nb_buckets = 1; put_elf_str(s->link, ""); @@ -239,7 +235,7 @@ ST_FUNC void init_symtab(Section *s) memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int)); } -ST_FUNC Section *new_symtab(TCCState *s1, +Section *new_symtab(TCCState *s1, const char *symtab_name, int sh_type, int sh_flags, const char *strtab_name, const char *hash_name, int hash_sh_flags) @@ -258,7 +254,7 @@ ST_FUNC Section *new_symtab(TCCState *s1, } /* realloc section and set its content to zero */ -ST_FUNC void section_realloc(Section *sec, unsigned long new_size) +void section_realloc(Section *sec, unsigned long new_size) { unsigned long size; unsigned char *data; @@ -276,7 +272,7 @@ ST_FUNC void section_realloc(Section *sec, unsigned long new_size) /* reserve at least 'size' bytes aligned per 'align' in section 'sec' from current offset, and return the aligned offset */ -ST_FUNC size_t section_add(Section *sec, addr_t size, int align) +size_t section_add(Section *sec, addr_t size, int align) { size_t offset, offset1; @@ -292,7 +288,7 @@ ST_FUNC size_t section_add(Section *sec, addr_t size, int align) /* reserve at least 'size' bytes in section 'sec' from sec->data_offset. */ -ST_FUNC void *section_ptr_add(Section *sec, addr_t size) +void *section_ptr_add(Section *sec, addr_t size) { size_t offset = section_add(sec, size, 1); return sec->data + offset; @@ -323,7 +319,7 @@ static Section *have_section(TCCState *s1, const char *name) /* return a reference to a section, and create it if it does not exists */ -ST_FUNC Section *find_section(TCCState *s1, const char *name) +Section *find_section(TCCState *s1, const char *name) { Section *sec = have_section(s1, name); if (sec) @@ -334,7 +330,7 @@ ST_FUNC Section *find_section(TCCState *s1, const char *name) /* ------------------------------------------------------------------------- */ -ST_FUNC int put_elf_str(Section *s, const char *sym) +int put_elf_str(Section *s, const char *sym) { int offset, len; char *ptr; @@ -399,7 +395,7 @@ static void rebuild_hash(Section *s, unsigned int nb_buckets) } /* return the symbol number */ -ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size, +int put_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name) { int name_offset, sym_index; @@ -446,7 +442,7 @@ ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size, return sym_index; } -ST_FUNC int find_elf_sym(Section *s, const char *name) +int find_elf_sym(Section *s, const char *name) { ElfW(Sym) *sym; Section *hs; @@ -471,7 +467,7 @@ ST_FUNC int find_elf_sym(Section *s, const char *name) /* return elf symbol value, signal error if 'err' is nonzero, decorate name if FORC */ -ST_FUNC addr_t get_sym_addr(TCCState *s1, const char *name, int err, int forc) +addr_t get_sym_addr(TCCState *s1, const char *name, int err, int forc) { int sym_index; ElfW(Sym) *sym; @@ -504,7 +500,7 @@ void *tcc_get_symbol(TCCState *s, const char *name) } /* list elf symbol names and values */ -ST_FUNC void list_elf_symbols(TCCState *s, void *ctx, +void list_elf_symbols(TCCState *s, void *ctx, void (*symbol_cb)(void *ctx, const char *name, const void *val)) { ElfW(Sym) *sym; @@ -534,110 +530,9 @@ void tcc_list_symbols(TCCState *s, void *ctx, list_elf_symbols(s, ctx, symbol_cb); } -#ifndef ELF_OBJ_ONLY -static void -version_add (TCCState *s1) -{ - int i; - ElfW(Sym) *sym; - ElfW(Verneed) *vn = NULL; - Section *symtab; - int sym_index, end_sym, nb_versions = 2, nb_entries = 0; - ElfW(Half) *versym; - const char *name; - - if (0 == nb_sym_versions) - return; - versym_section = new_section(s1, ".gnu.version", SHT_GNU_versym, SHF_ALLOC); - versym_section->sh_entsize = sizeof(ElfW(Half)); - versym_section->link = s1->dynsym; - - /* add needed symbols */ - symtab = s1->dynsym; - end_sym = symtab->data_offset / sizeof (ElfSym); - versym = section_ptr_add(versym_section, end_sym * sizeof(ElfW(Half))); - for (sym_index = 1; sym_index < end_sym; ++sym_index) { - int dllindex, verndx; - sym = &((ElfW(Sym) *)symtab->data)[sym_index]; - name = (char *) symtab->link->data + sym->st_name; - dllindex = find_elf_sym(s1->dynsymtab_section, name); - verndx = (dllindex && dllindex < nb_sym_to_version) - ? sym_to_version[dllindex] : -1; - if (verndx >= 0 - /* XXX: on android, clang refuses to link with a libtcc.so made by tcc - when defined symbols have a version > 1 or when the version is '0'. - Whereas version '1' for example for 'signal' in an exe defeats - bcheck's signal_redir. */ - && (sym->st_shndx == SHN_UNDEF || (s1->output_type & TCC_OUTPUT_EXE)) - ) { - if (!sym_versions[verndx].out_index) - sym_versions[verndx].out_index = nb_versions++; - versym[sym_index] = sym_versions[verndx].out_index; - } else { - versym[sym_index] = 1; /* (*global*) */ - } - //printf("SYM %d %s\n", versym[sym_index], name); - } - /* generate verneed section, but not when it will be empty. Some - dynamic linkers look at their contents even when DTVERNEEDNUM and - section size is zero. */ - if (nb_versions > 2) { - verneed_section = new_section(s1, ".gnu.version_r", - SHT_GNU_verneed, SHF_ALLOC); - verneed_section->link = s1->dynsym->link; - for (i = nb_sym_versions; i-- > 0;) { - struct sym_version *sv = &sym_versions[i]; - int n_same_libs = 0, prev; - size_t vnofs; - ElfW(Vernaux) *vna = 0; - if (sv->out_index < 1) - continue; - - /* make sure that a DT_NEEDED tag is put */ - /* abitest-tcc fails on older i386-linux with "ld-linux.so.2" DT_NEEDED - ret_int_test... Inconsistency detected by ld.so: dl-minimal.c: 148: - realloc: Assertion `ptr == alloc_last_block' failed! */ - if (strcmp(sv->lib, "ld-linux.so.2")) - tcc_add_dllref(s1, sv->lib, 0); - - vnofs = section_add(verneed_section, sizeof(*vn), 1); - vn = (ElfW(Verneed)*)(verneed_section->data + vnofs); - vn->vn_version = 1; - vn->vn_file = put_elf_str(verneed_section->link, sv->lib); - vn->vn_aux = sizeof (*vn); - do { - prev = sv->prev_same_lib; - if (sv->out_index > 0) { - vna = section_ptr_add(verneed_section, sizeof(*vna)); - vna->vna_hash = elf_hash ((const unsigned char *)sv->version); - vna->vna_flags = 0; - vna->vna_other = sv->out_index; - sv->out_index = -2; - vna->vna_name = put_elf_str(verneed_section->link, sv->version); - vna->vna_next = sizeof (*vna); - //printf("LIB %d %s %s\n", vna->vna_other, sv->lib, verneed_section->link->data + vna->vna_name); - n_same_libs++; - } - if (prev >= 0) - sv = &sym_versions[prev]; - } while(prev >= 0); - vna->vna_next = 0; - vn = (ElfW(Verneed)*)(verneed_section->data + vnofs); - vn->vn_cnt = n_same_libs; - vn->vn_next = sizeof(*vn) + n_same_libs * sizeof(*vna); - nb_entries++; - } - if (vn) - vn->vn_next = 0; - verneed_section->sh_info = nb_entries; - } - dt_verneednum = nb_entries; -} -#endif /* ndef ELF_OBJ_ONLY */ - /* add an elf symbol : check if it is already defined and patch it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */ -ST_FUNC int set_elf_sym(Section *s, addr_t value, unsigned long size, +int set_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name) { TCCState *s1 = s->s1; @@ -724,7 +619,7 @@ ST_FUNC int set_elf_sym(Section *s, addr_t value, unsigned long size, } /* put relocation */ -ST_FUNC void put_elf_reloca(Section *symtab, Section *s, unsigned long offset, +void put_elf_reloca(Section *symtab, Section *s, unsigned long offset, int type, int symbol, addr_t addend) { TCCState *s1 = s->s1; @@ -754,13 +649,13 @@ ST_FUNC void put_elf_reloca(Section *symtab, Section *s, unsigned long offset, tcc_error_noabort("non-zero addend on REL architecture"); } -ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset, +void put_elf_reloc(Section *symtab, Section *s, unsigned long offset, int type, int symbol) { put_elf_reloca(symtab, s, offset, type, symbol, 0); } -ST_FUNC struct sym_attr *get_sym_attr(TCCState *s1, int index, int alloc) +struct sym_attr *get_sym_attr(TCCState *s1, int index, int alloc) { int n; struct sym_attr *tab; @@ -853,43 +748,6 @@ static void sort_syms(TCCState *s1, Section *s) /* See: https://flapenguin.me/elf-dt-gnu-hash */ #define ELFCLASS_BITS (PTR_SIZE * 8) -static Section *create_gnu_hash(TCCState *s1) -{ - int nb_syms, i, ndef, nbuckets, symoffset, bloom_size, bloom_shift; - ElfW(Sym) *p; - Section *gnu_hash; - Section *dynsym = s1->dynsym; - Elf32_Word *ptr; - - gnu_hash = new_section(s1, ".gnu.hash", SHT_GNU_HASH, SHF_ALLOC); - gnu_hash->link = dynsym->hash->link; - - nb_syms = dynsym->data_offset / sizeof(ElfW(Sym)); - - /* count def symbols */ - ndef = 0; - p = (ElfW(Sym) *)dynsym->data; - for(i = 0; i < nb_syms; i++, p++) - ndef += p->st_shndx != SHN_UNDEF; - - /* calculate gnu hash sizes and fill header */ - nbuckets = ndef / 4 + 1; - symoffset = nb_syms - ndef; - bloom_shift = PTR_SIZE == 8 ? 6 : 5; - bloom_size = 1; /* must be power of two */ - while (ndef >= bloom_size * (1 << (bloom_shift - 3))) - bloom_size *= 2; - ptr = section_ptr_add(gnu_hash, 4 * 4 + - PTR_SIZE * bloom_size + - nbuckets * 4 + - ndef * 4); - ptr[0] = nbuckets; - ptr[1] = symoffset; - ptr[2] = bloom_size; - ptr[3] = bloom_shift; - return gnu_hash; -} - static Elf32_Word elf_gnu_hash (const unsigned char *name) { Elf32_Word h = 5381; @@ -1019,7 +877,7 @@ static void update_gnu_hash(TCCState *s1, Section *gnu_hash) /* relocate symbol table, resolve undefined symbols if do_resolve is true and output error if undefined symbol. */ -ST_FUNC void relocate_syms(TCCState *s1, Section *symtab, int do_resolve) +void relocate_syms(TCCState *s1, Section *symtab, int do_resolve) { ElfW(Sym) *sym; int sym_bind, sh_num; @@ -1088,7 +946,7 @@ static void relocate_section(TCCState *s1, Section *s, Section *sr) } /* relocate all sections */ -ST_FUNC void relocate_sections(TCCState *s1) +void relocate_sections(TCCState *s1) { int i; Section *s, *sr; @@ -1098,12 +956,7 @@ ST_FUNC void relocate_sections(TCCState *s1) if (sr->sh_type != SHT_RELX) continue; s = s1->sections[sr->sh_info]; - if (s != s1->got - || s1->static_link - || s1->output_type == TCC_OUTPUT_MEMORY) - { - relocate_section(s1, s, sr); - } + relocate_section(s1, s, sr); #ifndef ELF_OBJ_ONLY if (sr->sh_flags & SHF_ALLOC) { ElfW_Rel *rel; @@ -1115,40 +968,6 @@ ST_FUNC void relocate_sections(TCCState *s1) } } -#ifndef ELF_OBJ_ONLY -/* count the number of dynamic relocations so that we can reserve - their space */ -static int prepare_dynamic_rel(TCCState *s1, Section *sr) -{ - int count = 0; - - ElfW_Rel *rel; - for_each_elem(sr, 0, rel, ElfW_Rel) { - int sym_index = ELFW(R_SYM)(rel->r_info); - int type = ELFW(R_TYPE)(rel->r_info); - switch(type) { - - case R_386_32: - if (!get_sym_attr(s1, sym_index, 0)->dyn_index - && ((ElfW(Sym)*)symtab_section->data + sym_index)->st_shndx == SHN_UNDEF) { - /* don't fixup unresolved (weak) symbols */ - rel->r_info = ELFW(R_INFO)(sym_index, R_386_RELATIVE); - break; - } - count++; - break; - case R_386_PC32: - if (get_sym_attr(s1, sym_index, 0)->dyn_index) - count++; - break; - default: - break; - } - } - - return count; -} -#endif #ifdef NEED_BUILD_GOT static int build_got(TCCState *s1) @@ -1264,7 +1083,7 @@ static struct sym_attr * put_got_entry(TCCState *s1, int dyn_reloc_type, /* build GOT and PLT entries */ /* Two passes because R_JMP_SLOT should become first. Some targets (arm, arm64) do not allow mixing R_JMP_SLOT and R_GLOB_DAT. */ -ST_FUNC void build_got_entries(TCCState *s1, int got_sym) +void build_got_entries(TCCState *s1, int got_sym) { Section *s; ElfW_Rel *rel; @@ -1373,7 +1192,7 @@ redo: } #endif /* def NEED_BUILD_GOT */ -ST_FUNC int set_global_sym(TCCState *s1, const char *name, Section *sec, addr_t offs) +int set_global_sym(TCCState *s1, const char *name, Section *sec, addr_t offs) { int shn = sec ? sec->sh_num : offs || !name ? SHN_ABS : SHN_UNDEF; if (sec && offs == -1) @@ -1400,7 +1219,7 @@ static void add_init_array_defines(TCCState *s1, const char *section_name) set_global_sym(s1, buf, s, end_offset); } -ST_FUNC void add_array (TCCState *s1, const char *sec, int c) +void add_array (TCCState *s1, const char *sec, int c) { Section *s; s = find_section(s1, sec); @@ -1410,35 +1229,15 @@ ST_FUNC void add_array (TCCState *s1, const char *sec, int c) section_ptr_add(s, PTR_SIZE); } -/* set symbol to STB_LOCAL and resolve. The point is to not export it as - a dynamic symbol to allow so's to have one each with a different value. */ -static void set_local_sym(TCCState *s1, const char *name, Section *s, int offset) -{ - int c = find_elf_sym(s1->symtab, name); - if (c) { - ElfW(Sym) *esym = (ElfW(Sym)*)s1->symtab->data + c; - esym->st_info = ELFW(ST_INFO)(STB_LOCAL, STT_NOTYPE); - esym->st_value = offset; - esym->st_shndx = s->sh_num; - } -} - -/* avoid generating debug/test_coverage code for stub functions */ -static void tcc_compile_string_no_debug(TCCState *s, const char *str) -{ - tcc_compile_string(s, str); -} - - #if !defined TCC_TARGET_PE /* add libc crt1/crti objects */ -ST_FUNC void tccelf_add_crtbegin(TCCState *s1) +void tccelf_add_crtbegin(TCCState *s1) { tcc_add_crt(s1, "crt1.o"); tcc_add_crt(s1, "crti.o"); } -ST_FUNC void tccelf_add_crtend(TCCState *s1) +void tccelf_add_crtend(TCCState *s1) { tcc_add_crt(s1, "crtn.o"); } @@ -1446,7 +1245,7 @@ ST_FUNC void tccelf_add_crtend(TCCState *s1) #ifndef TCC_TARGET_PE /* add tcc runtime libraries */ -ST_FUNC void tcc_add_runtime(TCCState *s1) +void tcc_add_runtime(TCCState *s1) { s1->filetype = 0; @@ -1459,14 +1258,6 @@ ST_FUNC void tcc_add_runtime(TCCState *s1) if (lpthread) tcc_add_library(s1, "pthread"); tcc_add_library(s1, "c"); -#ifdef TCC_LIBGCC - if (!s1->static_link) { - if (TCC_LIBGCC[0] == '/') - tcc_add_file(s1, TCC_LIBGCC); - else - tcc_add_dll(s1, TCC_LIBGCC, AFF_PRINT_ERROR); - } -#endif if (TCC_LIBTCC1[0]) tcc_add_support(s1, TCC_LIBTCC1); @@ -1523,7 +1314,7 @@ static void tcc_add_linker_symbols(TCCState *s1) } } -ST_FUNC void resolve_common_syms(TCCState *s1) +void resolve_common_syms(TCCState *s1) { ElfW(Sym) *sym; @@ -1542,7 +1333,7 @@ ST_FUNC void resolve_common_syms(TCCState *s1) } #ifndef ELF_OBJ_ONLY -ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel) +void fill_got_entry(TCCState *s1, ElfW_Rel *rel) { int sym_index = ELFW(R_SYM) (rel->r_info); ElfW(Sym) *sym = &((ElfW(Sym) *) symtab_section->data)[sym_index]; @@ -1560,7 +1351,7 @@ ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel) } /* Perform relocation to GOT or PLT entries */ -ST_FUNC void fill_got(TCCState *s1) +void fill_got(TCCState *s1) { Section *s; ElfW_Rel *rel; @@ -1613,143 +1404,12 @@ static void fill_local_got_entries(TCCState *s1) } } -/* Bind symbols of executable: resolve undefined symbols from exported symbols - in shared libraries */ -static void bind_exe_dynsyms(TCCState *s1, int is_PIE) -{ - const char *name; - int sym_index, index; - ElfW(Sym) *sym, *esym; - int type; - - /* Resolve undefined symbols from dynamic symbols. When there is a match: - - if STT_FUNC or STT_GNU_IFUNC symbol -> add it in PLT - - if STT_OBJECT symbol -> add it in .bss section with suitable reloc */ - for_each_elem(symtab_section, 1, sym, ElfW(Sym)) { - if (sym->st_shndx == SHN_UNDEF) { - name = (char *) symtab_section->link->data + sym->st_name; - sym_index = find_elf_sym(s1->dynsymtab_section, name); - if (sym_index) { - if (is_PIE) - continue; - esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index]; - type = ELFW(ST_TYPE)(esym->st_info); - if ((type == STT_FUNC) || (type == STT_GNU_IFUNC)) { - /* Indirect functions shall have STT_FUNC type in executable - * dynsym section. Indeed, a dlsym call following a lazy - * resolution would pick the symbol value from the - * executable dynsym entry which would contain the address - * of the function wanted by the caller of dlsym instead of - * the address of the function that would return that - * address */ - int dynindex - = put_elf_sym(s1->dynsym, 0, esym->st_size, - ELFW(ST_INFO)(STB_GLOBAL,STT_FUNC), 0, 0, - name); - int index = sym - (ElfW(Sym) *) symtab_section->data; - get_sym_attr(s1, index, 1)->dyn_index = dynindex; - } else if (type == STT_OBJECT) { - unsigned long offset; - ElfW(Sym) *dynsym; - offset = bss_section->data_offset; - /* XXX: which alignment ? */ - offset = (offset + 16 - 1) & -16; - set_elf_sym (s1->symtab, offset, esym->st_size, - esym->st_info, 0, bss_section->sh_num, name); - index = put_elf_sym(s1->dynsym, offset, esym->st_size, - esym->st_info, 0, bss_section->sh_num, - name); - - /* Ensure R_COPY works for weak symbol aliases */ - if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) { - for_each_elem(s1->dynsymtab_section, 1, dynsym, ElfW(Sym)) { - if ((dynsym->st_value == esym->st_value) - && (ELFW(ST_BIND)(dynsym->st_info) == STB_GLOBAL)) { - char *dynname = (char *) s1->dynsymtab_section->link->data - + dynsym->st_name; - put_elf_sym(s1->dynsym, offset, dynsym->st_size, - dynsym->st_info, 0, - bss_section->sh_num, dynname); - break; - } - } - } - - put_elf_reloc(s1->dynsym, bss_section, - offset, R_COPY, index); - offset += esym->st_size; - bss_section->data_offset = offset; - } - } else { - /* STB_WEAK undefined symbols are accepted */ - /* XXX: _fp_hw seems to be part of the ABI, so we ignore it */ - if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK || - !strcmp(name, "_fp_hw")) { - } else { - tcc_error_noabort("undefined symbol '%s'", name); - } - } - } - } -} - -/* Bind symbols of libraries: export all non local symbols of executable that - are referenced by shared libraries. The reason is that the dynamic loader - search symbol first in executable and then in libraries. Therefore a - reference to a symbol already defined by a library can still be resolved by - a symbol in the executable. With -rdynamic, export all defined symbols */ -static void bind_libs_dynsyms(TCCState *s1) -{ - const char *name; - int dynsym_index; - ElfW(Sym) *sym, *esym; - - for_each_elem(symtab_section, 1, sym, ElfW(Sym)) { - name = (char *)symtab_section->link->data + sym->st_name; - dynsym_index = find_elf_sym(s1->dynsymtab_section, name); - if (sym->st_shndx != SHN_UNDEF) { - if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL - && (dynsym_index || s1->rdynamic)) - set_elf_sym(s1->dynsym, sym->st_value, sym->st_size, - sym->st_info, 0, sym->st_shndx, name); - } else if (dynsym_index) { - esym = (ElfW(Sym) *)s1->dynsymtab_section->data + dynsym_index; - if (esym->st_shndx == SHN_UNDEF) { - /* weak symbols can stay undefined */ - if (ELFW(ST_BIND)(esym->st_info) != STB_WEAK) - tcc_warning("undefined dynamic symbol '%s'", name); - } - } - } -} - -/* Export all non local symbols. This is used by shared libraries so that the - non local symbols they define can resolve a reference in another shared - library or in the executable. Correspondingly, it allows undefined local - symbols to be resolved by other shared libraries or by the executable. */ -static void export_global_syms(TCCState *s1) -{ - int dynindex, index; - const char *name; - ElfW(Sym) *sym; - for_each_elem(symtab_section, 1, sym, ElfW(Sym)) { - if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) { - name = (char *) symtab_section->link->data + sym->st_name; - dynindex = set_elf_sym(s1->dynsym, sym->st_value, sym->st_size, - sym->st_info, 0, sym->st_shndx, name); - index = sym - (ElfW(Sym) *) symtab_section->data; - get_sym_attr(s1, index, 1)->dyn_index = dynindex; - } - } -} - /* decide if an unallocated section should be output. */ static int set_sec_sizes(TCCState *s1) { int i; Section *s; int textrel = 0; - int file_type = s1->output_type; /* Allocate strings for section names */ for(i = 1; i < s1->nb_sections; i++) { @@ -2223,7 +1883,7 @@ static int tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr) sort_syms(s1, s1->symtab); - ehdr.e_machine = EM_TCC_TARGET; + ehdr.e_machine = EM_386; ehdr.e_version = EV_CURRENT; ehdr.e_shoff = (sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr)) + 3) & -4; ehdr.e_ehsize = sizeof(ElfW(Ehdr)); @@ -2378,7 +2038,7 @@ static int elf_output_file(TCCState *s1, const char *filename) int i, ret, file_type, *sec_order; struct dyn_inf dyninf = {0}; Section *interp, *dynstr, *dynamic; - int textrel, got_sym, dt_flags_1; + int textrel, got_sym; file_type = s1->output_type; s1->nb_errors = 0; @@ -2391,81 +2051,10 @@ static int elf_output_file(TCCState *s1, const char *filename) tcc_add_runtime(s1); resolve_common_syms(s1); - if (!s1->static_link) { - if (file_type & TCC_OUTPUT_EXE) { - char *ptr; - /* allow override the dynamic loader */ - const char *elfint = getenv("LD_SO"); - if (elfint == NULL) - elfint = DEFAULT_ELFINTERP(s1); - /* add interpreter section only if executable */ - interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC); - interp->sh_addralign = 1; - ptr = section_ptr_add(interp, 1 + strlen(elfint)); - strcpy(ptr, elfint); - dyninf.interp = interp; - } - - /* add dynamic symbol table */ - s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC, - ".dynstr", - ".hash", SHF_ALLOC); - /* Number of local symbols (readelf complains if not set) */ - s1->dynsym->sh_info = 1; - dynstr = s1->dynsym->link; - /* add dynamic section */ - dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC, - SHF_ALLOC | SHF_WRITE); - dynamic->link = dynstr; - dynamic->sh_entsize = sizeof(ElfW(Dyn)); - - got_sym = build_got(s1); - if (file_type & TCC_OUTPUT_EXE) { - if (s1->nb_errors) - goto the_end; - } - build_got_entries(s1, got_sym); - if (file_type & TCC_OUTPUT_EXE) { - bind_libs_dynsyms(s1); - } else { - /* shared library case: simply export all global symbols */ - export_global_syms(s1); - } - dyninf.gnu_hash = create_gnu_hash(s1); - } else { - build_got_entries(s1, 0); - } - version_add (s1); + build_got_entries(s1, 0); textrel = set_sec_sizes(s1); - if (!s1->static_link) { - /* add a list of needed dlls */ - for(i = 0; i < s1->nb_loaded_dlls; i++) { - DLLReference *dllref = s1->loaded_dlls[i]; - if (dllref->level == 0) - put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name)); - } - - if (s1->rpath) - put_dt(dynamic, s1->enable_new_dtags ? DT_RUNPATH : DT_RPATH, - put_elf_str(dynstr, s1->rpath)); - - dt_flags_1 = DF_1_NOW; - put_dt(dynamic, DT_FLAGS, DF_BIND_NOW); - put_dt(dynamic, DT_FLAGS_1, dt_flags_1); - if (s1->symbolic) - put_dt(dynamic, DT_SYMBOLIC, 0); - - dyninf.dynamic = dynamic; - dyninf.dynstr = dynstr; - /* remember offset and reserve space for 2nd call below */ - dyninf.data_offset = dynamic->data_offset; - fill_dynamic(s1, &dyninf); - dynamic->sh_size = dynamic->data_offset; - dynstr->sh_size = dynstr->data_offset; - } - /* create and fill .shstrtab section */ alloc_sec_names(s1, 0); /* this array is used to reorder sections in the output file */ @@ -2494,7 +2083,7 @@ static int elf_output_file(TCCState *s1, const char *filename) fill_dynamic(s1, &dyninf); } /* Perform relocation to GOT or PLT entries */ - if (file_type == TCC_OUTPUT_EXE && s1->static_link) + if (file_type == TCC_OUTPUT_EXE) fill_got(s1); else if (s1->got) fill_local_got_entries(s1); @@ -2564,7 +2153,7 @@ int tcc_output_file(TCCState *s, const char *filename) #endif } -ST_FUNC ssize_t full_read(int fd, void *buf, size_t count) { +ssize_t full_read(int fd, void *buf, size_t count) { char *cbuf = buf; size_t rnum = 0; while (1) { @@ -2576,7 +2165,7 @@ ST_FUNC ssize_t full_read(int fd, void *buf, size_t count) { } } -ST_FUNC void *load_data(int fd, unsigned long file_offset, unsigned long size) +void *load_data(int fd, unsigned long file_offset, unsigned long size) { void *data; @@ -2593,7 +2182,7 @@ typedef struct SectionMergeInfo { uint8_t link_once; /* true if link once section */ } SectionMergeInfo; -ST_FUNC int tcc_object_type(int fd, ElfW(Ehdr) *h) +int tcc_object_type(int fd, ElfW(Ehdr) *h) { int size = full_read(fd, h, sizeof *h); if (size == sizeof *h && 0 == memcmp(h, ELFMAG, 4)) { @@ -2612,7 +2201,7 @@ ST_FUNC int tcc_object_type(int fd, ElfW(Ehdr) *h) /* load an object file and merge it with current files */ /* XXX: handle correctly stab (debug) info */ -ST_FUNC int tcc_load_object_file(TCCState *s1, +int tcc_load_object_file(TCCState *s1, int fd, unsigned long file_offset) { ElfW(Ehdr) ehdr; @@ -2620,7 +2209,6 @@ ST_FUNC int tcc_load_object_file(TCCState *s1, unsigned long size, offset, offseti; int i, j, nb_syms, sym_index, ret, seencompressed; char *strsec, *strtab; - int stab_index, stabstr_index; int *old_to_new_syms; char *sh_name, *name; SectionMergeInfo *sm_table, *sm; @@ -2633,7 +2221,7 @@ ST_FUNC int tcc_load_object_file(TCCState *s1, goto invalid; /* test CPU specific stuff */ if (ehdr.e_ident[5] != ELFDATA2LSB || - ehdr.e_machine != EM_TCC_TARGET) { + ehdr.e_machine != EM_386) { invalid: return tcc_error_noabort("invalid object file"); } @@ -2652,7 +2240,6 @@ invalid: strtab = NULL; nb_syms = 0; seencompressed = 0; - stab_index = stabstr_index = 0; ret = -1; for(i = 1; i < ehdr.e_shnum; i++) { @@ -2756,21 +2343,6 @@ invalid: next: ; } - /* gr relocate stab strings */ - if (stab_index && stabstr_index) { - Stab_Sym *a, *b; - unsigned o; - s = sm_table[stab_index].s; - a = (Stab_Sym *)(s->data + sm_table[stab_index].offset); - b = (Stab_Sym *)(s->data + s->data_offset); - o = sm_table[stabstr_index].offset; - while (a < b) { - if (a->n_strx) - a->n_strx += o; - a++; - } - } - /* second short pass to update sh_link and sh_info fields of new sections */ for(i = 1; i < ehdr.e_shnum; i++) { @@ -2964,7 +2536,7 @@ static int tcc_load_alacarte(TCCState *s1, int fd, int size, int entrysize) } /* load a '.a' file */ -ST_FUNC int tcc_load_archive(TCCState *s1, int fd, int alacarte) +int tcc_load_archive(TCCState *s1, int fd, int alacarte) { ArchiveHeader hdr; /* char magic[8]; */ @@ -3002,52 +2574,6 @@ ST_FUNC int tcc_load_archive(TCCState *s1, int fd, int alacarte) } #ifndef ELF_OBJ_ONLY -/* Set LV[I] to the global index of sym-version (LIB,VERSION). Maybe resizes - LV, maybe create a new entry for (LIB,VERSION). */ -static void set_ver_to_ver(TCCState *s1, int *n, int **lv, int i, char *lib, char *version) -{ - while (i >= *n) { - *lv = tcc_realloc(*lv, (*n + 1) * sizeof(**lv)); - (*lv)[(*n)++] = -1; - } - if ((*lv)[i] == -1) { - int v, prev_same_lib = -1; - for (v = 0; v < nb_sym_versions; v++) { - if (strcmp(sym_versions[v].lib, lib)) - continue; - prev_same_lib = v; - if (!strcmp(sym_versions[v].version, version)) - break; - } - if (v == nb_sym_versions) { - sym_versions = tcc_realloc (sym_versions, - (v + 1) * sizeof(*sym_versions)); - sym_versions[v].lib = tcc_strdup(lib); - sym_versions[v].version = tcc_strdup(version); - sym_versions[v].out_index = 0; - sym_versions[v].prev_same_lib = prev_same_lib; - nb_sym_versions++; - } - (*lv)[i] = v; - } -} - -/* Associates symbol SYM_INDEX (in dynsymtab) with sym-version index - VERNDX. */ -static void -set_sym_version(TCCState *s1, int sym_index, int verndx) -{ - if (sym_index >= nb_sym_to_version) { - int newelems = sym_index ? sym_index * 2 : 1; - sym_to_version = tcc_realloc(sym_to_version, - newelems * sizeof(*sym_to_version)); - memset(sym_to_version + nb_sym_to_version, -1, - (newelems - nb_sym_to_version) * sizeof(*sym_to_version)); - nb_sym_to_version = newelems; - } - if (sym_to_version[sym_index] < 0) - sym_to_version[sym_index] = verndx; -} struct versym_info { int nb_versyms; @@ -3058,217 +2584,6 @@ struct versym_info { }; -static void store_version(TCCState *s1, struct versym_info *v, char *dynstr) -{ - char *lib, *version; - uint32_t next; - int i; - -#define DEBUG_VERSION 0 - - if (v->versym && v->verdef) { - ElfW(Verdef) *vdef = v->verdef; - lib = NULL; - do { - ElfW(Verdaux) *verdaux = - (ElfW(Verdaux) *) (((char *) vdef) + vdef->vd_aux); - -#if DEBUG_VERSION - printf ("verdef: version:%u flags:%u index:%u, hash:%u\n", - vdef->vd_version, vdef->vd_flags, vdef->vd_ndx, - vdef->vd_hash); -#endif - if (vdef->vd_cnt) { - version = dynstr + verdaux->vda_name; - - if (lib == NULL) - lib = version; - else - set_ver_to_ver(s1, &v->nb_local_ver, &v->local_ver, vdef->vd_ndx, - lib, version); -#if DEBUG_VERSION - printf (" verdaux(%u): %s\n", vdef->vd_ndx, version); -#endif - } - next = vdef->vd_next; - vdef = (ElfW(Verdef) *) (((char *) vdef) + next); - } while (next); - } - if (v->versym && v->verneed) { - ElfW(Verneed) *vneed = v->verneed; - do { - ElfW(Vernaux) *vernaux = - (ElfW(Vernaux) *) (((char *) vneed) + vneed->vn_aux); - - lib = dynstr + vneed->vn_file; -#if DEBUG_VERSION - printf ("verneed: %u %s\n", vneed->vn_version, lib); -#endif - for (i = 0; i < vneed->vn_cnt; i++) { - if ((vernaux->vna_other & 0x8000) == 0) { /* hidden */ - version = dynstr + vernaux->vna_name; - set_ver_to_ver(s1, &v->nb_local_ver, &v->local_ver, vernaux->vna_other, - lib, version); -#if DEBUG_VERSION - printf (" vernaux(%u): %u %u %s\n", - vernaux->vna_other, vernaux->vna_hash, - vernaux->vna_flags, version); -#endif - } - vernaux = (ElfW(Vernaux) *) (((char *) vernaux) + vernaux->vna_next); - } - next = vneed->vn_next; - vneed = (ElfW(Verneed) *) (((char *) vneed) + next); - } while (next); - } - -#if DEBUG_VERSION - for (i = 0; i < v->nb_local_ver; i++) { - if (v->local_ver[i] > 0) { - printf ("%d: lib: %s, version %s\n", - i, sym_versions[v->local_ver[i]].lib, - sym_versions[v->local_ver[i]].version); - } - } -#endif -} - -/* load a library / DLL - 'level = 0' means that the DLL is referenced by the user - (so it should be added as DT_NEEDED in the generated ELF file) */ -ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level) -{ - ElfW(Ehdr) ehdr; - ElfW(Shdr) *shdr, *sh, *sh1; - int i, nb_syms, nb_dts, sym_bind, ret = -1; - ElfW(Sym) *sym, *dynsym; - ElfW(Dyn) *dt, *dynamic; - - char *dynstr; - int sym_index; - const char *name, *soname; - struct versym_info v; - - full_read(fd, &ehdr, sizeof(ehdr)); - - /* test CPU specific stuff */ - if (ehdr.e_ident[5] != ELFDATA2LSB || - ehdr.e_machine != EM_TCC_TARGET) { - return tcc_error_noabort("bad architecture"); - } - - /* read sections */ - shdr = load_data(fd, ehdr.e_shoff, sizeof(ElfW(Shdr)) * ehdr.e_shnum); - - /* load dynamic section and dynamic symbols */ - nb_syms = 0; - nb_dts = 0; - dynamic = NULL; - dynsym = NULL; /* avoid warning */ - dynstr = NULL; /* avoid warning */ - memset(&v, 0, sizeof v); - - for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) { - switch(sh->sh_type) { - case SHT_DYNAMIC: - nb_dts = sh->sh_size / sizeof(ElfW(Dyn)); - dynamic = load_data(fd, sh->sh_offset, sh->sh_size); - break; - case SHT_DYNSYM: - nb_syms = sh->sh_size / sizeof(ElfW(Sym)); - dynsym = load_data(fd, sh->sh_offset, sh->sh_size); - sh1 = &shdr[sh->sh_link]; - dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size); - break; - case SHT_GNU_verdef: - v.verdef = load_data(fd, sh->sh_offset, sh->sh_size); - break; - case SHT_GNU_verneed: - v.verneed = load_data(fd, sh->sh_offset, sh->sh_size); - break; - case SHT_GNU_versym: - v.nb_versyms = sh->sh_size / sizeof(ElfW(Half)); - v.versym = load_data(fd, sh->sh_offset, sh->sh_size); - break; - default: - break; - } - } - - if (!dynamic) - goto the_end; - - /* compute the real library name */ - soname = tcc_basename(filename); - for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) - if (dt->d_tag == DT_SONAME) - soname = dynstr + dt->d_un.d_val; - - /* if the dll is already loaded, do not load it */ - if (tcc_add_dllref(s1, soname, level)->found) - goto ret_success; - - if (v.nb_versyms != nb_syms) - tcc_free (v.versym), v.versym = NULL; - else - store_version(s1, &v, dynstr); - - /* add dynamic symbols in dynsym_section */ - for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) { - sym_bind = ELFW(ST_BIND)(sym->st_info); - if (sym_bind == STB_LOCAL) - continue; - name = dynstr + sym->st_name; - sym_index = set_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size, - sym->st_info, sym->st_other, sym->st_shndx, name); - if (v.versym) { - ElfW(Half) vsym = v.versym[i]; - if ((vsym & 0x8000) == 0 && vsym > 0 && vsym < v.nb_local_ver) - set_sym_version(s1, sym_index, v.local_ver[vsym]); - } - } - - /* do not load all referenced libraries - (recursive loading can break linking of libraries) */ - /* following DT_NEEDED is needed for the dynamic loader (libdl.so), - but it is no longer needed, when linking a library or a program. - When tcc output mode is OUTPUT_MEM, - tcc calls dlopen, which handles DT_NEEDED for us */ - -#if 0 - for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) - if (dt->d_tag == DT_RPATH) - tcc_add_library_path(s1, dynstr + dt->d_un.d_val); - - /* load all referenced DLLs */ - for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) { - switch(dt->d_tag) { - case DT_NEEDED: - name = dynstr + dt->d_un.d_val; - if (tcc_add_dllref(s1, name, -1)) - continue; - if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) { - ret = tcc_error_noabort("referenced dll '%s' not found", name); - goto the_end; - } - } - } -#endif - - ret_success: - ret = 0; - the_end: - tcc_free(dynstr); - tcc_free(dynsym); - tcc_free(dynamic); - tcc_free(shdr); - tcc_free(v.local_ver); - tcc_free(v.verdef); - tcc_free(v.verneed); - tcc_free(v.versym); - return ret; -} - #define LD_TOK_NAME 256 #define LD_TOK_EOF (-1) @@ -3410,7 +2725,7 @@ static int ld_add_file(TCCState *s1, const char filename[]) return 0; filename = tcc_basename(filename); } - return tcc_add_dll(s1, filename, AFF_PRINT_ERROR); + return -1; } static int ld_add_file_list(TCCState *s1, const char *cmd, int as_needed) @@ -3442,11 +2757,7 @@ static int ld_add_file_list(TCCState *s1, const char *cmd, int as_needed) goto lib_parse_error; } pstrcpy(libname, sizeof libname, &filename[1]); - if (s1->static_link) { - snprintf(filename, sizeof filename, "lib%s.a", libname); - } else { - snprintf(filename, sizeof filename, "lib%s.so", libname); - } + snprintf(filename, sizeof filename, "lib%s.a", libname); } else if (t != LD_TOK_NAME) { ret = tcc_error_noabort("filename expected"); goto lib_parse_error; @@ -3490,7 +2801,7 @@ lib_parse_error: /* interpret a subset of GNU ldscripts to handle the dummy libc.so files */ -ST_FUNC int tcc_load_ldscript(TCCState *s1, int fd) +int tcc_load_ldscript(TCCState *s1, int fd) { char cmd[64]; char filename[1024]; diff --git a/libtcc/tccgen.c b/libtcc/tccgen.c index 1606b3c4..0c7d6cc2 100644 --- a/libtcc/tccgen.c +++ b/libtcc/tccgen.c @@ -21,6 +21,7 @@ #define USING_GLOBALS #include "tcc.h" #include "utils/string.h" +#include "token.h" /********************************************************/ /* global variables */ @@ -30,13 +31,13 @@ rsym: return symbol anon_sym: anonymous symbol index */ -ST_DATA int rsym, anon_sym, ind, loc; +int rsym, anon_sym, ind, loc; -ST_DATA Sym *global_stack; -ST_DATA Sym *local_stack; -ST_DATA Sym *define_stack; -ST_DATA Sym *global_label_stack; -ST_DATA Sym *local_label_stack; +Sym *global_stack; +Sym *local_stack; +Sym *define_stack; +Sym *global_label_stack; +Sym *local_label_stack; static Sym *sym_free_first; static void **sym_pools; @@ -45,11 +46,11 @@ static int nb_sym_pools; static Sym *all_cleanups, *pending_gotos; static int local_scope; -ST_DATA SValue *vtop; +SValue *vtop; static SValue _vstack[1 + VSTACK_SIZE]; #define vstack (_vstack + 1) -ST_DATA int nocode_wanted; /* no code generation wanted */ +int nocode_wanted; /* no code generation wanted */ #define NODATA_WANTED (nocode_wanted > 0) /* no static data output wanted either */ #define DATA_ONLY_WANTED 0x80000000 /* ON outside of functions and for static initializers */ @@ -67,13 +68,13 @@ ST_DATA int nocode_wanted; /* no code generation wanted */ #define CONST_WANTED_MASK 0x0FFF0000 #define CONST_WANTED (nocode_wanted & CONST_WANTED_MASK) -ST_DATA int global_expr; /* true if compound literals must be allocated globally (used during initializers parsing */ -ST_DATA CType func_vt; /* current function return type (used by return instruction) */ -ST_DATA int func_var; /* true if current function is variadic (used by return instruction) */ -ST_DATA int func_vc; -ST_DATA int func_ind; -ST_DATA const char *funcname; -ST_DATA CType int_type, func_old_type, char_type, char_pointer_type; +int global_expr; /* true if compound literals must be allocated globally (used during initializers parsing */ +CType func_vt; /* current function return type (used by return instruction) */ +int func_var; /* true if current function is variadic (used by return instruction) */ +int func_vc; +int func_ind; +const char *funcname; +CType int_type, func_old_type, char_type, char_pointer_type; static CString initstr; #if PTR_SIZE == 4 @@ -163,7 +164,7 @@ static void do_Static_assert(void); /* Automagical code suppression */ /* Clear 'nocode_wanted' at forward label if it was used */ -ST_FUNC void gsym(int t) +void gsym(int t) { if (t) { gsym_addr(t, ind); @@ -199,7 +200,7 @@ static int gjmp_acs(int t) #define gjmp gjmp_acs /* ------------------------------------------------------------------------- */ -ST_INLN int is_float(int t) +int is_float(int t) { int bt = t & VT_BTYPE; return bt == VT_LDOUBLE @@ -289,7 +290,7 @@ static int RC2_TYPE(int t, int rc) /* we use our own 'finite' function to avoid potential problems with non standard math libs */ /* XXX: endianness dependent */ -ST_FUNC int ieee_finite(double d) +int ieee_finite(double d) { int p[4]; memcpy(p, &d, sizeof(double)); @@ -299,13 +300,13 @@ ST_FUNC int ieee_finite(double d) /* compiling intel long double natively */ # define TCC_IS_NATIVE_387 -ST_FUNC void test_lvalue(void) +void test_lvalue(void) { if (!(vtop->r & VT_LVAL)) expect("lvalue"); } -ST_FUNC void check_vstack(void) +void check_vstack(void) { if (vtop != vstack - 1) tcc_error("internal compiler error: vstack leak (%d)", @@ -327,7 +328,7 @@ void pv (const char *lbl, int a, int b) /* ------------------------------------------------------------------------- */ /* initialize vstack and types. This must be done also for tcc -E */ -ST_FUNC void tccgen_init(TCCState *s1) +void tccgen_init(TCCState *s1) { vtop = vstack - 1; memset(vtop, 0, sizeof *vtop); @@ -351,7 +352,7 @@ ST_FUNC void tccgen_init(TCCState *s1) cstr_new(&initstr); } -ST_FUNC int tccgen_compile(TCCState *s1) +int tccgen_compile(TCCState *s1) { funcname = ""; func_ind = -1; @@ -371,7 +372,7 @@ ST_FUNC int tccgen_compile(TCCState *s1) return 0; } -ST_FUNC void tccgen_finish(TCCState *s1) +void tccgen_finish(TCCState *s1) { free_inline_functions(s1); sym_pop(&global_stack, NULL, 0); @@ -396,7 +397,7 @@ ST_FUNC void tccgen_finish(TCCState *s1) } /* ------------------------------------------------------------------------- */ -ST_FUNC ElfSym *elfsym(Sym *s) +ElfSym *elfsym(Sym *s) { if (!s || !s->c) return NULL; @@ -404,7 +405,7 @@ ST_FUNC ElfSym *elfsym(Sym *s) } /* apply storage attributes to Elf symbol */ -ST_FUNC void update_storage(Sym *sym) +void update_storage(Sym *sym) { ElfSym *esym; int sym_bind, old_sym_bind; @@ -450,7 +451,7 @@ ST_FUNC void update_storage(Sym *sym) /* update sym->c so that it points to an external symbol in section 'section' with value 'value' */ -ST_FUNC void put_extern_sym2(Sym *sym, int sh_num, +void put_extern_sym2(Sym *sym, int sh_num, addr_t value, unsigned long size, int can_add_underscore) { @@ -515,7 +516,7 @@ ST_FUNC void put_extern_sym2(Sym *sym, int sh_num, update_storage(sym); } -ST_FUNC void put_extern_sym(Sym *sym, Section *s, addr_t value, unsigned long size) +void put_extern_sym(Sym *sym, Section *s, addr_t value, unsigned long size) { if (nocode_wanted && (NODATA_WANTED || (s && s == cur_text_section))) return; @@ -523,7 +524,7 @@ ST_FUNC void put_extern_sym(Sym *sym, Section *s, addr_t value, unsigned long si } /* add a new relocation entry to symbol 'sym' in section 's' */ -ST_FUNC void greloca(Section *s, Sym *sym, unsigned long offset, int type, +void greloca(Section *s, Sym *sym, unsigned long offset, int type, addr_t addend) { int c = 0; @@ -542,7 +543,7 @@ ST_FUNC void greloca(Section *s, Sym *sym, unsigned long offset, int type, } #if PTR_SIZE == 4 -ST_FUNC void greloc(Section *s, Sym *sym, unsigned long offset, int type) +void greloc(Section *s, Sym *sym, unsigned long offset, int type) { greloca(s, sym, offset, type, 0); } @@ -584,7 +585,7 @@ static inline Sym *sym_malloc(void) #endif } -ST_INLN void sym_free(Sym *sym) +void sym_free(Sym *sym) { #ifndef SYM_DEBUG sym->next = sym_free_first; @@ -595,7 +596,7 @@ ST_INLN void sym_free(Sym *sym) } /* push, without hashing */ -ST_FUNC Sym *sym_push2(Sym **ps, int v, int t, int c) +Sym *sym_push2(Sym **ps, int v, int t, int c) { Sym *s; @@ -612,7 +613,7 @@ ST_FUNC Sym *sym_push2(Sym **ps, int v, int t, int c) /* find a symbol and return its associated structure. 's' is the top of the symbol stack */ -ST_FUNC Sym *sym_find2(Sym *s, int v) +Sym *sym_find2(Sym *s, int v) { while (s) { if (s->v == v) @@ -623,7 +624,7 @@ ST_FUNC Sym *sym_find2(Sym *s, int v) } /* structure lookup */ -ST_INLN Sym *struct_find(int v) +Sym *struct_find(int v) { v -= TOK_IDENT; if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT)) @@ -632,7 +633,7 @@ ST_INLN Sym *struct_find(int v) } /* find an identifier */ -ST_INLN Sym *sym_find(int v) +Sym *sym_find(int v) { v -= TOK_IDENT; if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT)) @@ -649,7 +650,7 @@ static int sym_scope(Sym *s) } /* push a given symbol on the symbol stack */ -ST_FUNC Sym *sym_push(int v, CType *type, int r, int c) +Sym *sym_push(int v, CType *type, int r, int c) { Sym *s, **ps; TokenSym *ts; @@ -681,7 +682,7 @@ ST_FUNC Sym *sym_push(int v, CType *type, int r, int c) } /* push a global identifier */ -ST_FUNC Sym *global_identifier_push(int v, int t, int c) +Sym *global_identifier_push(int v, int t, int c) { Sym *s, **ps; s = sym_push2(&global_stack, v, t, c); @@ -701,7 +702,7 @@ ST_FUNC Sym *global_identifier_push(int v, int t, int c) /* pop symbols until top reaches 'b'. If KEEP is non-zero don't really pop them yet from the list, but do remove them from the token array. */ -ST_FUNC void sym_pop(Sym **ptop, Sym *b, int keep) +void sym_pop(Sym **ptop, Sym *b, int keep) { Sym *s, *ss, **ps; TokenSym *ts; @@ -730,7 +731,7 @@ ST_FUNC void sym_pop(Sym **ptop, Sym *b, int keep) } /* label lookup */ -ST_FUNC Sym *label_find(int v) +Sym *label_find(int v) { v -= TOK_IDENT; if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT)) @@ -738,7 +739,7 @@ ST_FUNC Sym *label_find(int v) return table_ident[v]->sym_label; } -ST_FUNC Sym *label_push(Sym **ptop, int v, int flags) +Sym *label_push(Sym **ptop, int v, int flags) { Sym *s, **ps; s = sym_push2(ptop, v, VT_STATIC, 0); @@ -757,7 +758,7 @@ ST_FUNC Sym *label_push(Sym **ptop, int v, int flags) /* pop labels until element last is reached. Look if any labels are undefined. Define symbols if '&&label' was used. */ -ST_FUNC void label_pop(Sym **ptop, Sym *slast, int keep) +void label_pop(Sym **ptop, Sym *slast, int keep) { Sym *s, *s1; for(s = *ptop; s != slast; s = s1) { @@ -824,7 +825,7 @@ static void vsetc(CType *type, int r, CValue *vc) vtop->sym = NULL; } -ST_FUNC void vswap(void) +void vswap(void) { SValue tmp; @@ -835,7 +836,7 @@ ST_FUNC void vswap(void) } /* pop stack value */ -ST_FUNC void vpop(void) +void vpop(void) { int v; v = vtop->r & VT_VALMASK; @@ -868,7 +869,7 @@ static void vpush64(int ty, unsigned long long v) } /* push integer constant */ -ST_FUNC void vpushi(int v) +void vpushi(int v) { vpush64(VT_INT, v); } @@ -885,7 +886,7 @@ static inline void vpushll(long long v) vpush64(VT_LLONG, v); } -ST_FUNC void vset(CType *type, int r, int v) +void vset(CType *type, int r, int v) { CValue cval; cval.i = v; @@ -900,7 +901,7 @@ static void vseti(int r, int v) vset(&type, r, v); } -ST_FUNC void vpushv(SValue *v) +void vpushv(SValue *v) { if (vtop >= vstack + (VSTACK_SIZE - 1)) tcc_error("memory full (vstack)"); @@ -914,7 +915,7 @@ static void vdup(void) } /* rotate the stack element at position n-1 to the top */ -ST_FUNC void vrotb(int n) +void vrotb(int n) { SValue tmp; if (--n < 1) @@ -926,7 +927,7 @@ ST_FUNC void vrotb(int n) } /* rotate the top stack element into position n-1 */ -ST_FUNC void vrott(int n) +void vrott(int n) { SValue tmp; if (--n < 1) @@ -938,7 +939,7 @@ ST_FUNC void vrott(int n) } /* reverse order of the the first n stack elements */ -ST_FUNC void vrev(int n) +void vrev(int n) { int i; SValue tmp; @@ -951,7 +952,7 @@ ST_FUNC void vrev(int n) /* vtop->r = VT_CMP means CPU-flags have been set from comparison or test. */ /* called from generators to set the result from relational ops */ -ST_FUNC void vset_VT_CMP(int op) +void vset_VT_CMP(int op) { vtop->r = VT_CMP; vtop->cmp_op = op; @@ -1038,7 +1039,7 @@ static void gen_test_zero(int op) /* ------------------------------------------------------------------------- */ /* push a symbol value of TYPE */ -ST_FUNC void vpushsym(CType *type, Sym *sym) +void vpushsym(CType *type, Sym *sym) { CValue cval; cval.i = 0; @@ -1047,7 +1048,7 @@ ST_FUNC void vpushsym(CType *type, Sym *sym) } /* Return a static symbol pointing to a section */ -ST_FUNC Sym *get_sym_ref(CType *type, Section *sec, unsigned long offset, unsigned long size) +Sym *get_sym_ref(CType *type, Section *sec, unsigned long offset, unsigned long size) { int v; Sym *sym; @@ -1066,7 +1067,7 @@ static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned } /* define a new external reference to a symbol 'v' of type 'u' */ -ST_FUNC Sym *external_global_sym(int v, CType *type) +Sym *external_global_sym(int v, CType *type) { Sym *s; @@ -1085,14 +1086,14 @@ ST_FUNC Sym *external_global_sym(int v, CType *type) /* create an external reference with no specific type similar to asm labels. This avoids type conflicts if the symbol is used from C too */ -ST_FUNC Sym *external_helper_sym(int v) +Sym *external_helper_sym(int v) { CType ct = { VT_ASM_FUNC, NULL }; return external_global_sym(v, &ct); } /* push a reference to an helper function (such as memmove) */ -ST_FUNC void vpush_helper_func(int v) +void vpush_helper_func(int v) { vpushsym(&func_old_type, external_helper_sym(v)); } @@ -1289,7 +1290,7 @@ static Sym *external_sym(int v, CType *type, int r, AttributeDef *ad) } /* save registers up to (vtop - n) stack entry */ -ST_FUNC void save_regs(int n) +void save_regs(int n) { SValue *p, *p1; for(p = vstack, p1 = vtop - n; p <= p1; p++) @@ -1297,14 +1298,14 @@ ST_FUNC void save_regs(int n) } /* save r to the memory stack, and mark it as being free */ -ST_FUNC void save_reg(int r) +void save_reg(int r) { save_reg_upstack(r, 0); } /* save r to the memory stack, and mark it as being free, if seen up to (vtop - n) stack entry */ -ST_FUNC void save_reg_upstack(int r, int n) +void save_reg_upstack(int r, int n) { int l, size, align, bt, r2; SValue *p, *p1, sv; @@ -1357,7 +1358,7 @@ ST_FUNC void save_reg_upstack(int r, int n) } /* find a free register of class 'rc'. If none, save one register */ -ST_FUNC int get_reg(int rc) +int get_reg(int rc) { int r; SValue *p; @@ -1455,7 +1456,7 @@ static void move_reg(int r, int s, int t) } /* get address of vtop (vtop MUST BE an lvalue) */ -ST_FUNC void gaddrof(void) +void gaddrof(void) { vtop->r &= ~VT_LVAL; /* tricky: if saved lvalue, then we can go back to lvalue */ @@ -1555,7 +1556,7 @@ static void store_packed_bf(int bit_pos, int bit_size) vpop(), vpop(); } -static int adjust_bf(SValue *sv, int bit_pos, int bit_size) +static int adjust_bf(SValue *sv) { int t; if (0 == sv->type.ref) @@ -1571,7 +1572,7 @@ static int adjust_bf(SValue *sv, int bit_pos, int bit_size) /* store vtop a register belonging to class 'rc'. lvalues are converted to values. Cannot be used if cannot be converted to register value (such as structures). */ -ST_FUNC int gv(int rc) +int gv(int rc) { int r, r2, r_ok, r2_ok, rc2, bt; int bit_pos, bit_size, size, align; @@ -1590,7 +1591,7 @@ ST_FUNC int gv(int rc) if ((vtop->type.t & VT_BTYPE) == VT_BOOL) type.t |= VT_UNSIGNED; - r = adjust_bf(vtop, bit_pos, bit_size); + r = adjust_bf(vtop); if ((vtop->type.t & VT_BTYPE) == VT_LLONG) type.t |= VT_LLONG; @@ -1616,7 +1617,7 @@ ST_FUNC int gv(int rc) (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) { /* CPUs usually cannot use float constants, so we store them generically in data segment */ - init_params p = { rodata_section }; + init_params p = { rodata_section, 0, NULL }; unsigned long offset; size = type_size(&vtop->type, &align); if (NODATA_WANTED) @@ -1709,7 +1710,7 @@ ST_FUNC int gv(int rc) } /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */ -ST_FUNC void gv2(int rc1, int rc2) +void gv2(int rc1, int rc2) { /* generate more generic register first. But VT_JMP or VT_CMP values must be generated first in all cases to avoid possible @@ -1739,7 +1740,7 @@ ST_FUNC void gv2(int rc1, int rc2) #if PTR_SIZE == 4 /* expand 64bit on stack in two ints */ -ST_FUNC void lexpand(void) +void lexpand(void) { int u, v; u = vtop->type.t & (VT_DEFSIGN | VT_UNSIGNED); @@ -2031,10 +2032,6 @@ static void gen_opl(int op) else if (op1 == TOK_GE) op1 = TOK_UGE; gen_op(op1); -#if 0//def TCC_TARGET_I386 - if (op == TOK_NE) { gsym(b); break; } - if (op == TOK_EQ) { gsym(a); break; } -#endif gvtst_set(1, a); gvtst_set(0, b); break; @@ -2216,10 +2213,6 @@ static void gen_opif(int op) { int c1, c2, i, bt; SValue *v1, *v2; -#if defined _MSC_VER && defined __x86_64__ - /* avoid bad optimization with f1 -= f2 for f1:-0.0, f2:0.0 */ - volatile -#endif long double f1, f2; v1 = vtop - 1; @@ -2389,6 +2382,7 @@ static void type_to_str(char *buf, int buf_size, tstr = "double"; if (!(t & VT_LONG)) goto add_tstr; + // fall through case VT_LDOUBLE: tstr = "long double"; add_tstr: @@ -2703,7 +2697,7 @@ static int combine_types(CType *dest, SValue *op1, SValue *op2, int op) } /* generic gen_op: handles types problems */ -ST_FUNC void gen_op(int op) +void gen_op(int op) { int t1, t2, bt1, bt2, t; CType type1, combtype; @@ -2845,7 +2839,7 @@ static void gen_cvt_itof1(int t) vpushi(0); PUT_R_RET(vtop, t); } else { - gen_cvt_itof(t); + gen_cvt_itof(); } } @@ -3012,7 +3006,7 @@ error: if (sf || df) { if (sf && df) { /* convert from fp to fp */ - gen_cvt_ftof(dbt); + gen_cvt_ftof(); } else if (df) { /* convert int to fp */ gen_cvt_itof1(dbt); @@ -3122,7 +3116,7 @@ done: } /* return type size as known at compile time. Put alignment at 'a' */ -ST_FUNC int type_size(CType *type, int *a) +int type_size(CType *type, int *a) { Sym *s; int bt; @@ -3152,11 +3146,7 @@ ST_FUNC int type_size(CType *type, int *a) *a = LDOUBLE_ALIGN; return LDOUBLE_SIZE; } else if (bt == VT_DOUBLE || bt == VT_LLONG) { -#if (defined TCC_TARGET_I386 && !defined TCC_TARGET_PE) *a = 4; -#else - *a = 8; -#endif return 8; } else if (bt == VT_INT || bt == VT_FLOAT) { *a = 4; @@ -3196,7 +3186,7 @@ static inline CType *pointed_type(CType *type) } /* modify type so that its it is a pointer to type. */ -ST_FUNC void mk_pointer(CType *type) +void mk_pointer(CType *type) { Sym *s; s = sym_push(SYM_FIELD, type, 0, -1); @@ -3317,7 +3307,7 @@ static void gen_assign_cast(CType *dt) } /* store vtop in lvalue pushed on stack */ -ST_FUNC void vstore(void) +void vstore(void) { int sbt, dbt, ft, r, size, align, bit_size, bit_pos, delayed_cast; @@ -3369,7 +3359,7 @@ ST_FUNC void vstore(void) gen_cast(&vtop[-1].type); vtop[-1].type.t = (vtop[-1].type.t & ~VT_BTYPE) | (VT_BYTE | VT_UNSIGNED); } - r = adjust_bf(vtop - 1, bit_pos, bit_size); + r = adjust_bf(vtop - 1); if (dbt != VT_BOOL) { gen_cast(&vtop[-1].type); dbt = vtop[-1].type.t & VT_BTYPE; @@ -3463,7 +3453,7 @@ ST_FUNC void vstore(void) } /* post defines POST/PRE add. c is the token ++ or -- */ -ST_FUNC void inc(int post, int c) +void inc(int post, int c) { test_lvalue(); vdup(); /* save lvalue */ @@ -3480,7 +3470,7 @@ ST_FUNC void inc(int post, int c) vpop(); /* if post op, return saved value */ } -ST_FUNC CString* parse_mult_str (const char *msg) +CString* parse_mult_str (const char *msg) { /* read the string */ if (tok != TOK_STR) @@ -3497,7 +3487,7 @@ ST_FUNC CString* parse_mult_str (const char *msg) /* If I is >= 1 and a power of two, returns log2(i)+1. If I is 0 returns 0. */ -ST_FUNC int exact_log2p1(int i) +int exact_log2p1(int i) { int ret; if (!i) @@ -3638,7 +3628,6 @@ redo: case TOK_STDCALL3: ad->f.func_call = FUNC_STDCALL; break; -#ifdef TCC_TARGET_I386 case TOK_REGPARM1: case TOK_REGPARM2: skip('('); @@ -3661,7 +3650,6 @@ redo: case TOK_THISCALL3: ad->f.func_call = FUNC_THISCALL; break; -#endif case TOK_MODE: skip('('); switch(tok) { @@ -4553,7 +4541,7 @@ static inline void convert_parameter_type(CType *pt) } } -ST_FUNC CString* parse_asm_str(void) +CString* parse_asm_str(void) { skip('('); return parse_mult_str("string constant"); @@ -4865,7 +4853,7 @@ static CType *type_decl(CType *type, AttributeDef *ad, int *v, int td) } /* indirection with full error checking and bound check */ -ST_FUNC void indir(void) +void indir(void) { if ((vtop->type.t & VT_BTYPE) != VT_PTR) { if ((vtop->type.t & VT_BTYPE) == VT_FUNC) @@ -4972,12 +4960,14 @@ static void parse_builtin_params(int nc, const char *args) continue; case 'V': type.t = VT_CONSTANT; + // fall through case 'v': type.t |= VT_VOID; mk_pointer (&type); break; case 'S': type.t = VT_CONSTANT; + // fall through case 's': type.t |= char_type.t; mk_pointer (&type); @@ -5132,7 +5122,7 @@ static void parse_atomic(int atok) } } -ST_FUNC void unary(void) +void unary(void) { int n, t, align, size, r; CType type; @@ -6176,7 +6166,7 @@ static void expr_eq(void) } } -ST_FUNC void gexpr(void) +void gexpr(void) { expr_eq(); if (tok == ',') { @@ -6217,7 +6207,7 @@ static inline int64_t expr_const64(void) /* parse an integer constant and return its value. Complain if it doesn't fit 32bit (signed or unsigned). */ -ST_FUNC int expr_const(void) +int expr_const(void) { int c; int64_t wc = expr_const64(); @@ -7680,13 +7670,11 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, p.local_offset = addr + size; if (v) { /* local variable */ -#ifdef CONFIG_TCC_ASM if (ad->asm_label) { int reg = asm_parse_regvar(ad->asm_label); if (reg >= 0) r = (r & ~VT_VALMASK) | reg; } -#endif sym = sym_push(v, type, r, addr); if (ad->cleanup_func) { Sym *cls = sym_push2(&all_cleanups, @@ -7733,8 +7721,6 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, sec = rodata_section; } else if (has_init) { sec = data_section; - /*if (tcc_state->g_debug & 4) - tcc_warning("rw data: %s", get_tok_str(v, 0));*/ } else if (tcc_state->nocommon) sec = bss_section; } diff --git a/libtcc/tccpe.c b/libtcc/tccpe.c deleted file mode 100644 index e39d7a46..00000000 --- a/libtcc/tccpe.c +++ /dev/null @@ -1,2007 +0,0 @@ -/* - * TCCPE.C - PE file output for the Tiny C Compiler - * - * Copyright (c) 2005-2007 grischka - * - * 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" - -#define TCC_OUTPUT_DLL 666 - -#define PE_MERGE_DATA 1 -#define PE_PRINT_SECTIONS 0 - -#ifndef _WIN32 -#define stricmp strcasecmp -#define strnicmp strncasecmp -#include /* chmod() */ -#endif - -#ifdef TCC_TARGET_X86_64 -# define ADDR3264 ULONGLONG -# define PE_IMAGE_REL IMAGE_REL_BASED_DIR64 -# define REL_TYPE_DIRECT R_X86_64_64 -# define R_XXX_THUNKFIX R_X86_64_PC32 -# define R_XXX_RELATIVE R_X86_64_RELATIVE -# define R_XXX_FUNCCALL R_X86_64_PLT32 -# define IMAGE_FILE_MACHINE 0x8664 -# define RSRC_RELTYPE 3 - -#elif defined TCC_TARGET_ARM -# define ADDR3264 DWORD -# define PE_IMAGE_REL IMAGE_REL_BASED_HIGHLOW -# define REL_TYPE_DIRECT R_ARM_ABS32 -# define R_XXX_THUNKFIX R_ARM_ABS32 -# define R_XXX_RELATIVE R_ARM_RELATIVE -# define R_XXX_FUNCCALL R_ARM_PC24 -# define R_XXX_FUNCCALL2 R_ARM_ABS32 -# define IMAGE_FILE_MACHINE 0x01C0 -# define RSRC_RELTYPE 7 /* ??? (not tested) */ - -#elif defined TCC_TARGET_I386 -# define ADDR3264 DWORD -# define PE_IMAGE_REL IMAGE_REL_BASED_HIGHLOW -# define REL_TYPE_DIRECT R_386_32 -# define R_XXX_THUNKFIX R_386_32 -# define R_XXX_RELATIVE R_386_RELATIVE -# define R_XXX_FUNCCALL R_386_PC32 -# define IMAGE_FILE_MACHINE 0x014C -# define RSRC_RELTYPE 7 /* DIR32NB */ - -#endif - -#ifndef IMAGE_NT_SIGNATURE -/* ----------------------------------------------------------- */ -/* definitions below are from winnt.h */ - -typedef unsigned char BYTE; -typedef unsigned short WORD; -typedef unsigned int DWORD; -typedef unsigned long long ULONGLONG; -#pragma pack(push, 1) - -typedef struct _IMAGE_DOS_HEADER { /* DOS .EXE header */ - WORD e_magic; /* Magic number */ - WORD e_cblp; /* Bytes on last page of file */ - WORD e_cp; /* Pages in file */ - WORD e_crlc; /* Relocations */ - WORD e_cparhdr; /* Size of header in paragraphs */ - WORD e_minalloc; /* Minimum extra paragraphs needed */ - WORD e_maxalloc; /* Maximum extra paragraphs needed */ - WORD e_ss; /* Initial (relative) SS value */ - WORD e_sp; /* Initial SP value */ - WORD e_csum; /* Checksum */ - WORD e_ip; /* Initial IP value */ - WORD e_cs; /* Initial (relative) CS value */ - WORD e_lfarlc; /* File address of relocation table */ - WORD e_ovno; /* Overlay number */ - WORD e_res[4]; /* Reserved words */ - WORD e_oemid; /* OEM identifier (for e_oeminfo) */ - WORD e_oeminfo; /* OEM information; e_oemid specific */ - WORD e_res2[10]; /* Reserved words */ - DWORD e_lfanew; /* File address of new exe header */ -} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER; - -#define IMAGE_NT_SIGNATURE 0x00004550 /* PE00 */ -#define SIZE_OF_NT_SIGNATURE 4 - -typedef struct _IMAGE_FILE_HEADER { - WORD Machine; - WORD NumberOfSections; - DWORD TimeDateStamp; - DWORD PointerToSymbolTable; - DWORD NumberOfSymbols; - WORD SizeOfOptionalHeader; - WORD Characteristics; -} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; - - -#define IMAGE_SIZEOF_FILE_HEADER 20 - -typedef struct _IMAGE_DATA_DIRECTORY { - DWORD VirtualAddress; - DWORD Size; -} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY; - - -typedef struct _IMAGE_OPTIONAL_HEADER { - /* Standard fields. */ - WORD Magic; - BYTE MajorLinkerVersion; - BYTE MinorLinkerVersion; - DWORD SizeOfCode; - DWORD SizeOfInitializedData; - DWORD SizeOfUninitializedData; - DWORD AddressOfEntryPoint; - DWORD BaseOfCode; -#ifndef TCC_TARGET_X86_64 - DWORD BaseOfData; -#endif - /* NT additional fields. */ - ADDR3264 ImageBase; - DWORD SectionAlignment; - DWORD FileAlignment; - WORD MajorOperatingSystemVersion; - WORD MinorOperatingSystemVersion; - WORD MajorImageVersion; - WORD MinorImageVersion; - WORD MajorSubsystemVersion; - WORD MinorSubsystemVersion; - DWORD Win32VersionValue; - DWORD SizeOfImage; - DWORD SizeOfHeaders; - DWORD CheckSum; - WORD Subsystem; - WORD DllCharacteristics; - ADDR3264 SizeOfStackReserve; - ADDR3264 SizeOfStackCommit; - ADDR3264 SizeOfHeapReserve; - ADDR3264 SizeOfHeapCommit; - DWORD LoaderFlags; - DWORD NumberOfRvaAndSizes; - IMAGE_DATA_DIRECTORY DataDirectory[16]; -} IMAGE_OPTIONAL_HEADER32, IMAGE_OPTIONAL_HEADER64, IMAGE_OPTIONAL_HEADER; - -#define IMAGE_DIRECTORY_ENTRY_EXPORT 0 /* Export Directory */ -#define IMAGE_DIRECTORY_ENTRY_IMPORT 1 /* Import Directory */ -#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 /* Resource Directory */ -#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 /* Exception Directory */ -#define IMAGE_DIRECTORY_ENTRY_SECURITY 4 /* Security Directory */ -#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 /* Base Relocation Table */ -#define IMAGE_DIRECTORY_ENTRY_DEBUG 6 /* Debug Directory */ -/* IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 (X86 usage) */ -#define IMAGE_DIRECTORY_ENTRY_ARCHITECTURE 7 /* Architecture Specific Data */ -#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 /* RVA of GP */ -#define IMAGE_DIRECTORY_ENTRY_TLS 9 /* TLS Directory */ -#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 /* Load Configuration Directory */ -#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11 /* Bound Import Directory in headers */ -#define IMAGE_DIRECTORY_ENTRY_IAT 12 /* Import Address Table */ -#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13 /* Delay Load Import Descriptors */ -#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14 /* COM Runtime descriptor */ - -/* Section header format. */ -#define IMAGE_SIZEOF_SHORT_NAME 8 - -typedef struct _IMAGE_SECTION_HEADER { - BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; - union { - DWORD PhysicalAddress; - DWORD VirtualSize; - } Misc; - DWORD VirtualAddress; - DWORD SizeOfRawData; - DWORD PointerToRawData; - DWORD PointerToRelocations; - DWORD PointerToLinenumbers; - WORD NumberOfRelocations; - WORD NumberOfLinenumbers; - DWORD Characteristics; -} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER; - -#define IMAGE_SIZEOF_SECTION_HEADER 40 - -typedef struct _IMAGE_EXPORT_DIRECTORY { - DWORD Characteristics; - DWORD TimeDateStamp; - WORD MajorVersion; - WORD MinorVersion; - DWORD Name; - DWORD Base; - DWORD NumberOfFunctions; - DWORD NumberOfNames; - DWORD AddressOfFunctions; - DWORD AddressOfNames; - DWORD AddressOfNameOrdinals; -} IMAGE_EXPORT_DIRECTORY,*PIMAGE_EXPORT_DIRECTORY; - -typedef struct _IMAGE_IMPORT_DESCRIPTOR { - union { - DWORD Characteristics; - DWORD OriginalFirstThunk; - }; - DWORD TimeDateStamp; - DWORD ForwarderChain; - DWORD Name; - DWORD FirstThunk; -} IMAGE_IMPORT_DESCRIPTOR; - -typedef struct _IMAGE_BASE_RELOCATION { - DWORD VirtualAddress; - DWORD SizeOfBlock; -// WORD TypeOffset[1]; -} IMAGE_BASE_RELOCATION; - -#define IMAGE_SIZEOF_BASE_RELOCATION 8 - -#define IMAGE_REL_BASED_ABSOLUTE 0 -#define IMAGE_REL_BASED_HIGH 1 -#define IMAGE_REL_BASED_LOW 2 -#define IMAGE_REL_BASED_HIGHLOW 3 -#define IMAGE_REL_BASED_HIGHADJ 4 -#define IMAGE_REL_BASED_MIPS_JMPADDR 5 -#define IMAGE_REL_BASED_SECTION 6 -#define IMAGE_REL_BASED_REL32 7 -#define IMAGE_REL_BASED_DIR64 10 - -#define IMAGE_SCN_CNT_CODE 0x00000020 -#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 -#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 -#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 -#define IMAGE_SCN_MEM_SHARED 0x10000000 -#define IMAGE_SCN_MEM_EXECUTE 0x20000000 -#define IMAGE_SCN_MEM_READ 0x40000000 -#define IMAGE_SCN_MEM_WRITE 0x80000000 - -#pragma pack(pop) - -/* ----------------------------------------------------------- */ -#endif /* ndef IMAGE_NT_SIGNATURE */ -/* ----------------------------------------------------------- */ - -#ifndef IMAGE_REL_BASED_DIR64 -# define IMAGE_REL_BASED_DIR64 10 -#endif - -#pragma pack(push, 1) -struct pe_header -{ - IMAGE_DOS_HEADER doshdr; - BYTE dosstub[0x40]; - DWORD nt_sig; - IMAGE_FILE_HEADER filehdr; -#ifdef TCC_TARGET_X86_64 - IMAGE_OPTIONAL_HEADER64 opthdr; -#else -#ifdef _WIN64 - IMAGE_OPTIONAL_HEADER32 opthdr; -#else - IMAGE_OPTIONAL_HEADER opthdr; -#endif -#endif -}; - -struct pe_reloc_header { - DWORD offset; - DWORD size; -}; - -struct pe_rsrc_header { - struct _IMAGE_FILE_HEADER filehdr; - struct _IMAGE_SECTION_HEADER sectionhdr; -}; - -struct pe_rsrc_reloc { - DWORD offset; - DWORD size; - WORD type; -}; -#pragma pack(pop) - -/* ------------------------------------------------------------- */ -/* internal temporary structures */ - -enum { - sec_text = 0, - sec_rdata , - sec_data , - sec_bss , - sec_idata , - sec_pdata , - sec_other , - sec_rsrc , - sec_debug , - sec_reloc , - sec_last -}; - -#if 0 -static const DWORD pe_sec_flags[] = { - 0x60000020, /* ".text" , */ - 0xC0000040, /* ".data" , */ - 0xC0000080, /* ".bss" , */ - 0x40000040, /* ".idata" , */ - 0x40000040, /* ".pdata" , */ - 0xE0000060, /* < other > , */ - 0x40000040, /* ".rsrc" , */ - 0x42000802, /* ".stab" , */ - 0x42000040, /* ".reloc" , */ -}; -#endif - -struct section_info { - int cls; - char name[32]; - ADDR3264 sh_addr; - DWORD sh_size; - DWORD pe_flags; - Section *sec; - DWORD data_size; - IMAGE_SECTION_HEADER ish; -}; - -struct import_symbol { - int sym_index; - int iat_index; - int thk_offset; -}; - -struct pe_import_info { - int dll_index; - int sym_count; - struct import_symbol **symbols; -}; - -struct pe_info { - TCCState *s1; - Section *reloc; - Section *thunk; - const char *filename; - int type; - DWORD sizeofheaders; - ADDR3264 imagebase; - const char *start_symbol; - DWORD start_addr; - DWORD imp_offs; - DWORD imp_size; - DWORD iat_offs; - DWORD iat_size; - DWORD exp_offs; - DWORD exp_size; - int subsystem; - DWORD section_align; - DWORD file_align; - struct section_info **sec_info; - int sec_count; - struct pe_import_info **imp_info; - int imp_count; -}; - -#define PE_NUL 0 -#define PE_DLL 1 -#define PE_GUI 2 -#define PE_EXE 3 -#define PE_RUN 4 - -/* --------------------------------------------*/ - -static const char *pe_export_name(TCCState *s1, ElfW(Sym) *sym) -{ - const char *name = (char*)symtab_section->link->data + sym->st_name; - if (s1->leading_underscore && name[0] == '_' && !(sym->st_other & ST_PE_STDCALL)) - return name + 1; - return name; -} - - -static int dynarray_assoc(void **pp, int n, int key) -{ - int i; - for (i = 0; i < n; ++i, ++pp) - if (key == **(int **) pp) - return i; - return -1; -} - -static DWORD umin(DWORD a, DWORD b) -{ - return a < b ? a : b; -} - -static DWORD umax(DWORD a, DWORD b) -{ - return a < b ? b : a; -} - -static DWORD pe_file_align(struct pe_info *pe, DWORD n) -{ - return (n + (pe->file_align - 1)) & ~(pe->file_align - 1); -} - -static ADDR3264 pe_virtual_align(struct pe_info *pe, ADDR3264 n) -{ - return (n + (pe->section_align - 1)) & ~(ADDR3264)(pe->section_align - 1); -} - -static void pe_align_section(Section *s, int a) -{ - int i = s->data_offset & (a-1); - if (i) - section_ptr_add(s, a - i); -} - -static void pe_set_datadir(struct pe_header *hdr, int dir, DWORD addr, DWORD size) -{ - hdr->opthdr.DataDirectory[dir].VirtualAddress = addr; - hdr->opthdr.DataDirectory[dir].Size = size; -} - -struct pe_file { - FILE *op; - DWORD sum; - unsigned pos; -}; - -static int pe_fwrite(const void *data, int len, struct pe_file *pf) -{ - const WORD *p = data; - DWORD sum; - int ret, i; - pf->pos += (ret = fwrite(data, 1, len, pf->op)); - sum = pf->sum; - for (i = len; i > 0; i -= 2) { - sum += (i >= 2) ? *p++ : *(BYTE*)p; - sum = (sum + (sum >> 16)) & 0xFFFF; - } - pf->sum = sum; - return len == ret ? 0 : -1; -} - -static void pe_fpad(struct pe_file *pf, DWORD new_pos) -{ - char buf[256]; - int n, diff = new_pos - pf->pos; - memset(buf, 0, sizeof buf); - while (diff > 0) { - diff -= n = umin(diff, sizeof buf); - fwrite(buf, n, 1, pf->op); - } - pf->pos = new_pos; -} - -/*----------------------------------------------------------------------------*/ -/* PE-DWARF/COFF support - does not work with a mingw-gdb really but works with cv2pdb - (https://github.com/rainers/cv2pdb) */ - -#define N_COFF_SYMS 0 - -static const char dwarf_secs[] = -{ - ".debug_info\0" - ".debug_abbrev\0" - ".debug_line\0" - ".debug_aranges\0" - ".debug_str\0" - ".debug_line_str\0" -}; - -static const unsigned coff_strtab_size = 4 + sizeof dwarf_secs - 1; - -static int pe_put_long_secname(char *secname, const char *name) -{ - const char *d = dwarf_secs; - do { - if (0 == strcmp(d, name)) { - snprintf(secname, 8, "/%d", (int)(d - dwarf_secs + 4)); - return 1; - } - d = strchr(d, 0) + 1; - } while (*d); - return 0; -} - -static void pe_create_pdb(TCCState *s1, const char *exename) -{ - char buf[300]; int r; - snprintf(buf, sizeof buf, "cv2pdb.exe %s", exename); - r = system(buf); - strcpy(tcc_fileextension(strcpy(buf, exename)), ".pdb"); - if (r) { - tcc_error_noabort("could not create '%s'\n(need working cv2pdb from https://github.com/rainers/cv2pdb)", buf); - } else if (s1->verbose) { - printf("<- %s\n", buf); - } -} - -/*----------------------------------------------------------------------------*/ -static int pe_write(struct pe_info *pe) -{ - static const struct pe_header pe_template = { - { - /* IMAGE_DOS_HEADER doshdr */ - 0x5A4D, /*WORD e_magic; Magic number */ - 0x0090, /*WORD e_cblp; Bytes on last page of file */ - 0x0003, /*WORD e_cp; Pages in file */ - 0x0000, /*WORD e_crlc; Relocations */ - - 0x0004, /*WORD e_cparhdr; Size of header in paragraphs */ - 0x0000, /*WORD e_minalloc; Minimum extra paragraphs needed */ - 0xFFFF, /*WORD e_maxalloc; Maximum extra paragraphs needed */ - 0x0000, /*WORD e_ss; Initial (relative) SS value */ - - 0x00B8, /*WORD e_sp; Initial SP value */ - 0x0000, /*WORD e_csum; Checksum */ - 0x0000, /*WORD e_ip; Initial IP value */ - 0x0000, /*WORD e_cs; Initial (relative) CS value */ - 0x0040, /*WORD e_lfarlc; File address of relocation table */ - 0x0000, /*WORD e_ovno; Overlay number */ - {0,0,0,0}, /*WORD e_res[4]; Reserved words */ - 0x0000, /*WORD e_oemid; OEM identifier (for e_oeminfo) */ - 0x0000, /*WORD e_oeminfo; OEM information; e_oemid specific */ - {0,0,0,0,0,0,0,0,0,0}, /*WORD e_res2[10]; Reserved words */ - 0x00000080 /*DWORD e_lfanew; File address of new exe header */ - },{ - /* BYTE dosstub[0x40] */ - /* 14 code bytes + "This program cannot be run in DOS mode.\r\r\n$" + 6 * 0x00 */ - 0x0e,0x1f,0xba,0x0e,0x00,0xb4,0x09,0xcd,0x21,0xb8,0x01,0x4c,0xcd,0x21,0x54,0x68, - 0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,0x61,0x6d,0x20,0x63,0x61,0x6e,0x6e,0x6f, - 0x74,0x20,0x62,0x65,0x20,0x72,0x75,0x6e,0x20,0x69,0x6e,0x20,0x44,0x4f,0x53,0x20, - 0x6d,0x6f,0x64,0x65,0x2e,0x0d,0x0d,0x0a,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - }, - 0x00004550, /* DWORD nt_sig = IMAGE_NT_SIGNATURE */ - { - /* IMAGE_FILE_HEADER filehdr */ - IMAGE_FILE_MACHINE, /*WORD Machine; */ - 0x0003, /*WORD NumberOfSections; */ - 0x00000000, /*DWORD TimeDateStamp; */ - 0x00000000, /*DWORD PointerToSymbolTable; */ - 0x00000000, /*DWORD NumberOfSymbols; */ -#if defined(TCC_TARGET_X86_64) - 0x00F0, /*WORD SizeOfOptionalHeader; */ - 0x022F /*WORD Characteristics; */ -#define CHARACTERISTICS_DLL 0x222E -#elif defined(TCC_TARGET_I386) - 0x00E0, /*WORD SizeOfOptionalHeader; */ - 0x030F /*WORD Characteristics; */ -#define CHARACTERISTICS_DLL 0x230E -#elif defined(TCC_TARGET_ARM) - 0x00E0, /*WORD SizeOfOptionalHeader; */ - 0x010F, /*WORD Characteristics; */ -#define CHARACTERISTICS_DLL 0x230F -#endif -},{ - /* IMAGE_OPTIONAL_HEADER opthdr */ - /* Standard fields. */ -#ifdef TCC_TARGET_X86_64 - 0x020B, /*WORD Magic; */ -#else - 0x010B, /*WORD Magic; */ -#endif - 0x06, /*BYTE MajorLinkerVersion; */ - 0x00, /*BYTE MinorLinkerVersion; */ - 0x00000000, /*DWORD SizeOfCode; */ - 0x00000000, /*DWORD SizeOfInitializedData; */ - 0x00000000, /*DWORD SizeOfUninitializedData; */ - 0x00000000, /*DWORD AddressOfEntryPoint; */ - 0x00000000, /*DWORD BaseOfCode; */ -#ifndef TCC_TARGET_X86_64 - 0x00000000, /*DWORD BaseOfData; */ -#endif - /* NT additional fields. */ -#if defined(TCC_TARGET_ARM) - 0x00100000, /*DWORD ImageBase; */ -#else - 0x00400000, /*DWORD ImageBase; */ -#endif - 0x00001000, /*DWORD SectionAlignment; */ - 0x00000200, /*DWORD FileAlignment; */ - 0x0004, /*WORD MajorOperatingSystemVersion; */ - 0x0000, /*WORD MinorOperatingSystemVersion; */ - 0x0000, /*WORD MajorImageVersion; */ - 0x0000, /*WORD MinorImageVersion; */ - 0x0004, /*WORD MajorSubsystemVersion; */ - 0x0000, /*WORD MinorSubsystemVersion; */ - 0x00000000, /*DWORD Win32VersionValue; */ - 0x00000000, /*DWORD SizeOfImage; */ - 0x00000200, /*DWORD SizeOfHeaders; */ - 0x00000000, /*DWORD CheckSum; */ - 0x0002, /*WORD Subsystem; */ - 0x0000, /*WORD DllCharacteristics; */ - 0x00100000, /*DWORD SizeOfStackReserve; */ - 0x00001000, /*DWORD SizeOfStackCommit; */ - 0x00100000, /*DWORD SizeOfHeapReserve; */ - 0x00001000, /*DWORD SizeOfHeapCommit; */ - 0x00000000, /*DWORD LoaderFlags; */ - 0x00000010, /*DWORD NumberOfRvaAndSizes; */ - - /* IMAGE_DATA_DIRECTORY DataDirectory[16]; */ - {{0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, - {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}} - }}; - - struct pe_header pe_header = pe_template; - - int i; - struct pe_file pf = {0}; - DWORD file_offset; - struct section_info *si; - IMAGE_SECTION_HEADER *psh; - TCCState *s1 = pe->s1; - int need_strtab = 0; - - pf.op = fopen(pe->filename, "wb"); - if (NULL == pf.op) - return tcc_error_noabort("could not write '%s': %s", pe->filename, strerror(errno)); - - pe->sizeofheaders = pe_file_align(pe, - sizeof (struct pe_header) - + pe->sec_count * sizeof (IMAGE_SECTION_HEADER) - ); - - file_offset = pe->sizeofheaders; - - if (2 == pe->s1->verbose) - printf("-------------------------------" - "\n virt file size section" "\n"); - for (i = 0; i < pe->sec_count; ++i) { - DWORD addr, size; - const char *sh_name; - - si = pe->sec_info[i]; - sh_name = si->name; - addr = si->sh_addr - pe->imagebase; - size = si->sh_size; - psh = &si->ish; - - if (2 == pe->s1->verbose) - printf("%6x %6x %6x %s\n", - (unsigned)addr, (unsigned)file_offset, (unsigned)size, sh_name); - - switch (si->cls) { - case sec_text: - if (!pe_header.opthdr.BaseOfCode) - pe_header.opthdr.BaseOfCode = addr; - break; - - case sec_data: -#ifndef TCC_TARGET_X86_64 - if (!pe_header.opthdr.BaseOfData) - pe_header.opthdr.BaseOfData = addr; -#endif - break; - - case sec_bss: - break; - - case sec_reloc: - pe_set_datadir(&pe_header, IMAGE_DIRECTORY_ENTRY_BASERELOC, addr, size); - break; - - case sec_rsrc: - pe_set_datadir(&pe_header, IMAGE_DIRECTORY_ENTRY_RESOURCE, addr, size); - break; - - case sec_pdata: - pe_set_datadir(&pe_header, IMAGE_DIRECTORY_ENTRY_EXCEPTION, addr, size); - break; - } - - if (pe->imp_size) { - pe_set_datadir(&pe_header, IMAGE_DIRECTORY_ENTRY_IMPORT, - pe->imp_offs, pe->imp_size); - pe_set_datadir(&pe_header, IMAGE_DIRECTORY_ENTRY_IAT, - pe->iat_offs, pe->iat_size); - } - if (pe->exp_size) { - pe_set_datadir(&pe_header, IMAGE_DIRECTORY_ENTRY_EXPORT, - pe->exp_offs, pe->exp_size); - } - - memcpy(psh->Name, sh_name, umin(strlen(sh_name), sizeof psh->Name)); - if (si->cls == sec_debug) - need_strtab += pe_put_long_secname((char*)psh->Name, sh_name); - - psh->Characteristics = si->pe_flags; - psh->VirtualAddress = addr; - psh->Misc.VirtualSize = size; - pe_header.opthdr.SizeOfImage = - umax(pe_virtual_align(pe, size + addr), pe_header.opthdr.SizeOfImage); - - if (si->data_size) { - psh->PointerToRawData = file_offset; - file_offset = pe_file_align(pe, file_offset + si->data_size); - psh->SizeOfRawData = file_offset - psh->PointerToRawData; - if (si->cls == sec_text) - pe_header.opthdr.SizeOfCode += psh->SizeOfRawData; - else - pe_header.opthdr.SizeOfInitializedData += psh->SizeOfRawData; - } - } - - //pe_header.filehdr.TimeDateStamp = time(NULL); - pe_header.filehdr.NumberOfSections = pe->sec_count; - pe_header.opthdr.AddressOfEntryPoint = pe->start_addr; - pe_header.opthdr.SizeOfHeaders = pe->sizeofheaders; - pe_header.opthdr.ImageBase = pe->imagebase; - pe_header.opthdr.Subsystem = pe->subsystem; - if (pe->s1->pe_stack_size) - pe_header.opthdr.SizeOfStackReserve = pe->s1->pe_stack_size; - if (PE_DLL == pe->type) - pe_header.filehdr.Characteristics = CHARACTERISTICS_DLL; - pe_header.filehdr.Characteristics |= pe->s1->pe_characteristics; - if (need_strtab) { - pe_header.filehdr.PointerToSymbolTable = file_offset; - pe_header.filehdr.NumberOfSymbols = N_COFF_SYMS; - } - pe_fwrite(&pe_header, sizeof pe_header, &pf); - for (i = 0; i < pe->sec_count; ++i) - pe_fwrite(&pe->sec_info[i]->ish, sizeof(IMAGE_SECTION_HEADER), &pf); - - file_offset = pe->sizeofheaders; - for (i = 0; i < pe->sec_count; ++i) { - Section *s; - si = pe->sec_info[i]; - if (!si->data_size) - continue; - for (s = si->sec; s; s = s->prev) { - pe_fpad(&pf, file_offset); - pe_fwrite(s->data, s->data_offset, &pf); - if (s->prev) - file_offset += s->prev->sh_addr - s->sh_addr; - } - file_offset = si->ish.PointerToRawData + si->ish.SizeOfRawData; - pe_fpad(&pf, file_offset); - } - - if (need_strtab) { - /* create a tiny COFF string table with the long section names */ - pe_fwrite(&coff_strtab_size, sizeof coff_strtab_size, &pf); - pe_fwrite(dwarf_secs, sizeof dwarf_secs - 1, &pf); - file_offset = pf.pos; - } - - pf.sum += file_offset; - fseek(pf.op, offsetof(struct pe_header, opthdr.CheckSum), SEEK_SET); - pe_fwrite(&pf.sum, sizeof (DWORD), &pf); - - fclose (pf.op); -#ifndef _WIN32 - chmod(pe->filename, 0777); -#endif - - if (2 == pe->s1->verbose) - printf("-------------------------------\n"); - if (pe->s1->verbose) - printf("<- %s (%u bytes)\n", pe->filename, (unsigned)file_offset); - - if (s1->do_debug & 16) - pe_create_pdb(s1, pe->filename); - return 0; -} - -/*----------------------------------------------------------------------------*/ - -static struct import_symbol *pe_add_import(struct pe_info *pe, int sym_index) -{ - int i; - int dll_index; - struct pe_import_info *p; - struct import_symbol *s; - ElfW(Sym) *isym; - - isym = (ElfW(Sym) *)pe->s1->dynsymtab_section->data + sym_index; - dll_index = isym->st_size; - - i = dynarray_assoc ((void**)pe->imp_info, pe->imp_count, dll_index); - if (-1 != i) { - p = pe->imp_info[i]; - goto found_dll; - } - p = tcc_mallocz(sizeof *p); - p->dll_index = dll_index; - dynarray_add(&pe->imp_info, &pe->imp_count, p); - -found_dll: - i = dynarray_assoc ((void**)p->symbols, p->sym_count, sym_index); - if (-1 != i) - return p->symbols[i]; - - s = tcc_mallocz(sizeof *s); - dynarray_add(&p->symbols, &p->sym_count, s); - s->sym_index = sym_index; - return s; -} - -static void pe_free_imports(struct pe_info *pe) -{ - int i; - for (i = 0; i < pe->imp_count; ++i) { - struct pe_import_info *p = pe->imp_info[i]; - dynarray_reset(&p->symbols, &p->sym_count); - } - dynarray_reset(&pe->imp_info, &pe->imp_count); -} - -/*----------------------------------------------------------------------------*/ -static void pe_build_imports(struct pe_info *pe) -{ - int thk_ptr, ent_ptr, dll_ptr, sym_cnt, i; - DWORD rva_base = pe->thunk->sh_addr - pe->imagebase; - int ndlls = pe->imp_count; - TCCState *s1 = pe->s1; - - for (sym_cnt = i = 0; i < ndlls; ++i) - sym_cnt += pe->imp_info[i]->sym_count; - - if (0 == sym_cnt) - return; - - pe_align_section(pe->thunk, 16); - pe->imp_size = (ndlls + 1) * sizeof(IMAGE_IMPORT_DESCRIPTOR); - pe->iat_size = (sym_cnt + ndlls) * sizeof(ADDR3264); - dll_ptr = pe->thunk->data_offset; - thk_ptr = dll_ptr + pe->imp_size; - ent_ptr = thk_ptr + pe->iat_size; - pe->imp_offs = dll_ptr + rva_base; - pe->iat_offs = thk_ptr + rva_base; - section_ptr_add(pe->thunk, pe->imp_size + 2*pe->iat_size); - - for (i = 0; i < pe->imp_count; ++i) { - IMAGE_IMPORT_DESCRIPTOR *hdr; - int k, n, dllindex; - ADDR3264 v; - struct pe_import_info *p = pe->imp_info[i]; - const char *name; - DLLReference *dllref; - - dllindex = p->dll_index; - if (dllindex) - name = (dllref = pe->s1->loaded_dlls[dllindex-1])->name; - else - name = "", dllref = NULL; - - /* put the dll name into the import header */ - v = put_elf_str(pe->thunk, name); - hdr = (IMAGE_IMPORT_DESCRIPTOR*)(pe->thunk->data + dll_ptr); - hdr->FirstThunk = thk_ptr + rva_base; - hdr->OriginalFirstThunk = ent_ptr + rva_base; - hdr->Name = v + rva_base; - - for (k = 0, n = p->sym_count; k <= n; ++k) { - if (k < n) { - int iat_index = p->symbols[k]->iat_index; - int sym_index = p->symbols[k]->sym_index; - ElfW(Sym) *imp_sym = (ElfW(Sym) *)pe->s1->dynsymtab_section->data + sym_index; - const char *name = (char*)pe->s1->dynsymtab_section->link->data + imp_sym->st_name; - int ordinal; - - /* patch symbol (and possibly its underscored alias) */ - do { - ElfW(Sym) *esym = (ElfW(Sym) *)symtab_section->data + iat_index; - iat_index = esym->st_value; - esym->st_value = thk_ptr; - esym->st_shndx = pe->thunk->sh_num; - } while (iat_index); - - if (dllref) - v = 0, ordinal = imp_sym->st_value; /* ordinal from pe_load_def */ - else - ordinal = 0, v = imp_sym->st_value; /* address from tcc_add_symbol() */ - -#ifdef TCC_IS_NATIVE - if (pe->type == PE_RUN) { - if (dllref) { - if ( !dllref->handle ) - dllref->handle = LoadLibraryA(dllref->name); - v = (ADDR3264)GetProcAddress(dllref->handle, ordinal?(char*)0+ordinal:name); - } - if (!v) - tcc_error_noabort("could not resolve symbol '%s'", name); - } else -#endif - if (ordinal) { - v = ordinal | (ADDR3264)1 << (sizeof(ADDR3264)*8 - 1); - } else { - v = pe->thunk->data_offset + rva_base; - section_ptr_add(pe->thunk, sizeof(WORD)); /* hint, not used */ - put_elf_str(pe->thunk, name); - } - - } else { - v = 0; /* last entry is zero */ - } - - *(ADDR3264*)(pe->thunk->data+thk_ptr) = - *(ADDR3264*)(pe->thunk->data+ent_ptr) = v; - thk_ptr += sizeof (ADDR3264); - ent_ptr += sizeof (ADDR3264); - } - dll_ptr += sizeof(IMAGE_IMPORT_DESCRIPTOR); - } -} - -/* ------------------------------------------------------------- */ - -struct pe_sort_sym -{ - int index; - const char *name; -}; - -static int sym_cmp(const void *va, const void *vb) -{ - const char *ca = (*(struct pe_sort_sym**)va)->name; - const char *cb = (*(struct pe_sort_sym**)vb)->name; - return strcmp(ca, cb); -} - -static void pe_build_exports(struct pe_info *pe) -{ - ElfW(Sym) *sym; - int sym_index, sym_end; - DWORD rva_base, base_o, func_o, name_o, ord_o, str_o; - IMAGE_EXPORT_DIRECTORY *hdr; - int sym_count, ord; - struct pe_sort_sym **sorted, *p; - TCCState *s1 = pe->s1; - - FILE *op; - char buf[260]; - const char *dllname; - const char *name; - - rva_base = pe->thunk->sh_addr - pe->imagebase; - sym_count = 0, sorted = NULL, op = NULL; - - sym_end = symtab_section->data_offset / sizeof(ElfW(Sym)); - for (sym_index = 1; sym_index < sym_end; ++sym_index) { - sym = (ElfW(Sym)*)symtab_section->data + sym_index; - name = pe_export_name(pe->s1, sym); - if (sym->st_other & ST_PE_EXPORT) { - p = tcc_malloc(sizeof *p); - p->index = sym_index; - p->name = name; - dynarray_add(&sorted, &sym_count, p); - } -#if 0 - if (sym->st_other & ST_PE_EXPORT) - printf("export: %s\n", name); - if (sym->st_other & ST_PE_STDCALL) - printf("stdcall: %s\n", name); -#endif - } - - if (0 == sym_count) - return; - - qsort (sorted, sym_count, sizeof *sorted, sym_cmp); - - pe_align_section(pe->thunk, 16); - dllname = tcc_basename(pe->filename); - - base_o = pe->thunk->data_offset; - func_o = base_o + sizeof(IMAGE_EXPORT_DIRECTORY); - name_o = func_o + sym_count * sizeof (DWORD); - ord_o = name_o + sym_count * sizeof (DWORD); - str_o = ord_o + sym_count * sizeof(WORD); - - hdr = section_ptr_add(pe->thunk, str_o - base_o); - hdr->Characteristics = 0; - hdr->Base = 1; - hdr->NumberOfFunctions = sym_count; - hdr->NumberOfNames = sym_count; - hdr->AddressOfFunctions = func_o + rva_base; - hdr->AddressOfNames = name_o + rva_base; - hdr->AddressOfNameOrdinals = ord_o + rva_base; - hdr->Name = str_o + rva_base; - put_elf_str(pe->thunk, dllname); - -#if 1 - /* automatically write exports to .def */ - pstrcpy(buf, sizeof buf, pe->filename); - strcpy(tcc_fileextension(buf), ".def"); - op = fopen(buf, "wb"); - if (NULL == op) { - tcc_error_noabort("could not create '%s': %s", buf, strerror(errno)); - } else { - fprintf(op, "LIBRARY %s\n\nEXPORTS\n", dllname); - if (pe->s1->verbose) - printf("<- %s (%d symbol%s)\n", buf, sym_count, &"s"[sym_count < 2]); - } -#endif - - for (ord = 0; ord < sym_count; ++ord) - { - p = sorted[ord], sym_index = p->index, name = p->name; - /* insert actual address later in relocate_sections() */ - put_elf_reloc(symtab_section, pe->thunk, - func_o, R_XXX_RELATIVE, sym_index); - *(DWORD*)(pe->thunk->data + name_o) - = pe->thunk->data_offset + rva_base; - *(WORD*)(pe->thunk->data + ord_o) - = ord; - put_elf_str(pe->thunk, name); - func_o += sizeof (DWORD); - name_o += sizeof (DWORD); - ord_o += sizeof (WORD); - if (op) - fprintf(op, "%s\n", name); - } - - pe->exp_offs = base_o + rva_base; - pe->exp_size = pe->thunk->data_offset - base_o; - dynarray_reset(&sorted, &sym_count); - if (op) - fclose(op); -} - -/* ------------------------------------------------------------- */ -static void pe_build_reloc (struct pe_info *pe) -{ - DWORD offset, block_ptr, sh_addr, addr; - int count, i; - ElfW_Rel *rel, *rel_end; - Section *s = NULL, *sr; - struct pe_reloc_header *hdr; - - sh_addr = offset = block_ptr = count = i = 0; - rel = rel_end = NULL; - - for(;;) { - if (rel < rel_end) { - int type = ELFW(R_TYPE)(rel->r_info); - addr = rel->r_offset + sh_addr; - ++ rel; - if (type != REL_TYPE_DIRECT) - continue; - if (count == 0) { /* new block */ - block_ptr = pe->reloc->data_offset; - section_ptr_add(pe->reloc, sizeof(struct pe_reloc_header)); - offset = addr & 0xFFFFFFFF<<12; - } - if ((addr -= offset) < (1<<12)) { /* one block spans 4k addresses */ - WORD *wp = section_ptr_add(pe->reloc, sizeof (WORD)); - *wp = addr | PE_IMAGE_REL<<12; - ++count; - continue; - } - -- rel; - - } else if (s) { - sr = s->reloc; - if (sr) { - rel = (ElfW_Rel *)sr->data; - rel_end = (ElfW_Rel *)(sr->data + sr->data_offset); - sh_addr = s->sh_addr; - } - s = s->prev; - continue; - - } else if (i < pe->sec_count) { - s = pe->sec_info[i]->sec, ++i; - continue; - - } else if (!count) - break; - - /* fill the last block and ready for a new one */ - if (count & 1) /* align for DWORDS */ - section_ptr_add(pe->reloc, sizeof(WORD)), ++count; - hdr = (struct pe_reloc_header *)(pe->reloc->data + block_ptr); - hdr -> offset = offset - pe->imagebase; - hdr -> size = count * sizeof(WORD) + sizeof(struct pe_reloc_header); - count = 0; - } -} - -/* ------------------------------------------------------------- */ -static int pe_section_class(Section *s) -{ - int type, flags; - const char *name; - type = s->sh_type; - flags = s->sh_flags; - name = s->name; - - if (0 == memcmp(name, ".stab", 5) || 0 == memcmp(name, ".debug_", 7)) { - return sec_debug; - } else if (flags & SHF_ALLOC) { - if (type == SHT_PROGBITS - || type == SHT_INIT_ARRAY - || type == SHT_FINI_ARRAY) { - if (flags & SHF_EXECINSTR) - return sec_text; - if (flags & SHF_WRITE) - return sec_data; - if (0 == strcmp(name, ".rsrc")) - return sec_rsrc; - if (0 == strcmp(name, ".iedat")) - return sec_idata; - if (0 == strcmp(name, ".pdata")) - return sec_pdata; - return sec_rdata; - } else if (type == SHT_NOBITS) { - return sec_bss; - } - return sec_other; - } else { - if (0 == strcmp(name, ".reloc")) - return sec_reloc; - } - return sec_last; -} - -static int pe_assign_addresses (struct pe_info *pe) -{ - int i, k, n, c, nbs; - ADDR3264 addr; - int *sec_order, *sec_cls; - struct section_info *si; - Section *s; - TCCState *s1 = pe->s1; - - if (PE_DLL == pe->type) - pe->reloc = new_section(pe->s1, ".reloc", SHT_PROGBITS, 0); - //pe->thunk = new_section(pe->s1, ".iedat", SHT_PROGBITS, SHF_ALLOC); - - nbs = s1->nb_sections; - sec_order = tcc_mallocz(2 * sizeof (int) * nbs); - sec_cls = sec_order + nbs; - for (i = 1; i < nbs; ++i) { - s = s1->sections[i]; - k = pe_section_class(s); - for (n = i; n > 1 && k < (c = sec_cls[n - 1]); --n) - sec_cls[n] = c, sec_order[n] = sec_order[n - 1]; - sec_cls[n] = k, sec_order[n] = i; - } - si = NULL; - addr = pe->imagebase + 1; - - for (i = 1; (c = sec_cls[i]) < sec_last; ++i) { - s = s1->sections[sec_order[i]]; - - if (PE_MERGE_DATA && c == sec_bss) - c = sec_data; - - if (si && c == si->cls && c != sec_debug) { - /* merge with previous section */ - s->sh_addr = addr = ((addr - 1) | (16 - 1)) + 1; - } else { - si = NULL; - s->sh_addr = addr = pe_virtual_align(pe, addr); - } - - if (NULL == pe->thunk - && c == (data_section == rodata_section ? sec_data : sec_rdata)) - pe->thunk = s; - - if (s == pe->thunk) { - pe_build_imports(pe); - pe_build_exports(pe); - } - if (s == pe->reloc) - pe_build_reloc (pe); - - if (0 == s->data_offset) - continue; - - if (si) - goto add_section; - - si = tcc_mallocz(sizeof *si); - dynarray_add(&pe->sec_info, &pe->sec_count, si); - - strcpy(si->name, s->name); - si->cls = c; - si->sh_addr = addr; - - si->pe_flags = IMAGE_SCN_MEM_READ; - if (s->sh_flags & SHF_EXECINSTR) - si->pe_flags |= IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_CNT_CODE; - else if (s->sh_type == SHT_NOBITS) - si->pe_flags |= IMAGE_SCN_CNT_UNINITIALIZED_DATA; - else - si->pe_flags |= IMAGE_SCN_CNT_INITIALIZED_DATA; - if (s->sh_flags & SHF_WRITE) - si->pe_flags |= IMAGE_SCN_MEM_WRITE; - if (0 == (s->sh_flags & SHF_ALLOC)) - si->pe_flags |= IMAGE_SCN_MEM_DISCARDABLE; - -add_section: - addr += s->data_offset; - si->sh_size = addr - si->sh_addr; - if (s->sh_type != SHT_NOBITS) { - Section **ps = &si->sec; - while (*ps) - ps = &(*ps)->prev; - *ps = s, s->prev = NULL; - si->data_size = si->sh_size; - } - //printf("%08x %05x %08x %s\n", si->sh_addr, si->sh_size, si->pe_flags, s->name); - } -#if 0 - for (i = 1; i < nbs; ++i) { - Section *s = s1->sections[sec_order[i]]; - int type = s->sh_type; - int flags = s->sh_flags; - printf("section %-16s %-10s %p %04x %s,%s,%s\n", - s->name, - type == SHT_PROGBITS ? "progbits" : - type == SHT_INIT_ARRAY ? "initarr" : - type == SHT_FINI_ARRAY ? "finiarr" : - type == SHT_NOBITS ? "nobits" : - type == SHT_SYMTAB ? "symtab" : - type == SHT_STRTAB ? "strtab" : - type == SHT_RELX ? "rel" : "???", - s->sh_addr, - (unsigned)s->data_offset, - flags & SHF_ALLOC ? "alloc" : "", - flags & SHF_WRITE ? "write" : "", - flags & SHF_EXECINSTR ? "exec" : "" - ); - fflush(stdout); - } - s1->verbose = 2; -#endif - tcc_free(sec_order); - return 0; -} - -/*----------------------------------------------------------------------------*/ -static int pe_check_symbols(struct pe_info *pe) -{ - int sym_index, sym_end; - int ret = 0; - TCCState *s1 = pe->s1; - - pe_align_section(text_section, 8); - - sym_end = symtab_section->data_offset / sizeof(ElfW(Sym)); - for (sym_index = 1; sym_index < sym_end; ++sym_index) { - ElfW(Sym) *sym = (ElfW(Sym) *)symtab_section->data + sym_index; - if (sym->st_shndx == SHN_UNDEF) { - const char *name = (char*)symtab_section->link->data + sym->st_name; - unsigned type = ELFW(ST_TYPE)(sym->st_info); - int imp_sym; - struct import_symbol *is; - - int _imp_, n; - char buffer[200]; - const char *s, *p; - - n = _imp_ = 0; - do { - s = pe_export_name(s1, sym); - if (n) { - /* second try: */ - if (sym->st_other & ST_PE_STDCALL) { - /* try w/0 stdcall deco (windows API convention) */ - p = strrchr(s, '@'); - if (!p || s[0] != '_') - break; - strcpy(buffer, s+1)[p-s-1] = 0, s = buffer; - } else if (s[0] != '_') { /* try non-ansi function */ - buffer[0] = '_', strcpy(buffer + 1, s), s = buffer; - } else if (0 == memcmp(s, "_imp__", 6)) { /* mingw 3.7 */ - s += 6, _imp_ = 1; - } else if (0 == memcmp(s, "__imp_", 6)) { /* mingw 2.0 */ - s += 6, _imp_ = 1; - } else { - break; - } - } - imp_sym = find_elf_sym(s1->dynsymtab_section, s); - } while (0 == imp_sym && ++n < 2); - - //printf("pe_find_export (%d) %4x %s\n", n, imp_sym, name); - if (0 == imp_sym) - continue; /* will throw the 'undefined' error in relocate_syms() */ - - is = pe_add_import(pe, imp_sym); - - if (type == STT_FUNC - /* symbols from assembler often have no type */ - || type == STT_NOTYPE) { - unsigned offset = is->thk_offset; - if (offset) { - /* got aliased symbol, like stricmp and _stricmp */ - } else { - unsigned char *p; - - /* add a helper symbol, will be patched later in - pe_build_imports */ - sprintf(buffer, "IAT.%s", name); - is->iat_index = put_elf_sym( - symtab_section, 0, sizeof(DWORD), - ELFW(ST_INFO)(STB_LOCAL, STT_OBJECT), - 0, SHN_UNDEF, buffer); - - offset = text_section->data_offset; - is->thk_offset = offset; - - /* add the 'jmp IAT[x]' instruction */ -#ifdef TCC_TARGET_ARM - p = section_ptr_add(text_section, 8+4); // room for code and address - write32le(p + 0, 0xE59FC000); // arm code ldr ip, [pc] ; PC+8+0 = 0001xxxx - write32le(p + 4, 0xE59CF000); // arm code ldr pc, [ip] - put_elf_reloc(symtab_section, text_section, - offset + 8, R_XXX_THUNKFIX, is->iat_index); // offset to IAT position -#else - p = section_ptr_add(text_section, 8); - write16le(p, 0x25FF); -#ifdef TCC_TARGET_X86_64 - write32le(p + 2, (DWORD)-4); -#endif - put_elf_reloc(symtab_section, text_section, - offset + 2, R_XXX_THUNKFIX, is->iat_index); -#endif - } - /* tcc_realloc might have altered sym's address */ - sym = (ElfW(Sym) *)symtab_section->data + sym_index; - /* patch the original symbol */ - sym->st_value = offset; - sym->st_shndx = text_section->sh_num; - sym->st_other &= ~ST_PE_EXPORT; /* do not export */ - - } else { /* STT_OBJECT */ - if (0 == _imp_ && 0 == (sym->st_other & ST_PE_IMPORT)) - ret = tcc_error_noabort("symbol '%s' is missing __declspec(dllimport)", name); - /* original symbol will be patched later in pe_build_imports */ - sym->st_value = is->iat_index; /* chain potential alias */ - is->iat_index = sym_index; - } - - } else if (pe->s1->rdynamic - && ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) { - /* if -rdynamic option, then export all non local symbols */ - sym->st_other |= ST_PE_EXPORT; - } - } - return ret; -} - -/*----------------------------------------------------------------------------*/ -#if PE_PRINT_SECTIONS -static void pe_print_section(FILE * f, Section * s) -{ - /* just if you're curious */ - BYTE *p, *e, b; - int i, n, l, m; - p = s->data; - e = s->data + s->data_offset; - l = e - p; - - fprintf(f, "section \"%s\"", s->name); - if (s->link) - fprintf(f, "\nlink \"%s\"", s->link->name); - if (s->reloc) - fprintf(f, "\nreloc \"%s\"", s->reloc->name); - fprintf(f, "\nv_addr %08X", (unsigned)s->sh_addr); - fprintf(f, "\ncontents %08X", (unsigned)l); - fprintf(f, "\n\n"); - - if (s->sh_type == SHT_NOBITS) - return; - - if (0 == l) - return; - - if (s->sh_type == SHT_SYMTAB) - m = sizeof(ElfW(Sym)); - else if (s->sh_type == SHT_RELX) - m = sizeof(ElfW_Rel); - else - m = 16; - - fprintf(f, "%-8s", "offset"); - for (i = 0; i < m; ++i) - fprintf(f, " %02x", i); - n = 56; - - if (s->sh_type == SHT_SYMTAB || s->sh_type == SHT_RELX) { - const char *fields1[] = { - "name", - "value", - "size", - "bind", - "type", - "other", - "shndx", - NULL - }; - - const char *fields2[] = { - "offs", - "type", - "symb", - NULL - }; - - const char **p; - - if (s->sh_type == SHT_SYMTAB) - p = fields1, n = 106; - else - p = fields2, n = 58; - - for (i = 0; p[i]; ++i) - fprintf(f, "%6s", p[i]); - fprintf(f, " symbol"); - } - - fprintf(f, "\n"); - for (i = 0; i < n; ++i) - fprintf(f, "-"); - fprintf(f, "\n"); - - for (i = 0; i < l;) - { - fprintf(f, "%08X", i); - for (n = 0; n < m; ++n) { - if (n + i < l) - fprintf(f, " %02X", p[i + n]); - else - fprintf(f, " "); - } - - if (s->sh_type == SHT_SYMTAB) { - ElfW(Sym) *sym = (ElfW(Sym) *) (p + i); - const char *name = s->link->data + sym->st_name; - fprintf(f, " %04X %04X %04X %02X %02X %02X %04X \"%s\"", - (unsigned)sym->st_name, - (unsigned)sym->st_value, - (unsigned)sym->st_size, - (unsigned)ELFW(ST_BIND)(sym->st_info), - (unsigned)ELFW(ST_TYPE)(sym->st_info), - (unsigned)sym->st_other, - (unsigned)sym->st_shndx, - name); - - } else if (s->sh_type == SHT_RELX) { - ElfW_Rel *rel = (ElfW_Rel *) (p + i); - ElfW(Sym) *sym = - (ElfW(Sym) *) s->link->data + ELFW(R_SYM)(rel->r_info); - const char *name = s->link->link->data + sym->st_name; - fprintf(f, " %04X %02X %04X \"%s\"", - (unsigned)rel->r_offset, - (unsigned)ELFW(R_TYPE)(rel->r_info), - (unsigned)ELFW(R_SYM)(rel->r_info), - name); - } else { - fprintf(f, " "); - for (n = 0; n < m; ++n) { - if (n + i < l) { - b = p[i + n]; - if (b < 32 || b >= 127) - b = '.'; - fprintf(f, "%c", b); - } - } - } - i += m; - fprintf(f, "\n"); - } - fprintf(f, "\n\n"); -} - -static void pe_print_sections(TCCState *s1, const char *fname) -{ - Section *s; - FILE *f; - int i; - f = fopen(fname, "w"); - for (i = 1; i < s1->nb_sections; ++i) { - s = s1->sections[i]; - pe_print_section(f, s); - } - pe_print_section(f, s1->dynsymtab_section); - fclose(f); -} -#endif - -/* ------------------------------------------------------------- */ - -ST_FUNC int pe_putimport(TCCState *s1, int dllindex, const char *name, addr_t value) -{ - return set_elf_sym( - s1->dynsymtab_section, - value, - dllindex, /* st_size */ - ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), - 0, - value ? SHN_ABS : SHN_UNDEF, - name - ); -} - -static int read_mem(int fd, unsigned offset, void *buffer, unsigned len) -{ - lseek(fd, offset, SEEK_SET); - return len == read(fd, buffer, len); -} - -/* ------------------------------------------------------------- */ - -static int get_dllexports(int fd, char **pp) -{ - int i, k, l, n, n0, ret; - char *p; - - IMAGE_SECTION_HEADER ish; - IMAGE_EXPORT_DIRECTORY ied; - IMAGE_DOS_HEADER dh; - IMAGE_FILE_HEADER ih; - DWORD sig, ref, addr; - DWORD *namep = NULL, p0 = 0, p1; - - int pef_hdroffset, opt_hdroffset, sec_hdroffset; - - n = n0 = 0; - p = NULL; - ret = 1; - if (!read_mem(fd, 0, &dh, sizeof dh)) - goto the_end; - if (!read_mem(fd, dh.e_lfanew, &sig, sizeof sig)) - goto the_end; - if (sig != 0x00004550) - goto the_end; - pef_hdroffset = dh.e_lfanew + sizeof sig; - if (!read_mem(fd, pef_hdroffset, &ih, sizeof ih)) - goto the_end; - opt_hdroffset = pef_hdroffset + sizeof ih; - if (ih.Machine == 0x014C) { - IMAGE_OPTIONAL_HEADER32 oh; - sec_hdroffset = opt_hdroffset + sizeof oh; - if (!read_mem(fd, opt_hdroffset, &oh, sizeof oh)) - goto the_end; - if (IMAGE_DIRECTORY_ENTRY_EXPORT >= oh.NumberOfRvaAndSizes) - goto the_end_0; - addr = oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; - } else if (ih.Machine == 0x8664) { - IMAGE_OPTIONAL_HEADER64 oh; - sec_hdroffset = opt_hdroffset + sizeof oh; - if (!read_mem(fd, opt_hdroffset, &oh, sizeof oh)) - goto the_end; - if (IMAGE_DIRECTORY_ENTRY_EXPORT >= oh.NumberOfRvaAndSizes) - goto the_end_0; - addr = oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; - } else - goto the_end; - - //printf("addr: %08x\n", addr); - for (i = 0; i < ih.NumberOfSections; ++i) { - if (!read_mem(fd, sec_hdroffset + i * sizeof ish, &ish, sizeof ish)) - goto the_end; - //printf("vaddr: %08x\n", ish.VirtualAddress); - if (addr >= ish.VirtualAddress && addr < ish.VirtualAddress + ish.SizeOfRawData) - goto found; - } - goto the_end_0; -found: - ref = ish.VirtualAddress - ish.PointerToRawData; - if (!read_mem(fd, addr - ref, &ied, sizeof ied)) - goto the_end; - k = ied.NumberOfNames; - if (k) { - namep = tcc_malloc(l = k * sizeof *namep); - if (!read_mem(fd, ied.AddressOfNames - ref, namep, l)) - goto the_end; - for (i = l = 0; i < k; ++i) { - p1 = namep[i] - ref; - if (p1 != p0) - lseek(fd, p0 = p1, SEEK_SET), l = 0; - do { - if (0 == l) { - if (n + 1000 >= n0) - p = tcc_realloc(p, n0 += 1000); - if ((l = read(fd, p + n, 1000 - 1)) <= 0) - goto the_end; - } - --l, ++p0; - } while (p[n++]); - } - p[n] = 0; - } -the_end_0: - ret = 0; -the_end: - tcc_free(namep); - if (ret && p) - tcc_free(p), p = NULL; - *pp = p; - return ret; -} - -/* ------------------------------------------------------------- - * This is for compiled windows resources in 'coff' format - * as generated by 'windres.exe -O coff ...'. - */ - -static int pe_load_res(TCCState *s1, int fd) -{ - struct pe_rsrc_header hdr; - Section *rsrc_section; - int i, ret = -1, sym_index; - BYTE *ptr; - unsigned offs; - - if (!read_mem(fd, 0, &hdr, sizeof hdr)) - goto quit; - - if (hdr.filehdr.Machine != IMAGE_FILE_MACHINE - || hdr.filehdr.NumberOfSections != 1 - || strcmp((char*)hdr.sectionhdr.Name, ".rsrc") != 0) - goto quit; - - rsrc_section = new_section(s1, ".rsrc", SHT_PROGBITS, SHF_ALLOC); - ptr = section_ptr_add(rsrc_section, hdr.sectionhdr.SizeOfRawData); - offs = hdr.sectionhdr.PointerToRawData; - if (!read_mem(fd, offs, ptr, hdr.sectionhdr.SizeOfRawData)) - goto quit; - offs = hdr.sectionhdr.PointerToRelocations; - sym_index = put_elf_sym(symtab_section, 0, 0, 0, 0, rsrc_section->sh_num, ".rsrc"); - for (i = 0; i < hdr.sectionhdr.NumberOfRelocations; ++i) { - struct pe_rsrc_reloc rel; - if (!read_mem(fd, offs, &rel, sizeof rel)) - goto quit; - // printf("rsrc_reloc: %x %x %x\n", rel.offset, rel.size, rel.type); - if (rel.type != RSRC_RELTYPE) - goto quit; - put_elf_reloc(symtab_section, rsrc_section, - rel.offset, R_XXX_RELATIVE, sym_index); - offs += sizeof rel; - } - ret = 0; -quit: - return ret; -} - -/* ------------------------------------------------------------- */ - -static char *trimfront(char *p) -{ - while ((unsigned char)*p <= ' ' && *p && *p != '\n') - ++p; - return p; -} - -/* -static char *trimback(char *a, char *e) -{ - while (e > a && (unsigned char)e[-1] <= ' ') - --e; - *e = 0;; - return a; -}*/ - -static char *get_token(char **s, char *f) -{ - char *p = *s, *e; - p = e = trimfront(p); - while ((unsigned char)*e > ' ') - ++e; - *s = trimfront(e); - *f = **s; *e = 0; - return p; -} - -static int pe_load_def(TCCState *s1, int fd) -{ - int state = 0, ret = -1, dllindex = 0, ord; - char dllname[80], *buf, *line, *p, *x, next; - - buf = tcc_load_text(fd); - if (!buf) - return ret; - - for (line = buf;; ++line) { - p = get_token(&line, &next); - if (!(*p && *p != ';')) - goto skip; - switch (state) { - case 0: - if (0 != stricmp(p, "LIBRARY") || next == '\n') - goto quit; - pstrcpy(dllname, sizeof dllname, get_token(&line, &next)); - ++state; - break; - case 1: - if (0 != stricmp(p, "EXPORTS")) - goto quit; - ++state; - break; - case 2: - dllindex = tcc_add_dllref(s1, dllname, 0)->index; - ++state; - /* fall through */ - default: - /* get ordinal and will store in sym->st_value */ - ord = 0; - if (next == '@') { - x = get_token(&line, &next); - ord = (int)strtol(x + 1, &x, 10); - } - //printf("token %s ; %s : %d\n", dllname, p, ord); - pe_putimport(s1, dllindex, p, ord); - break; - } -skip: - while ((unsigned char)next > ' ') - get_token(&line, &next); - if (next != '\n') - break; - } - ret = 0; -quit: - tcc_free(buf); - return ret; -} - -/* ------------------------------------------------------------- */ - -static int pe_load_dll(TCCState *s1, int fd, const char *filename) -{ - char *p, *q; - DLLReference *ref = tcc_add_dllref(s1, tcc_basename(filename), 0); - if (ref->found) - return 0; - if (get_dllexports(fd, &p)) - return -1; - if (p) { - for (q = p; *q; q += 1 + strlen(q)) - pe_putimport(s1, ref->index, q, 0); - tcc_free(p); - } - return 0; -} - -ST_FUNC int pe_load_file(struct TCCState *s1, int fd, const char *filename) -{ - int ret = -1; - char buf[10]; - if (0 == strcmp(tcc_fileextension(filename), ".def")) - ret = pe_load_def(s1, fd); - else if (pe_load_res(s1, fd) == 0) - ret = 0; - else if (read_mem(fd, 0, buf, 4) && 0 == memcmp(buf, "MZ", 2)) - ret = pe_load_dll(s1, fd, filename); - return ret; -} - -PUB_FUNC int tcc_get_dllexports(const char *filename, char **pp) -{ - int ret, fd = open(filename, O_RDONLY | O_BINARY); - if (fd < 0) - return -1; - ret = get_dllexports(fd, pp); - close(fd); - return ret; -} - -/* ------------------------------------------------------------- */ -#ifdef TCC_TARGET_X86_64 -static unsigned pe_add_uwwind_info(TCCState *s1) -{ - if (NULL == s1->uw_pdata) { - s1->uw_pdata = find_section(s1, ".pdata"); - s1->uw_pdata->sh_addralign = 4; - } - if (0 == s1->uw_sym) - s1->uw_sym = put_elf_sym(symtab_section, 0, 0, 0, 0, text_section->sh_num, ".uw_base"); - if (0 == s1->uw_offs) { - /* As our functions all have the same stackframe, we use one entry for all */ - static const unsigned char uw_info[] = { - 0x01, // UBYTE: 3 Version , UBYTE: 5 Flags - 0x04, // UBYTE Size of prolog - 0x02, // UBYTE Count of unwind codes - 0x05, // UBYTE: 4 Frame Register (rbp), UBYTE: 4 Frame Register offset (scaled) - // USHORT * n Unwind codes array (descending order) - // 0x0b, 0x01, 0xff, 0xff, // stack size - // UBYTE offset of end of instr in prolog + 1, UBYTE:4 operation, UBYTE:4 info - 0x04, 0x03, // 3:0 UWOP_SET_FPREG (mov rsp -> rbp) - 0x01, 0x50, // 0:5 UWOP_PUSH_NONVOL (push rbp) - }; - - Section *s = text_section; - unsigned char *p; - - section_ptr_add(s, -s->data_offset & 3); /* align */ - s1->uw_offs = s->data_offset; - p = section_ptr_add(s, sizeof uw_info); - memcpy(p, uw_info, sizeof uw_info); - } - - return s1->uw_offs; -} - -ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack) -{ - TCCState *s1 = tcc_state; - Section *pd; - unsigned o, n, d; - struct /* _RUNTIME_FUNCTION */ { - DWORD BeginAddress; - DWORD EndAddress; - DWORD UnwindData; - } *p; - - d = pe_add_uwwind_info(s1); - pd = s1->uw_pdata; - o = pd->data_offset; - p = section_ptr_add(pd, sizeof *p); - - /* record this function */ - p->BeginAddress = start; - p->EndAddress = end; - p->UnwindData = d; - - /* put relocations on it */ - for (n = o + sizeof *p; o < n; o += sizeof p->BeginAddress) - put_elf_reloc(symtab_section, pd, o, R_XXX_RELATIVE, s1->uw_sym); -} -#endif -/* ------------------------------------------------------------- */ -#ifdef TCC_TARGET_X86_64 -#define PE_STDSYM(n,s) n -#else -#define PE_STDSYM(n,s) "_" n s -#endif - -static void pe_add_runtime(TCCState *s1, struct pe_info *pe) -{ - const char *start_symbol; - int pe_type; - - if (TCC_OUTPUT_DLL == s1->output_type) { - pe_type = PE_DLL; - start_symbol = PE_STDSYM("__dllstart","@12"); - } else { - const char *run_symbol; - if (find_elf_sym(symtab_section, PE_STDSYM("WinMain","@16"))) { - start_symbol = "__winstart"; - run_symbol = "__runwinmain"; - pe_type = PE_GUI; - } else if (find_elf_sym(symtab_section, PE_STDSYM("wWinMain","@16"))) { - start_symbol = "__wwinstart"; - run_symbol = "__runwwinmain"; - pe_type = PE_GUI; - } else if (find_elf_sym(symtab_section, "wmain")) { - start_symbol = "__wstart"; - run_symbol = "__runwmain"; - pe_type = PE_EXE; - } else { - start_symbol = "__start"; - run_symbol = "__runmain"; - pe_type = PE_EXE; - if (s1->pe_subsystem == 2) - pe_type = PE_GUI; - } - - if (TCC_OUTPUT_MEMORY == s1->output_type && !s1->nostdlib) - start_symbol = run_symbol; - } - if (s1->elf_entryname) { - pe->start_symbol = start_symbol = s1->elf_entryname; - } else { - pe->start_symbol = start_symbol + 1; - if (!s1->leading_underscore || strchr(start_symbol, '@')) - ++start_symbol; - } - - /* grab the startup code from libtcc1.a */ -#ifdef TCC_IS_NATIVE - if (TCC_OUTPUT_MEMORY != s1->output_type || s1->run_main) -#endif - set_global_sym(s1, start_symbol, NULL, 0); - - if (0 == s1->nostdlib) { - static const char * const libs[] = { - "msvcrt", "kernel32", "", "user32", "gdi32", NULL - }; - const char * const *pp, *p; - if (TCC_LIBTCC1[0]) - tcc_add_support(s1, TCC_LIBTCC1); - s1->static_link = 0; /* no static crt for tcc */ - for (pp = libs; 0 != (p = *pp); ++pp) { - if (*p) - tcc_add_library(s1, p); - else if (PE_DLL != pe_type && PE_GUI != pe_type) - break; - } - } - - /* need this for 'tccelf.c:relocate_sections()' */ - if (TCC_OUTPUT_DLL == s1->output_type) - s1->output_type = TCC_OUTPUT_EXE; - if (TCC_OUTPUT_MEMORY == s1->output_type) - pe_type = PE_RUN; - pe->type = pe_type; -} - -static void pe_set_options(TCCState * s1, struct pe_info *pe) -{ - if (PE_DLL == pe->type) { - /* XXX: check if is correct for arm-pe target */ - pe->imagebase = 0x10000000; - } else { -#if defined(TCC_TARGET_ARM) - pe->imagebase = 0x00010000; -#else - pe->imagebase = 0x00400000; -#endif - } - -#if defined(TCC_TARGET_ARM) - /* we use "console" subsystem by default */ - pe->subsystem = 9; -#else - if (PE_DLL == pe->type || PE_GUI == pe->type) - pe->subsystem = 2; - else - pe->subsystem = 3; -#endif - /* Allow override via -Wl,-subsystem=... option */ - if (s1->pe_subsystem != 0) - pe->subsystem = s1->pe_subsystem; - - /* set default file/section alignment */ - if (pe->subsystem == 1) { - pe->section_align = 0x20; - pe->file_align = 0x20; - } else { - pe->section_align = 0x1000; - pe->file_align = 0x200; - } - - if (s1->section_align != 0) - pe->section_align = s1->section_align; - if (s1->pe_file_align != 0) - pe->file_align = s1->pe_file_align; - - if ((pe->subsystem >= 10) && (pe->subsystem <= 12)) - pe->imagebase = 0; - - if (s1->has_text_addr) - pe->imagebase = s1->text_addr; -} - -ST_FUNC int pe_output_file(TCCState *s1, const char *filename) -{ - struct pe_info pe; - - memset(&pe, 0, sizeof pe); - pe.filename = filename; - pe.s1 = s1; - s1->filetype = 0; - - tcc_add_pragma_libs(s1); - pe_add_runtime(s1, &pe); - resolve_common_syms(s1); - pe_set_options(s1, &pe); - pe_check_symbols(&pe); - - if (s1->nb_errors) - ; - else if (filename) { - pe_assign_addresses(&pe); - relocate_syms(s1, s1->symtab, 0); - s1->pe_imagebase = pe.imagebase; - relocate_sections(s1); - pe.start_addr = (DWORD) - (get_sym_addr(s1, pe.start_symbol, 1, 1) - pe.imagebase); - if (0 == s1->nb_errors) - pe_write(&pe); - dynarray_reset(&pe.sec_info, &pe.sec_count); - } else { -#ifdef TCC_IS_NATIVE - pe.thunk = data_section; - pe_build_imports(&pe); - s1->run_main = pe.start_symbol; -#ifdef TCC_TARGET_X86_64 - s1->uw_pdata = find_section(s1, ".pdata"); -#endif -#endif - } - pe_free_imports(&pe); -#if PE_PRINT_SECTIONS - if (s1->g_debug & 8) - pe_print_sections(s1, "tcc.log"); -#endif - return s1->nb_errors ? -1 : 0; -} - -/* ------------------------------------------------------------- */ diff --git a/libtcc/tccpp.c b/libtcc/tccpp.c index 15b540f7..a5f7e46f 100644 --- a/libtcc/tccpp.c +++ b/libtcc/tccpp.c @@ -21,6 +21,9 @@ #define USING_GLOBALS #include "tcc.h" #include "utils/string.h" +#include "token.h" +#include +#include /* #define to 1 to enable (see parse_pp_string()) */ #define ACCEPT_LF_IN_STRINGS 0 @@ -28,19 +31,19 @@ /********************************************************/ /* global variables */ -ST_DATA int tok_flags; -ST_DATA int parse_flags; +int tok_flags; +int parse_flags; -ST_DATA struct BufferedFile *file; -ST_DATA int tok; -ST_DATA CValue tokc; -ST_DATA const int *macro_ptr; -ST_DATA CString tokcstr; /* current parsed string, if any */ +struct BufferedFile *file; +int tok; +CValue tokc; +const int *macro_ptr; +CString tokcstr; /* current parsed string, if any */ /* display benchmark infos */ -ST_DATA int tok_ident; -ST_DATA TokenSym **table_ident; -ST_DATA int pp_expr; +int tok_ident; +TokenSym **table_ident; +int pp_expr; /* ------------------------------------------------------------------------- */ @@ -64,7 +67,7 @@ static TokenString *macro_stack; static const char tcc_keywords[] = #define DEF(id, str) str "\0" -#include "tcctok.h" +#include "token.inc" #undef DEF ; @@ -98,7 +101,7 @@ static const unsigned char tok_two_chars[] = 0 }; -ST_FUNC void skip(int c) +void skip(int c) { if (tok != c) { char tmp[40]; @@ -108,7 +111,7 @@ ST_FUNC void skip(int c) next(); } -ST_FUNC void expect(const char *msg) +void expect(const char *msg) { tcc_error("%s expected", msg); } @@ -339,7 +342,7 @@ static void cstr_realloc(CString *cstr, int new_size) } /* add a byte */ -ST_INLN void cstr_ccat(CString *cstr, int ch) +void cstr_ccat(CString *cstr, int ch) { int size; size = cstr->size + 1; @@ -349,7 +352,7 @@ ST_INLN void cstr_ccat(CString *cstr, int ch) cstr->size = size; } -ST_INLN char *unicode_to_utf8 (char *b, uint32_t Uc) +char *unicode_to_utf8 (char *b, uint32_t Uc) { if (Uc<0x80) *b++=Uc; else if (Uc<0x800) *b++=192+Uc/64, *b++=128+Uc%64; @@ -361,7 +364,7 @@ ST_INLN char *unicode_to_utf8 (char *b, uint32_t Uc) } /* add a unicode character expanded into utf8 */ -ST_INLN void cstr_u8cat(CString *cstr, int ch) +void cstr_u8cat(CString *cstr, int ch) { char buf[4], *e; e = unicode_to_utf8(buf, (uint32_t)ch); @@ -369,7 +372,7 @@ ST_INLN void cstr_u8cat(CString *cstr, int ch) } /* add string of 'len', or of its len/len+1 when 'len' == -1/0 */ -ST_FUNC void cstr_cat(CString *cstr, const char *str, int len) +void cstr_cat(CString *cstr, const char *str, int len) { int size; if (len <= 0) @@ -382,7 +385,7 @@ ST_FUNC void cstr_cat(CString *cstr, const char *str, int len) } /* add a wide char */ -ST_FUNC void cstr_wccat(CString *cstr, int ch) +void cstr_wccat(CString *cstr, int ch) { int size; size = cstr->size + sizeof(nwchar_t); @@ -392,24 +395,24 @@ ST_FUNC void cstr_wccat(CString *cstr, int ch) cstr->size = size; } -ST_FUNC void cstr_new(CString *cstr) +void cstr_new(CString *cstr) { memset(cstr, 0, sizeof(CString)); } /* free string and reset it to NULL */ -ST_FUNC void cstr_free(CString *cstr) +void cstr_free(CString *cstr) { tcc_free(cstr->data); } /* reset string to empty */ -ST_FUNC void cstr_reset(CString *cstr) +void cstr_reset(CString *cstr) { cstr->size = 0; } -ST_FUNC int cstr_vprintf(CString *cstr, const char *fmt, va_list ap) +int cstr_vprintf(CString *cstr, const char *fmt, va_list ap) { va_list v; int len, size = 80; @@ -429,7 +432,7 @@ ST_FUNC int cstr_vprintf(CString *cstr, const char *fmt, va_list ap) return len; } -ST_FUNC int cstr_printf(CString *cstr, const char *fmt, ...) +int cstr_printf(CString *cstr, const char *fmt, ...) { va_list ap; int len; va_start(ap, fmt); @@ -496,7 +499,7 @@ static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len) /* find a token and add it if not found */ -ST_FUNC TokenSym *tok_alloc(const char *str, int len) +TokenSym *tok_alloc(const char *str, int len) { TokenSym *ts, **pts; int i; @@ -519,7 +522,7 @@ ST_FUNC TokenSym *tok_alloc(const char *str, int len) return tok_alloc_new(pts, str, len); } -ST_FUNC int tok_alloc_const(const char *str) +int tok_alloc_const(const char *str) { return tok_alloc(str, strlen(str))->tok; } @@ -527,7 +530,7 @@ ST_FUNC int tok_alloc_const(const char *str) /* XXX: buffer overflow */ /* XXX: float tokens */ -ST_FUNC const char *get_tok_str(int v, CValue *cv) +const char *get_tok_str(int v, CValue *cv) { char *p; int i, len; @@ -551,6 +554,7 @@ ST_FUNC const char *get_tok_str(int v, CValue *cv) break; case TOK_LCHAR: cstr_ccat(&cstr_buf, 'L'); + // fall through case TOK_CCHAR: cstr_ccat(&cstr_buf, '\''); add_char(&cstr_buf, cv->i); @@ -562,6 +566,7 @@ ST_FUNC const char *get_tok_str(int v, CValue *cv) return (char*)cv->str.data; case TOK_LSTR: cstr_ccat(&cstr_buf, 'L'); + // fall through case TOK_STR: cstr_ccat(&cstr_buf, '\"'); if (v == TOK_STR) { @@ -1000,7 +1005,7 @@ static inline int tok_size(const int *p) #endif /* token string handling */ -ST_INLN void tok_str_new(TokenString *s) +void tok_str_new(TokenString *s) { s->str = NULL; s->len = s->need_spc = 0; @@ -1008,25 +1013,25 @@ ST_INLN void tok_str_new(TokenString *s) s->last_line_num = -1; } -ST_FUNC TokenString *tok_str_alloc(void) +TokenString *tok_str_alloc(void) { TokenString *str = tal_realloc(tokstr_alloc, 0, sizeof *str); tok_str_new(str); return str; } -ST_FUNC void tok_str_free_str(int *str) +void tok_str_free_str(int *str) { tal_free(tokstr_alloc, str); } -ST_FUNC void tok_str_free(TokenString *str) +void tok_str_free(TokenString *str) { tok_str_free_str(str->str); tal_free(tokstr_alloc, str); } -ST_FUNC int *tok_str_realloc(TokenString *s, int new_size) +int *tok_str_realloc(TokenString *s, int new_size) { int *str, size; @@ -1043,7 +1048,7 @@ ST_FUNC int *tok_str_realloc(TokenString *s, int new_size) return s->str; } -ST_FUNC void tok_str_add(TokenString *s, int t) +void tok_str_add(TokenString *s, int t) { int len, *str; @@ -1055,7 +1060,7 @@ ST_FUNC void tok_str_add(TokenString *s, int t) s->len = len; } -ST_FUNC void begin_macro(TokenString *str, int alloc) +void begin_macro(TokenString *str, int alloc) { str->alloc = alloc; str->prev = macro_stack; @@ -1065,7 +1070,7 @@ ST_FUNC void begin_macro(TokenString *str, int alloc) macro_stack = str; } -ST_FUNC void end_macro(void) +void end_macro(void) { TokenString *str = macro_stack; macro_stack = str->prev; @@ -1154,7 +1159,7 @@ static void tok_str_add2(TokenString *s, int t, CValue *cv) } /* add the current parse token in token string 's' */ -ST_FUNC void tok_str_add_tok(TokenString *s) +void tok_str_add_tok(TokenString *s) { CValue cval; @@ -1272,7 +1277,7 @@ static int macro_is_equal(const int *a, const int *b) } /* defines handling */ -ST_INLN void define_push(int v, int macro_type, int *str, Sym *first_arg) +void define_push(int v, int macro_type, int *str, Sym *first_arg) { Sym *s, *o; @@ -1287,14 +1292,14 @@ ST_INLN void define_push(int v, int macro_type, int *str, Sym *first_arg) } /* undefined a define symbol. Its name is just set to zero */ -ST_FUNC void define_undef(Sym *s) +void define_undef(Sym *s) { int v = s->v; if (v >= TOK_IDENT && v < tok_ident) table_ident[v - TOK_IDENT]->sym_define = NULL; } -ST_INLN Sym *define_find(int v) +Sym *define_find(int v) { v -= TOK_IDENT; if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT)) @@ -1303,7 +1308,7 @@ ST_INLN Sym *define_find(int v) } /* free define stack until top reaches 'b' */ -ST_FUNC void free_defines(Sym *b) +void free_defines(Sym *b) { while (define_stack != b) { Sym *top = define_stack; @@ -1314,22 +1319,7 @@ ST_FUNC void free_defines(Sym *b) } } -/* fake the nth "#if defined test_..." for tcc -dt -run */ -static void maybe_run_test(TCCState *s) -{ - const char *p; - if (s->include_stack_ptr != s->include_stack) - return; - p = get_tok_str(tok, NULL); - if (0 != memcmp(p, "test_", 5)) - return; - /*if (0 != --s->run_test) - return;*/ - fprintf(s->ppfp, &"\n[%s]\n"[!(s->dflag & 32)], p), fflush(s->ppfp); - define_push(tok, MACRO_OBJ, NULL, NULL); -} - -ST_FUNC void skip_to_eol(int warn) +void skip_to_eol(int warn) { if (tok == TOK_LINEFEED) return; @@ -1521,7 +1511,7 @@ static int expr_preprocess(TCCState *s1) return c != 0; } -ST_FUNC void pp_error(CString *cs) +void pp_error(CString *cs) { cstr_printf(cs, "bad preprocessor expression: #%s", get_tok_str(pp_expr, 0)); macro_ptr = macro_stack->str; @@ -1530,7 +1520,7 @@ ST_FUNC void pp_error(CString *cs) } /* parse after #define */ -ST_FUNC void parse_define(void) +void parse_define(void) { Sym *s, *first, **ps; int v, t, varg, is_vaargs, t0; @@ -1780,7 +1770,7 @@ pragma_err: } /* put alternative filename */ -ST_FUNC void tccpp_putfile(const char *filename) +void tccpp_putfile(const char *filename) { char buf[1024]; buf[0] = 0; @@ -1802,7 +1792,7 @@ ST_FUNC void tccpp_putfile(const char *filename) } /* is_bof is true if first non space token at beginning of file */ -ST_FUNC void preprocess(int is_bof) +void preprocess(int is_bof) { TCCState *s1 = tcc_state; int c, n, saved_parse_flags; @@ -2659,7 +2649,7 @@ maybe_newline: if (!(isidnum_table['$' - CH_EOF] & IS_ID) || (parse_flags & PARSE_FLAG_ASM_FILE)) goto parse_simple; - + // fall through case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': @@ -3465,7 +3455,7 @@ static int macro_subst( } /* return next token with macro substitution */ -ST_FUNC void next(void) +void next(void) { int t; while (macro_ptr) { @@ -3524,7 +3514,7 @@ convert: /* push back current token and set current token to 'last_tok'. Only identifier case handled for labels. */ -ST_INLN void unget_tok(int last_tok) +void unget_tok(int last_tok) { TokenString *str = &unget_buf; int alloc = 0; @@ -3595,7 +3585,7 @@ static void tcc_predefs(TCCState *s1, CString *cs, int is_asm) cstr_printf(cs, "#define __BASE_FILE__ \"%s\"\n", file->filename); } -ST_FUNC void preprocess_start(TCCState *s1, int filetype) +void preprocess_start(TCCState *s1, int filetype) { int is_asm = !!(filetype & (AFF_TYPE_ASM|AFF_TYPE_ASMPP)); @@ -3631,7 +3621,7 @@ ST_FUNC void preprocess_start(TCCState *s1, int filetype) } /* cleanup from error/setjmp */ -ST_FUNC void preprocess_end(TCCState *s1) +void preprocess_end(TCCState *s1) { while (macro_stack) end_macro(); @@ -3641,14 +3631,14 @@ ST_FUNC void preprocess_end(TCCState *s1) tccpp_delete(s1); } -ST_FUNC int set_idnum(int c, int val) +int set_idnum(int c, int val) { int prev = isidnum_table[c - CH_EOF]; isidnum_table[c - CH_EOF] = val; return prev; } -ST_FUNC void tccpp_new(TCCState *s) +void tccpp_new(TCCState *s) { int i, c; const char *p, *r; @@ -3700,7 +3690,7 @@ ST_FUNC void tccpp_new(TCCState *s) define_push(TOK___COUNTER__, MACRO_OBJ, NULL, NULL); } -ST_FUNC void tccpp_delete(TCCState *s) +void tccpp_delete(TCCState *s) { int i, n; @@ -3852,7 +3842,7 @@ static int pp_check_he0xE(int t, const char *p) } /* Preprocess the current file */ -ST_FUNC int tcc_preprocess(TCCState *s1) +int tcc_preprocess(TCCState *s1) { BufferedFile **iptr; int token_seen, spcs, level; diff --git a/libtcc/token.h b/libtcc/token.h new file mode 100644 index 00000000..13bba666 --- /dev/null +++ b/libtcc/token.h @@ -0,0 +1,98 @@ +#ifndef TCC_TOKEN_H +# define TCC_TOKEN_H 1 + +/* conditional ops */ +# define TOK_LAND 0x90 +# define TOK_LOR 0x91 +/* warning: the following compare tokens depend on i386 asm code */ +# define TOK_ULT 0x92 +# define TOK_UGE 0x93 +# define TOK_EQ 0x94 +# define TOK_NE 0x95 +# define TOK_ULE 0x96 +# define TOK_UGT 0x97 +# define TOK_Nset 0x98 +# define TOK_Nclear 0x99 +# define TOK_LT 0x9c +# define TOK_GE 0x9d +# define TOK_LE 0x9e +# define TOK_GT 0x9f + +# define TOK_ISCOND(t) (t >= TOK_LAND && t <= TOK_GT) + +# define TOK_DEC 0x80 /* -- */ +# define TOK_MID 0x81 /* inc/dec, to void constant */ +# define TOK_INC 0x82 /* ++ */ +# define TOK_UDIV 0x83 /* unsigned division */ +# define TOK_UMOD 0x84 /* unsigned modulo */ +# define TOK_PDIV 0x85 /* fast division with undefined rounding for pointers */ +# define TOK_UMULL 0x86 /* unsigned 32x32 -> 64 mul */ +# define TOK_ADDC1 0x87 /* add with carry generation */ +# define TOK_ADDC2 0x88 /* add with carry use */ +# define TOK_SUBC1 0x89 /* add with carry generation */ +# define TOK_SUBC2 0x8a /* add with carry use */ +# define TOK_SHL '<' /* shift left */ +# define TOK_SAR '>' /* signed shift right */ +# define TOK_SHR 0x8b /* unsigned shift right */ +# define TOK_NEG TOK_MID /* unary minus operation (for floats) */ + +# define TOK_ARROW 0xa0 /* -> */ +# define TOK_DOTS 0xa1 /* three dots */ +# define TOK_TWODOTS 0xa2 /* C++ token ? */ +# define TOK_TWOSHARPS 0xa3 /* ## preprocessing token */ +# define TOK_PLCHLDR 0xa4 /* placeholder token as defined in C99 */ +# define TOK_PPJOIN (TOK_TWOSHARPS | SYM_FIELD) /* A '##' in a macro to mean pasting */ +# define TOK_SOTYPE 0xa7 /* alias of '(' for parsing sizeof (type) */ + +/* assignment operators */ +# define TOK_A_ADD 0xb0 +# define TOK_A_SUB 0xb1 +# define TOK_A_MUL 0xb2 +# define TOK_A_DIV 0xb3 +# define TOK_A_MOD 0xb4 +# define TOK_A_AND 0xb5 +# define TOK_A_OR 0xb6 +# define TOK_A_XOR 0xb7 +# define TOK_A_SHL 0xb8 +# define TOK_A_SAR 0xb9 + +# define TOK_ASSIGN(t) (t >= TOK_A_ADD && t <= TOK_A_SAR) +# define TOK_ASSIGN_OP(t) ("+-*/%&|^<>"[t - TOK_A_ADD]) + +/* tokens that carry values (in additional token string space / tokc) --> */ +# define TOK_CCHAR 0xc0 /* char constant in tokc */ +# define TOK_LCHAR 0xc1 +# define TOK_CINT 0xc2 /* number in tokc */ +# define TOK_CUINT 0xc3 /* unsigned int constant */ +# define TOK_CLLONG 0xc4 /* long long constant */ +# define TOK_CULLONG 0xc5 /* unsigned long long constant */ +# define TOK_CLONG 0xc6 /* long constant */ +# define TOK_CULONG 0xc7 /* unsigned long constant */ +# define TOK_STR 0xc8 /* pointer to string in tokc */ +# define TOK_LSTR 0xc9 +# define TOK_CFLOAT 0xca /* float constant */ +# define TOK_CDOUBLE 0xcb /* double constant */ +# define TOK_CLDOUBLE 0xcc /* long double constant */ +# define TOK_PPNUM 0xcd /* preprocessor number */ +# define TOK_PPSTR 0xce /* preprocessor string */ +# define TOK_LINENUM 0xcf /* line number info */ + +# define TOK_HAS_VALUE(t) (t >= TOK_CCHAR && t <= TOK_LINENUM) + +# define TOK_EOF (-1) /* end of file */ +# define TOK_LINEFEED 10 /* line feed */ + +/* all identifiers and strings have token above that */ +# define TOK_IDENT 256 + +enum tcc_token { + TOK_LAST = TOK_IDENT - 1 +# define DEF(id, str) ,id +# include "token.inc" +# undef DEF +}; + +/* keywords: tok >= TOK_IDENT && tok < TOK_UIDENT */ +# define TOK_UIDENT TOK_DEFINE + +#endif /* !TCC_TOKEN_H */ \ No newline at end of file diff --git a/libtcc/tcctok.h b/libtcc/token.inc similarity index 99% rename from libtcc/tcctok.h rename to libtcc/token.inc index c1cfbe9e..bd1326b6 100644 --- a/libtcc/tcctok.h +++ b/libtcc/token.inc @@ -265,4 +265,4 @@ DEF_ASMDIR(symver) DEF_ASMDIR(section) /* must be last directive */ -#include "i386/tok.h" +#include "i386/token.inc" diff --git a/libtcc/utils/cstr.h b/libtcc/utils/cstr.h new file mode 100644 index 00000000..142c13b7 --- /dev/null +++ b/libtcc/utils/cstr.h @@ -0,0 +1,21 @@ +#ifndef LIBTCC_UTILS_CSTR_H +# define LIBTCC_UTILS_CSTR_H 1 + +# include + +typedef struct CString { + int size; + int size_allocated; + char *data; +} CString; + +void cstr_ccat(CString *cstr, int ch); +void cstr_cat(CString *cstr, const char *str, int len); +void cstr_wccat(CString *cstr, int ch); +void cstr_new(CString *cstr); +void cstr_free(CString *cstr); +int cstr_printf(CString *cs, const char *fmt, ...) __attribute__ ((format (printf, (2), (3)))); +int cstr_vprintf(CString *cstr, const char *fmt, va_list ap); +void cstr_reset(CString *cstr); + +#endif /* !LIBTCC_UTILS_CSTR_H */ \ No newline at end of file diff --git a/libtcc1/Makefile.am b/libtcc1/Makefile.am new file mode 100644 index 00000000..4fac7564 --- /dev/null +++ b/libtcc1/Makefile.am @@ -0,0 +1,20 @@ +COMPILE = ../tcc/tcc + +noinst_LIBRARIES = libtcc1.a + +libtcc1_a_SOURCES = alloca.S atomic.S builtin.c libtcc1.c stdatomic.c + +alloca.o: alloca.S + $(COMPILE) -o $@ -c $^ -I$(srcdir)/include + +atomic.o: atomic.S + $(COMPILE) -o $@ -c $^ -I$(srcdir)/include + +builtin.o: builtin.c + $(COMPILE) -o $@ -c $^ -I$(srcdir)/include + +libtcc1.o: libtcc1.c + $(COMPILE) -o $@ -c $^ -I$(srcdir)/include + +stdatomic.o: stdatomic.c + $(COMPILE) -o $@ -c $^ -I$(srcdir)/include \ No newline at end of file diff --git a/libtcc1/alloca-bt.S b/libtcc1/alloca-bt.S deleted file mode 100644 index c1614886..00000000 --- a/libtcc1/alloca-bt.S +++ /dev/null @@ -1,96 +0,0 @@ -/* ---------------------------------------------- */ -/* alloca-bt.S */ - -#ifdef __leading_underscore -# define _(s) _##s -#else -# define _(s) s -#endif - -/* ---------------------------------------------- */ -#if defined __i386__ - -.globl _(__bound_alloca) -_(__bound_alloca): - pop %edx - pop %eax - mov %eax, %ecx - add $3+1,%eax - and $-4,%eax - jz p6 - -#ifdef _WIN32 -p4: - cmp $4096,%eax - jbe p5 - test %eax,-4096(%esp) - sub $4096,%esp - sub $4096,%eax - jmp p4 - -p5: -#endif - - sub %eax,%esp - mov %esp,%eax - - push %edx - push %eax - push %ecx - push %eax - call _(__bound_new_region) - add $8, %esp - pop %eax - pop %edx - -p6: - push %edx - push %edx - ret - -/* ---------------------------------------------- */ -#elif defined __x86_64__ - -.globl _(__bound_alloca) -_(__bound_alloca): -#ifdef _WIN32 - inc %rcx # add one extra to separate regions - jmp _(alloca) -.globl _(__bound_alloca_nr) -_(__bound_alloca_nr): - dec %rcx - push %rax - mov %rcx,%rdx - mov %rax,%rcx - sub $32,%rsp - call _(__bound_new_region) - add $32,%rsp - pop %rax - ret -#else - pop %rdx - mov %rdi,%rax - mov %rax,%rsi # size, a second parm to the __bound_new_region - - add $15 + 1,%rax # add one extra to separate regions - and $-16,%rax - jz p3 - - - sub %rax,%rsp - mov %rsp,%rdi # pointer, a first parm to the __bound_new_region - mov %rsp,%rax - - push %rdx - push %rax - call _(__bound_new_region) - pop %rax - pop %rdx - -p3: - push %rdx - ret -#endif - -/* ---------------------------------------------- */ -#endif diff --git a/libtcc1/alloca.S b/libtcc1/alloca.S index 6ebafd7c..12b4d3a6 100644 --- a/libtcc1/alloca.S +++ b/libtcc1/alloca.S @@ -7,9 +7,6 @@ # define _(s) s #endif -/* ---------------------------------------------- */ -#if defined __i386__ - .globl _(alloca), _(__alloca) _(alloca): _(__alloca): @@ -35,51 +32,3 @@ p2: push %eax lea 8(%esp),%eax ret - -/* ---------------------------------------------- */ -#elif defined __x86_64__ - -.globl _(alloca) -_(alloca): - pop %rdx -#ifdef _WIN32 - mov %rcx,%rax -#else - mov %rdi,%rax -#endif - add $15,%rax - and $-16,%rax - jz p3 - -#ifdef _WIN32 -p1: - cmp $4096,%rax - jbe p2 - test %rax,-4096(%rsp) - sub $4096,%rsp - sub $4096,%rax - jmp p1 -p2: -#endif - sub %rax,%rsp - mov %rsp,%rax -p3: - push %rdx - ret - -/* ---------------------------------------------- */ -#elif defined __arm__ - - .text - .align 2 - .global alloca - .type alloca, %function -alloca: - rsb sp, r0, sp - bic sp, sp, #7 - mov r0, sp - mov pc, lr - .size alloca, .-alloca - -/* ---------------------------------------------- */ -#endif diff --git a/libtcc1/armeabi.c b/libtcc1/armeabi.c deleted file mode 100644 index 6ade65ef..00000000 --- a/libtcc1/armeabi.c +++ /dev/null @@ -1,544 +0,0 @@ -/* TCC ARM runtime EABI - Copyright (C) 2013 Thomas Preud'homme - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE.*/ - -#ifdef __TINYC__ -#define INT_MIN (-2147483647 - 1) -#define INT_MAX 2147483647 -#define UINT_MAX 0xffffffff -#define LONG_MIN (-2147483647L - 1) -#define LONG_MAX 2147483647L -#define ULONG_MAX 0xffffffffUL -#define LLONG_MAX 9223372036854775807LL -#define LLONG_MIN (-9223372036854775807LL - 1) -#define ULLONG_MAX 0xffffffffffffffffULL -#else -#include -#endif - -/* We rely on the little endianness and EABI calling convention for this to - work */ - -typedef struct double_unsigned_struct { - unsigned low; - unsigned high; -} double_unsigned_struct; - -typedef struct unsigned_int_struct { - unsigned low; - int high; -} unsigned_int_struct; - -#define REGS_RETURN(name, type) \ - void name ## _return(type ret) {} - - -/* Float helper functions */ - -#define FLOAT_EXP_BITS 8 -#define FLOAT_FRAC_BITS 23 - -#define DOUBLE_EXP_BITS 11 -#define DOUBLE_FRAC_BITS 52 - -#define ONE_EXP(type) ((1 << (type ## _EXP_BITS - 1)) - 1) - -REGS_RETURN(unsigned_int_struct, unsigned_int_struct) -REGS_RETURN(double_unsigned_struct, double_unsigned_struct) - -/* float -> integer: (sign) 1.fraction x 2^(exponent - exp_for_one) */ - - -/* float to [unsigned] long long conversion */ -#define DEFINE__AEABI_F2XLZ(name, with_sign) \ -void __aeabi_ ## name(unsigned val) \ -{ \ - int exp, high_shift, sign; \ - double_unsigned_struct ret; \ - \ - /* compute sign */ \ - sign = val >> 31; \ - \ - /* compute real exponent */ \ - exp = val >> FLOAT_FRAC_BITS; \ - exp &= (1 << FLOAT_EXP_BITS) - 1; \ - exp -= ONE_EXP(FLOAT); \ - \ - /* undefined behavior if truncated value cannot be represented */ \ - if (with_sign) { \ - if (exp > 62) /* |val| too big, double cannot represent LLONG_MAX */ \ - return; \ - } else { \ - if ((sign && exp >= 0) || exp > 63) /* if val < 0 || val too big */ \ - return; \ - } \ - \ - val &= (1 << FLOAT_FRAC_BITS) - 1; \ - if (exp >= 32) { \ - ret.high = 1 << (exp - 32); \ - if (exp - 32 >= FLOAT_FRAC_BITS) { \ - ret.high |= val << (exp - 32 - FLOAT_FRAC_BITS); \ - ret.low = 0; \ - } else { \ - high_shift = FLOAT_FRAC_BITS - (exp - 32); \ - ret.high |= val >> high_shift; \ - ret.low = val << (32 - high_shift); \ - } \ - } else { \ - ret.high = 0; \ - ret.low = 1 << exp; \ - if (exp > FLOAT_FRAC_BITS) \ - ret.low |= val << (exp - FLOAT_FRAC_BITS); \ - else \ - ret.low |= val >> (FLOAT_FRAC_BITS - exp); \ - } \ - \ - /* encode negative integer using 2's complement */ \ - if (with_sign && sign) { \ - ret.low = ~ret.low; \ - ret.high = ~ret.high; \ - if (ret.low == UINT_MAX) { \ - ret.low = 0; \ - ret.high++; \ - } else \ - ret.low++; \ - } \ - \ - double_unsigned_struct_return(ret); \ -} - -/* float to unsigned long long conversion */ -DEFINE__AEABI_F2XLZ(f2ulz, 0) - -/* float to long long conversion */ -DEFINE__AEABI_F2XLZ(f2lz, 1) - -/* double to [unsigned] long long conversion */ -#define DEFINE__AEABI_D2XLZ(name, with_sign) \ -void __aeabi_ ## name(double_unsigned_struct val) \ -{ \ - int exp, high_shift, sign; \ - double_unsigned_struct ret; \ - \ - if ((val.high & ~0x80000000) == 0 && val.low == 0) { \ - ret.low = ret.high = 0; \ - goto _ret_; \ - } \ - \ - /* compute sign */ \ - sign = val.high >> 31; \ - \ - /* compute real exponent */ \ - exp = (val.high >> (DOUBLE_FRAC_BITS - 32)); \ - exp &= (1 << DOUBLE_EXP_BITS) - 1; \ - exp -= ONE_EXP(DOUBLE); \ - \ - /* undefined behavior if truncated value cannot be represented */ \ - if (with_sign) { \ - if (exp > 62) /* |val| too big, double cannot represent LLONG_MAX */ \ - return; \ - } else { \ - if ((sign && exp >= 0) || exp > 63) /* if val < 0 || val too big */ \ - return; \ - } \ - \ - val.high &= (1 << (DOUBLE_FRAC_BITS - 32)) - 1; \ - if (exp >= 32) { \ - ret.high = 1 << (exp - 32); \ - if (exp >= DOUBLE_FRAC_BITS) { \ - high_shift = exp - DOUBLE_FRAC_BITS; \ - ret.high |= val.high << high_shift; \ - ret.high |= val.low >> (32 - high_shift); \ - ret.low = val.low << high_shift; \ - } else { \ - high_shift = DOUBLE_FRAC_BITS - exp; \ - ret.high |= val.high >> high_shift; \ - ret.low = val.high << (32 - high_shift); \ - ret.low |= val.low >> high_shift; \ - } \ - } else { \ - ret.high = 0; \ - ret.low = 1 << exp; \ - if (exp > DOUBLE_FRAC_BITS - 32) { \ - high_shift = exp - DOUBLE_FRAC_BITS - 32; \ - ret.low |= val.high << high_shift; \ - ret.low |= val.low >> (32 - high_shift); \ - } else \ - ret.low |= val.high >> (DOUBLE_FRAC_BITS - 32 - exp); \ - } \ - \ - /* encode negative integer using 2's complement */ \ - if (with_sign && sign) { \ - ret.low = ~ret.low; \ - ret.high = ~ret.high; \ - if (ret.low == UINT_MAX) { \ - ret.low = 0; \ - ret.high++; \ - } else \ - ret.low++; \ - } \ - \ -_ret_: \ - double_unsigned_struct_return(ret); \ -} - -/* double to unsigned long long conversion */ -DEFINE__AEABI_D2XLZ(d2ulz, 0) - -/* double to long long conversion */ -DEFINE__AEABI_D2XLZ(d2lz, 1) - -/* long long to float conversion */ -#define DEFINE__AEABI_XL2F(name, with_sign) \ -unsigned __aeabi_ ## name(unsigned long long v) \ -{ \ - int s /* shift */, flb /* first lost bit */, sign = 0; \ - unsigned p = 0 /* power */, ret; \ - double_unsigned_struct val; \ - \ - /* fraction in negative float is encoded in 1's complement */ \ - if (with_sign && (v & (1ULL << 63))) { \ - sign = 1; \ - v = ~v + 1; \ - } \ - val.low = v; \ - val.high = v >> 32; \ - /* fill fraction bits */ \ - for (s = 31, p = 1 << 31; p && !(val.high & p); s--, p >>= 1); \ - if (p) { \ - ret = val.high & (p - 1); \ - if (s < FLOAT_FRAC_BITS) { \ - ret <<= FLOAT_FRAC_BITS - s; \ - ret |= val.low >> (32 - (FLOAT_FRAC_BITS - s)); \ - flb = (val.low >> (32 - (FLOAT_FRAC_BITS - s - 1))) & 1; \ - } else { \ - flb = (ret >> (s - FLOAT_FRAC_BITS - 1)) & 1; \ - ret >>= s - FLOAT_FRAC_BITS; \ - } \ - s += 32; \ - } else { \ - for (s = 31, p = 1 << 31; p && !(val.low & p); s--, p >>= 1); \ - if (p) { \ - ret = val.low & (p - 1); \ - if (s <= FLOAT_FRAC_BITS) { \ - ret <<= FLOAT_FRAC_BITS - s; \ - flb = 0; \ - } else { \ - flb = (ret >> (s - FLOAT_FRAC_BITS - 1)) & 1; \ - ret >>= s - FLOAT_FRAC_BITS; \ - } \ - } else \ - return 0; \ - } \ - if (flb) \ - ret++; \ - \ - /* fill exponent bits */ \ - ret |= (s + ONE_EXP(FLOAT)) << FLOAT_FRAC_BITS; \ - \ - /* fill sign bit */ \ - ret |= sign << 31; \ - \ - return ret; \ -} - -/* unsigned long long to float conversion */ -DEFINE__AEABI_XL2F(ul2f, 0) - -/* long long to float conversion */ -DEFINE__AEABI_XL2F(l2f, 1) - -/* long long to double conversion */ -#define __AEABI_XL2D(name, with_sign) \ -void __aeabi_ ## name(unsigned long long v) \ -{ \ - int s /* shift */, high_shift, sign = 0; \ - unsigned tmp, p = 0; \ - double_unsigned_struct val, ret; \ - \ - /* fraction in negative float is encoded in 1's complement */ \ - if (with_sign && (v & (1ULL << 63))) { \ - sign = 1; \ - v = ~v + 1; \ - } \ - val.low = v; \ - val.high = v >> 32; \ - \ - /* fill fraction bits */ \ - for (s = 31, p = 1 << 31; p && !(val.high & p); s--, p >>= 1); \ - if (p) { \ - tmp = val.high & (p - 1); \ - if (s < DOUBLE_FRAC_BITS - 32) { \ - high_shift = DOUBLE_FRAC_BITS - 32 - s; \ - ret.high = tmp << high_shift; \ - ret.high |= val.low >> (32 - high_shift); \ - ret.low = val.low << high_shift; \ - } else { \ - high_shift = s - (DOUBLE_FRAC_BITS - 32); \ - ret.high = tmp >> high_shift; \ - ret.low = tmp << (32 - high_shift); \ - ret.low |= val.low >> high_shift; \ - if ((val.low >> (high_shift - 1)) & 1) { \ - if (ret.low == UINT_MAX) { \ - ret.high++; \ - ret.low = 0; \ - } else \ - ret.low++; \ - } \ - } \ - s += 32; \ - } else { \ - for (s = 31, p = 1 << 31; p && !(val.low & p); s--, p >>= 1); \ - if (p) { \ - tmp = val.low & (p - 1); \ - if (s <= DOUBLE_FRAC_BITS - 32) { \ - high_shift = DOUBLE_FRAC_BITS - 32 - s; \ - ret.high = tmp << high_shift; \ - ret.low = 0; \ - } else { \ - high_shift = s - (DOUBLE_FRAC_BITS - 32); \ - ret.high = tmp >> high_shift; \ - ret.low = tmp << (32 - high_shift); \ - } \ - } else { \ - ret.high = ret.low = 0; \ - goto _ret_; \ - } \ - } \ - \ - /* fill exponent bits */ \ - ret.high |= (s + ONE_EXP(DOUBLE)) << (DOUBLE_FRAC_BITS - 32); \ - \ - /* fill sign bit */ \ - ret.high |= sign << 31; \ - \ -_ret_: \ - double_unsigned_struct_return(ret); \ -} - -/* unsigned long long to double conversion */ -__AEABI_XL2D(ul2d, 0) - -/* long long to double conversion */ -__AEABI_XL2D(l2d, 1) - - -/* Long long helper functions */ - -/* TODO: add error in case of den == 0 (see §4.3.1 and §4.3.2) */ - -#define define_aeabi_xdivmod_signed_type(basetype, type) \ -typedef struct type { \ - basetype quot; \ - unsigned basetype rem; \ -} type - -#define define_aeabi_xdivmod_unsigned_type(basetype, type) \ -typedef struct type { \ - basetype quot; \ - basetype rem; \ -} type - -#define AEABI_UXDIVMOD(name,type, rettype, typemacro) \ -static inline rettype aeabi_ ## name (type num, type den) \ -{ \ - rettype ret; \ - type quot = 0; \ - \ - /* Increase quotient while it is less than numerator */ \ - while (num >= den) { \ - type q = 1; \ - \ - /* Find closest power of two */ \ - while ((q << 1) * den <= num && q * den <= typemacro ## _MAX / 2) \ - q <<= 1; \ - \ - /* Compute difference between current quotient and numerator */ \ - num -= q * den; \ - quot += q; \ - } \ - ret.quot = quot; \ - ret.rem = num; \ - return ret; \ -} - -#define __AEABI_XDIVMOD(name, type, uiname, rettype, urettype, typemacro) \ -void __aeabi_ ## name(type numerator, type denominator) \ -{ \ - unsigned type num, den; \ - urettype uxdiv_ret; \ - rettype ret; \ - \ - if (numerator >= 0) \ - num = numerator; \ - else \ - num = 0 - numerator; \ - if (denominator >= 0) \ - den = denominator; \ - else \ - den = 0 - denominator; \ - uxdiv_ret = aeabi_ ## uiname(num, den); \ - /* signs differ */ \ - if ((numerator & typemacro ## _MIN) != (denominator & typemacro ## _MIN)) \ - ret.quot = 0 - uxdiv_ret.quot; \ - else \ - ret.quot = uxdiv_ret.quot; \ - if (numerator < 0) \ - ret.rem = 0 - uxdiv_ret.rem; \ - else \ - ret.rem = uxdiv_ret.rem; \ - \ - rettype ## _return(ret); \ -} - -define_aeabi_xdivmod_signed_type(long long, lldiv_t); -define_aeabi_xdivmod_unsigned_type(unsigned long long, ulldiv_t); -define_aeabi_xdivmod_signed_type(int, idiv_t); -define_aeabi_xdivmod_unsigned_type(unsigned, uidiv_t); - -REGS_RETURN(lldiv_t, lldiv_t) -REGS_RETURN(ulldiv_t, ulldiv_t) -REGS_RETURN(idiv_t, idiv_t) -REGS_RETURN(uidiv_t, uidiv_t) - -AEABI_UXDIVMOD(uldivmod, unsigned long long, ulldiv_t, ULLONG) - -__AEABI_XDIVMOD(ldivmod, long long, uldivmod, lldiv_t, ulldiv_t, LLONG) - -void __aeabi_uldivmod(unsigned long long num, unsigned long long den) -{ - ulldiv_t_return(aeabi_uldivmod(num, den)); -} - -void __aeabi_llsl(double_unsigned_struct val, int shift) -{ - double_unsigned_struct ret; - - if (shift >= 32) { - val.high = val.low; - val.low = 0; - shift -= 32; - } - if (shift > 0) { - ret.low = val.low << shift; - ret.high = (val.high << shift) | (val.low >> (32 - shift)); - double_unsigned_struct_return(ret); - return; - } - double_unsigned_struct_return(val); -} - -#define aeabi_lsr(val, shift, fill, type) \ - type ## _struct ret; \ - \ - if (shift >= 32) { \ - val.low = val.high; \ - val.high = fill; \ - shift -= 32; \ - } \ - if (shift > 0) { \ - ret.high = val.high >> shift; \ - ret.low = (val.high << (32 - shift)) | (val.low >> shift); \ - type ## _struct_return(ret); \ - return; \ - } \ - type ## _struct_return(val); - -void __aeabi_llsr(double_unsigned_struct val, int shift) -{ - aeabi_lsr(val, shift, 0, double_unsigned); -} - -void __aeabi_lasr(unsigned_int_struct val, int shift) -{ - aeabi_lsr(val, shift, val.high >> 31, unsigned_int); -} - - -/* Integer division functions */ - -AEABI_UXDIVMOD(uidivmod, unsigned, uidiv_t, UINT) - -int __aeabi_idiv(int numerator, int denominator) -{ - unsigned num, den; - uidiv_t ret; - - if (numerator >= 0) - num = numerator; - else - num = 0 - numerator; - if (denominator >= 0) - den = denominator; - else - den = 0 - denominator; - ret = aeabi_uidivmod(num, den); - if ((numerator & INT_MIN) != (denominator & INT_MIN)) /* signs differ */ - ret.quot *= -1; - return ret.quot; -} - -unsigned __aeabi_uidiv(unsigned num, unsigned den) -{ - return aeabi_uidivmod(num, den).quot; -} - -__AEABI_XDIVMOD(idivmod, int, uidivmod, idiv_t, uidiv_t, INT) - -void __aeabi_uidivmod(unsigned num, unsigned den) -{ - uidiv_t_return(aeabi_uidivmod(num, den)); -} - -/* Some targets do not have all eabi calls (OpenBSD) */ -typedef __SIZE_TYPE__ size_t; -extern void *memcpy(void *dest, const void *src, size_t n); -extern void *memmove(void *dest, const void *src, size_t n); -extern void *memset(void *s, int c, size_t n); - -void * -__aeabi_memcpy (void *dest, const void *src, size_t n) -{ - return memcpy (dest, src, n); -} - -void * -__aeabi_memmove (void *dest, const void *src, size_t n) -{ - return memmove (dest, src, n); -} - -void * -__aeabi_memmove4 (void *dest, const void *src, size_t n) -{ - return memmove (dest, src, n); -} - -void * -__aeabi_memmove8 (void *dest, const void *src, size_t n) -{ - return memmove (dest, src, n); -} - -void * -__aeabi_memset (void *s, size_t n, int c) -{ - return memset (s, c, n); -} diff --git a/libtcc1/armflush.c b/libtcc1/armflush.c deleted file mode 100644 index c379e436..00000000 --- a/libtcc1/armflush.c +++ /dev/null @@ -1,51 +0,0 @@ -/* armflush.c - flush the instruction cache - - __clear_cache is used in tccrun.c, It is a built-in - intrinsic with gcc. However tcc in order to compile - itself needs this function */ - -#ifdef __TINYC__ - -/* syscall wrapper */ -unsigned _tccsyscall(unsigned syscall_nr, ...); - -/* arm-tcc supports only fake asm currently */ -__asm__( - ".global _tccsyscall\n" - "_tccsyscall:\n" - "push {r7, lr}\n\t" - "mov r7, r0\n\t" - "mov r0, r1\n\t" - "mov r1, r2\n\t" - "mov r2, r3\n\t" - "svc #0\n\t" - "pop {r7, pc}" - ); - -/* from unistd.h: */ -#if defined(__thumb__) || defined(__ARM_EABI__) -# define __NR_SYSCALL_BASE 0x0 -#else -# define __NR_SYSCALL_BASE 0x900000 -#endif -#define __ARM_NR_BASE (__NR_SYSCALL_BASE+0x0f0000) -#define __ARM_NR_cacheflush (__ARM_NR_BASE+2) - -#define syscall _tccsyscall - -#else - -#define _GNU_SOURCE -#include -#include -#include - -#endif - -/* Flushing for tccrun */ -void __clear_cache(void *beginning, void *end) -{ -/* __ARM_NR_cacheflush is kernel private and should not be used in user space. - * However, there is no ARM asm parser in tcc so we use it for now */ - syscall(__ARM_NR_cacheflush, beginning, end, 0); -} diff --git a/libtcc1/atomic.S b/libtcc1/atomic.S index 29fdbee1..d6bbbe8a 100644 --- a/libtcc1/atomic.S +++ b/libtcc1/atomic.S @@ -12,7 +12,6 @@ # define _(s) s #endif -#if defined __i386__ .text .align 2 @@ -33,826 +32,3 @@ _(__atomic_clear): xchgb (%edx), %al ret .size _(__atomic_clear), .-_(__atomic_clear) - -#elif defined __x86_64__ - .text - .align 2 - - .global _(__atomic_test_and_set) - .type _(__atomic_test_and_set), %function -_(__atomic_test_and_set): - movl $1, %eax - xchgb (%rdi), %al - ret - .size _(__atomic_test_and_set), .-_(__atomic_test_and_set) - - .global _(__atomic_clear) - .type _(__atomic_clear), %function -_(__atomic_clear): - xorl %eax, %eax - xchgb (%rdi), %al - ret - .size _(__atomic_clear), .-_(__atomic_clear) - -#elif defined __arm__ - -#ifndef __TINYC__ - .arch armv6k - .syntax unified -#endif - .text - .align 2 - - .global _(fetch_and_add_arm) - .type _(fetch_and_add_arm), %function -_(fetch_and_add_arm): - mcr p15, #0, r0, c7, c10, #5 -.L0: - ldrex r3, [r0] - add r3, r3, r1 - strex r2, r3, [r0] - cmp r2, #0 - bne .L0 - mcr p15, #0, r0, c7, c10, #5 - bx lr - .size _(fetch_and_add_arm), .-_(fetch_and_add_arm) - - .global _(__atomic_test_and_set) - .type _(__atomic_test_and_set), %function -_(__atomic_test_and_set): -#ifdef __TINYC__ - .int 0xe92d4030 - .int 0xee070fba - .int 0xe5d03000 - .int 0xe24dd014 - .int 0xe1a05000 - .int 0xe2533000 - .int 0xe1a04001 - .int 0x13a03001 - .int 0xee070fba - .int 0xe5cd300f - .int 0xe3a03001 - .int 0xe1a02003 - .int 0xe28d100f - .int 0xe1a00005 - .int 0xe58d4004 - .int 0xe58d4000 - .int 0xeb000009 - .int 0xe3500000 - .int 0x0afffff6 - .int 0xe5dd000f - .int 0xe28dd014 - .int 0xe8bd8030 -#else - push {r4, r5, lr} - mcr p15, 0, r0, c7, c10, 5 - ldrb r3, [r0] - sub sp, sp, #20 - mov r5, r0 - subs r3, r3, #0 - mov r4, r1 - movne r3, #1 - mcr p15, 0, r0, c7, c10, 5 - strb r3, [sp, #15] -.L20: - mov r3, #1 - mov r2, r3 - add r1, sp, #15 - mov r0, r5 - str r4, [sp, #4] - str r4, [sp] - bl __atomic_compare_exchange_1 - cmp r0, #0 - beq .L20 - ldrb r0, [sp, #15] - add sp, sp, #20 - pop {r4, r5, pc} -#endif - .size _(__atomic_test_and_set), .-_(__atomic_test_and_set) - - .global _(__atomic_clear) - .type _(__atomic_clear), %function -_(__atomic_clear): -#ifdef __TINYC__ - .int 0xe3a03000 - .int 0xee070fba - .int 0xe5c03000 - .int 0xee070fba - .int 0xe12fff1e -#else - mov r3, #0 - mcr p15, 0, r0, c7, c10, 5 - strb r3, [r0] - mcr p15, 0, r0, c7, c10, 5 - bx lr -#endif - .size _(__atomic_clear), .-_(__atomic_clear) - - .global _(__atomic_compare_exchange_1) - .type _(__atomic_compare_exchange_1), %function -_(__atomic_compare_exchange_1): -#ifdef __TINYC__ - .int 0xe52de004 - .int 0xe5d13000 - .int 0xf57ff05b - .int 0xe1d0cf9f - .int 0xe15c0003 - .int 0x1a000002 - .int 0xe1c0ef92 - .int 0xe35e0000 - .int 0x1afffff9 - .int 0x03a00001 - .int 0x13a00000 - .int 0xf57ff05b - .int 0x15c1c000 - .int 0xe49df004 -#else - str lr, [sp, #-4]! - ldrb r3, [r1] - mcr p15, 0, r0, c7, c10, 5 -.L1: - ldrexb ip, [r0] - cmp ip, r3 - bne .L2 - strexb lr, r2, [r0] - cmp lr, #0 - bne .L1 -.L2: - mcr p15, 0, r0, c7, c10, 5 - moveq r0, #1 - movne r0, #0 - strbne ip, [r1] - ldr pc, [sp], #4 -#endif - .size _(__atomic_compare_exchange_1), .-_(__atomic_compare_exchange_1) - - .global _(__atomic_compare_exchange_2) - .type _(__atomic_compare_exchange_2), %function -_(__atomic_compare_exchange_2): -#ifdef __TINYC__ - .int 0xe52de004 - .int 0xe1d130b0 - .int 0xf57ff05b - .int 0xe1f0cf9f - .int 0xe15c0003 - .int 0x1a000002 - .int 0xe1e0ef92 - .int 0xe35e0000 - .int 0x1afffff9 - .int 0x03a00001 - .int 0x13a00000 - .int 0xf57ff05b - .int 0x11c1c0b0 - .int 0xe49df004 -#else - str lr, [sp, #-4]! - ldrh r3, [r1] - mcr p15, 0, r0, c7, c10, 5 -.L3: - ldrexh ip, [r0] - cmp ip, r3 - bne .L4 - strexh lr, r2, [r0] - cmp lr, #0 - bne .L3 -.L4: - mcr p15, 0, r0, c7, c10, 5 - moveq r0, #1 - movne r0, #0 - strhne ip, [r1] - ldr pc, [sp], #4 -#endif - .size _(__atomic_compare_exchange_2), .-_(__atomic_compare_exchange_2) - - .global _(__atomic_compare_exchange_4) - .type _(__atomic_compare_exchange_4), %function -_(__atomic_compare_exchange_4): -#ifdef __TINYC__ - .int 0xe52de004 - .int 0xe5913000 - .int 0xf57ff05b - .int 0xe190cf9f - .int 0xe15c0003 - .int 0x1a000002 - .int 0xe180ef92 - .int 0xe35e0000 - .int 0x1afffff9 - .int 0x03a00001 - .int 0x13a00000 - .int 0xf57ff05b - .int 0x1581c000 - .int 0xe49df004 -#else - str lr, [sp, #-4]! - ldr r3, [r1] - mcr p15, 0, r0, c7, c10, 5 -.L5: - ldrex ip, [r0] - cmp ip, r3 - bne .L6 - strex lr, r2, [r0] - cmp lr, #0 - bne .L5 -.L6: - mcr p15, 0, r0, c7, c10, 5 - moveq r0, #1 - movne r0, #0 - strne ip, [r1] - ldr pc, [sp], #4 -#endif - .size _(__atomic_compare_exchange_4), .-_(__atomic_compare_exchange_4) - -/* ---------------------------------------------- */ -#elif defined __aarch64__ - - .text - .align 2 - - .global _(fetch_and_add_arm64) - .type _(fetch_and_add_arm64), %function -_(fetch_and_add_arm64): -#ifdef __TINYC__ - .int 0x885f7c02 - .int 0x0b010042 - .int 0x8803fc02 - .int 0x35ffffa3 - .int 0xd5033bbf - .int 0xd65f03c0 -#else - ldxr w2, [x0] - add w2, w2, w1 - stlxr w3, w2, [x0] - cbnz w3, _(fetch_and_add_arm64) - dmb ish - ret -#endif - .size _(fetch_and_add_arm64), .-_(fetch_and_add_arm64) - - .global _(__atomic_test_and_set) - .type _(__atomic_test_and_set), %function -_(__atomic_test_and_set): -#ifdef __TINYC__ - .int 0xa9bf7bfd - .int 0xaa0003e1 - .int 0x52800020 - .int 0x910003fd - .int 0x2a0003f0 - .int 0x085ffc20 - .int 0x0811fc30 - .int 0x35ffffd1 - .int 0xa8c17bfd - .int 0xd65f03c0 -#else - stp x29, x30, [sp, -16]! - mov x1, x0 - mov w0, 1 - mov x29, sp - mov w16, w0 -.L20: - ldaxrb w0, [x1] - stlxrb w17, w16, [x1] - cbnz w17, .L20 - ldp x29, x30, [sp], 16 - ret -#endif - .size _(__atomic_test_and_set), .-_(__atomic_test_and_set) - - .global _(__atomic_clear) - .type _(__atomic_clear), %function -_(__atomic_clear): -#ifdef __TINYC__ - .int 0x089ffc1f - .int 0xd65f03c0 -#else - stlrb wzr, [x0] - ret -#endif - .size _(__atomic_clear), .-_(__atomic_clear) - - .global _(__atomic_compare_exchange_1) - .type _(__atomic_compare_exchange_1), %function -_(__atomic_compare_exchange_1): -#ifdef __TINYC__ - .int 0xa9be7bfd - .int 0x910003fd - .int 0xa90153f3 - .int 0xaa0103f3 - .int 0x12001c41 - .int 0xaa0003e2 - .int 0x39400274 - .int 0x2a1403e0 - .int 0x53001c10 - .int 0x085ffc40 - .int 0x6b10001f - .int 0x54000061 - .int 0x0811fc41 - .int 0x35ffff91 - .int 0x6b34001f - .int 0x1a9f17e1 - .int 0x54000040 - .int 0x39000260 - .int 0x2a0103e0 - .int 0xa94153f3 - .int 0xa8c27bfd - .int 0xd65f03c0 -#else - stp x29, x30, [sp, -32]! - mov x29, sp - stp x19, x20, [sp, 16] - mov x19, x1 - and w1, w2, 255 - mov x2, x0 - ldrb w20, [x19] - mov w0, w20 - uxtb w16, w0 -.L1: - ldaxrb w0, [x2] - cmp w0, w16 - b.ne .L2 - stlxrb w17, w1, [x2] - cbnz w17, .L1 -.L2: - cmp w0, w20, uxtb - cset w1, eq - beq .L3 - strb w0, [x19] -.L3: - mov w0, w1 - ldp x19, x20, [sp, 16] - ldp x29, x30, [sp], 32 - ret -#endif - .size _(__atomic_compare_exchange_1), .-_(__atomic_compare_exchange_1) - - .global _(__atomic_compare_exchange_2) - .type _(__atomic_compare_exchange_2), %function -_(__atomic_compare_exchange_2): -#ifdef __TINYC__ - .int 0xa9be7bfd - .int 0x910003fd - .int 0xa90153f3 - .int 0xaa0103f3 - .int 0x12003c41 - .int 0xaa0003e2 - .int 0x79400274 - .int 0x2a1403e0 - .int 0x53003c10 - .int 0x485ffc40 - .int 0x6b10001f - .int 0x54000061 - .int 0x4811fc41 - .int 0x35ffff91 - .int 0x6b34201f - .int 0x1a9f17e1 - .int 0x54000040 - .int 0x79000260 - .int 0x2a0103e0 - .int 0xa94153f3 - .int 0xa8c27bfd - .int 0xd65f03c0 -#else - stp x29, x30, [sp, -32]! - mov x29, sp - stp x19, x20, [sp, 16] - mov x19, x1 - and w1, w2, 65535 - mov x2, x0 - ldrh w20, [x19] - mov w0, w20 - uxth w16, w0 -.L4: - ldaxrh w0, [x2] - cmp w0, w16 - b.ne .L5 - stlxrh w17, w1, [x2] - cbnz w17, .L4 -.L5: - cmp w0, w20, uxth - cset w1, eq - beq .L6 - strh w0, [x19] -.L6: - mov w0, w1 - ldp x19, x20, [sp, 16] - ldp x29, x30, [sp], 32 - ret -#endif - .size _(__atomic_compare_exchange_2), .-_(__atomic_compare_exchange_2) - - .global _(__atomic_compare_exchange_4) - .type _(__atomic_compare_exchange_4), %function -_(__atomic_compare_exchange_4): -#ifdef __TINYC__ - .int 0xa9be7bfd - .int 0x910003fd - .int 0xa90153f3 - .int 0xaa0103f3 - .int 0x2a0203e1 - .int 0xaa0003e2 - .int 0xb9400274 - .int 0x2a1403e0 - .int 0x2a0003f0 - .int 0x885ffc40 - .int 0x6b10001f - .int 0x54000061 - .int 0x8811fc41 - .int 0x35ffff91 - .int 0x6b14001f - .int 0x1a9f17e1 - .int 0x54000040 - .int 0xb9000260 - .int 0x2a0103e0 - .int 0xa94153f3 - .int 0xa8c27bfd - .int 0xd65f03c0 -#else - stp x29, x30, [sp, -32]! - mov x29, sp - stp x19, x20, [sp, 16] - mov x19, x1 - mov w1, w2 - mov x2, x0 - ldr w20, [x19] - mov w0, w20 - mov w16, w0 -.L7: - ldaxr w0, [x2] - cmp w0, w16 - b.ne .L8 - stlxr w17, w1, [x2] - cbnz w17, .L7 -.L8: - cmp w0, w20 - cset w1, eq - beq .L9 - str w0, [x19] -.L9: - mov w0, w1 - ldp x19, x20, [sp, 16] - ldp x29, x30, [sp], 32 - ret -#endif - .size _(__atomic_compare_exchange_4), .-_(__atomic_compare_exchange_4) - - .global _(__atomic_compare_exchange_8) - .type _(__atomic_compare_exchange_8), %function -_(__atomic_compare_exchange_8): -#ifdef __TINYC__ - .int 0xa9be7bfd - .int 0x910003fd - .int 0xa90153f3 - .int 0xaa0103f3 - .int 0xaa0203e1 - .int 0xaa0003e2 - .int 0xf9400274 - .int 0xaa1403e0 - .int 0xaa0003f0 - .int 0xc85ffc40 - .int 0xeb10001f - .int 0x54000061 - .int 0xc811fc41 - .int 0x35ffff91 - .int 0xeb14001f - .int 0x1a9f17e1 - .int 0x54000040 - .int 0xf9000260 - .int 0x2a0103e0 - .int 0xa94153f3 - .int 0xa8c27bfd - .int 0xd65f03c0 -#else - stp x29, x30, [sp, -32]! - mov x29, sp - stp x19, x20, [sp, 16] - mov x19, x1 - mov x1, x2 - mov x2, x0 - ldr x20, [x19] - mov x0, x20 - mov x16, x0 -.L10: - ldaxr x0, [x2] - cmp x0, x16 - b.ne .L11 - stlxr w17, x1, [x2] - cbnz w17, .L10 -.L11: - cmp x0, x20 - cset w1, eq - beq .L12 - str x0, [x19] -.L12: - mov w0, w1 - ldp x19, x20, [sp, 16] - ldp x29, x30, [sp], 32 - ret -#endif - .size _(__atomic_compare_exchange_8), .-_(__atomic_compare_exchange_8) - -/* ---------------------------------------------- */ -#elif defined __riscv - - .text - .align 2 - - .global _(fetch_and_add_riscv64) - .type _(fetch_and_add_riscv64), %function -_(fetch_and_add_riscv64): -#ifdef __TINYC__ - .int 0x0f50000f - .int 0x004b5202f - .short 0x8082 -#else - fence iorw,ow - amoadd.w.aq zero,a1,0(a0) - ret -#endif - .size _(fetch_and_add_riscv64), .-_(fetch_and_add_riscv64) - - .global _(__atomic_test_and_set) - .type _(__atomic_test_and_set), %function -_(__atomic_test_and_set): -#ifdef __TINYC__ - .int 0x00357793 - .int 0x0037979b - .short 0x4685 - .short 0x9971 - .int 0x00f696bb - .int 0x0f50000f - .int 0x44d5272f - .int 0x00f7553b - .int 0x0ff57513 - .short 0x8082 -#else - andi a5,a0,3 - slliw a5,a5,3 - li a3,1 - andi a0,a0,-4 - sllw a3,a3,a5 - fence iorw,ow; amoor.w.aq a4,a3,0(a0) - srlw a0,a4,a5 - andi a0,a0,0xff - ret -#endif - .size _(__atomic_test_and_set), .-_(__atomic_test_and_set) - - .global _(__atomic_clear) - .type _(__atomic_clear), %function -_(__atomic_clear): -#ifdef __TINYC__ - .int 0x0ff0000f - .int 0x00050023 - .int 0x0ff0000f - .short 0x8082 -#else - fence iorw,iorw - sb zero,0(a0) - fence iorw,iorw - ret -#endif - .size _(__atomic_clear), .-_(__atomic_clear) - - .global _(__atomic_compare_exchange_1) - .type _(__atomic_compare_exchange_1), %function -_(__atomic_compare_exchange_1): -#ifdef __TINYC__ - .short 0x1141 - .short 0x86ba - .short 0x873e - .short 0xe406 - .int 0x0ff0000f - .int 0x0005c803 - .int 0xff857893 - .int 0x0008b783 - .short 0x891d - .short 0x050e - .int 0x0ff00693 - .int 0x00a696b3 - .int 0x00a81833 - .int 0x00a61633 - .int 0xfff6c713 - .short 0x8f7d - .int 0x00f6f333 - .short 0x8f51 - .int 0x03031263 - .int 0x1008b32f - .int 0x00f31663 - .int 0x18e8be2f - .int 0xfe0e1ae3 - .int 0x40f30733 - .short 0x879a - .short 0xff69 - .int 0x0ff0000f - .short 0x4505 - .short 0xa801 - .int 0x00a7d7b3 - .int 0x00f58023 - .int 0x0ff0000f - .short 0x4501 - .short 0x60a2 - .short 0x0141 - .short 0x8082 -#else - addi sp,sp,-16 - mv a3,a4 - mv a4,a5 - sd ra,8(sp) - fence - lbu a6,0(a1) - andi a7,a0,-8 - ld a5,0(a7) - andi a0,a0,7 - slli a0,a0,0x3 - li a3,255 - sll a3,a3,a0 - sll a6,a6,a0 - sll a2,a2,a0 -.L1: - not a4,a3 - and a4,a4,a5 - and t1,a3,a5 - or a4,a4,a2 - bne t1,a6,.L4 -.L2: - lr.d t1,(a7) - bne t1,a5,.L3 - sc.d t3,a4,(a7) - bnez t3,.L2 -.L3: - sub a4,t1,a5 - mv a5,t1 - bnez a4,.L1 - fence - li a0,1 - j .L5 -.L4: - srl a5,a5,a0 - sb a5,0(a1) - fence - li a0,0 -.L5: - ld ra,8(sp) - addi sp,sp,16 - jr ra -#endif - .size _(__atomic_compare_exchange_1), .-_(__atomic_compare_exchange_1) - - .global _(__atomic_compare_exchange_2) - .type _(__atomic_compare_exchange_2), %function -_(__atomic_compare_exchange_2): -#ifdef __TINYC__ - .short 0x1141 - .short 0x86ba - .short 0x873e - .short 0xe406 - .int 0x0ff0000f - .int 0x0005d803 - .int 0xff857893 - .short 0x67c1 - .short 0x891d - .int 0x0008b703 - .short 0x050e - .short 0x17fd - .int 0x00a797b3 - .int 0x00a81833 - .int 0x00a61633 - .int 0xfff7c693 - .short 0x8ef9 - .int 0x00e7f333 - .short 0x8ed1 - .int 0x03031263 - .int 0x1008b32f - .int 0x00e31663 - .int 0x18d8be2f - .int 0xfe0e1ae3 - .int 0x40e306b3 - .short 0x871a - .short 0xfee9 - .int 0x0ff0000f - .short 0x4505 - .short 0xa801 - .int 0x00a75733 - .int 0x00e59023 - .int 0x0ff0000f - .short 0x4501 - .short 0x60a2 - .short 0x0141 - .short 0x8082 -#else - addi sp,sp,-16 - mv a3,a4 - mv a4,a5 - sd ra,8(sp) - fence - lhu a6,0(a1) - andi a7,a0,-8 - lui a5,0x10 - andi a0,a0,7 - ld a4,0(a7) - slli a0,a0,0x3 - addi a5,a5,-1 - sll a5,a5,a0 - sll a6,a6,a0 - sll a2,a2,a0 -.L6: - not a3,a5 - and a3,a3,a4 - and t1,a5,a4 - or a3,a3,a2 - bne t1,a6,.L9 -.L7: - lr.d t1,(a7) - bne t1,a4,.L8 - sc.d t3,a3,(a7) - bnez t3,.L7 -.L8: - sub a3,t1,a4 - mv a4,t1 - bnez a3,.L6 - fence - li a0,1 - j .L10 -.L9: - srl a4,a4,a0 - sh a4,0(a1) - fence - li a0,0 -.L10: - ld ra,8(sp) - addi sp,sp,16 - jr ra -#endif - .size _(__atomic_compare_exchange_2), .-_(__atomic_compare_exchange_2) - - .global _(__atomic_compare_exchange_4) - .type _(__atomic_compare_exchange_4), %function -_(__atomic_compare_exchange_4): -#ifdef __TINYC__ - .short 0x419c - .int 0x0f50000f - .int 0x1405272f - .int 0x00f71663 - .int 0x1cc5282f - .int 0xfe081ae3 - .int 0x40f707bb - .int 0x0017b513 - .short 0xc391 - .short 0xc198 - .short 0x8905 - .short 0x8082 -#else - lw a5,0(a1) - fence iorw,ow; -.L11: - lr.w.aq a4,0(a0) - bne a4,a5,.L12 - sc.w.aq a6,a2,0(a0) - bnez a6,.L11 -.L12: - subw a5,a4,a5 - seqz a0,a5 - beq a5,zero,.L13 - sw a4,0(a1) -.L13: - andi a0,a0,1 - ret -#endif - .size _(__atomic_compare_exchange_4), .-_(__atomic_compare_exchange_4) - - .global _(__atomic_compare_exchange_8) - .type _(__atomic_compare_exchange_8), %function -_(__atomic_compare_exchange_8): -#ifdef __TINYC__ - .short 0x619c - .int 0x0f50000f - .int 0x1405372f - .int 0x00f71563 - .int 0x1cc536af - .short 0xfaf5 - .int 0x40f707b3 - .int 0x0017b513 - .short 0xc391 - .short 0xe198 - .short 0x8905 - .short 0x8082 -#else - ld a5,0(a1) - fence iorw,ow; -.L14: - lr.d.aq a4,0(a0) - bne a4,a5,.L15 - sc.d.aq a3,a2,0(a0) - bnez a3,.L14 -.L15: - sub a5,a4,a5 - seqz a0,a5 - beq a5,zero,.L16 - sd a4,0(a1) -.L16: - andi a0,a0,1 - ret -#endif - .size _(__atomic_compare_exchange_8), .-_(__atomic_compare_exchange_8) - -/* ---------------------------------------------- */ -#endif diff --git a/libtcc1/bcheck.c b/libtcc1/bcheck.c deleted file mode 100644 index e3f70e14..00000000 --- a/libtcc1/bcheck.c +++ /dev/null @@ -1,2281 +0,0 @@ -/* - * Tiny C Memory and bounds checker - * - * Copyright (c) 2002 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 -#include -#include -#include -#include - -#if !defined(__FreeBSD__) \ - && !defined(__FreeBSD_kernel__) \ - && !defined(__DragonFly__) \ - && !defined(__OpenBSD__) \ - && !defined(__APPLE__) \ - && !defined(__NetBSD__) -#include -#endif - -#if !defined(_WIN32) -#include -#include -#endif - -#include "config.h" - -#define BOUND_DEBUG (1) -#define BOUND_STATISTIC (1) - -#if BOUND_DEBUG - #define dprintf(a...) if (print_calls) { bounds_loc(a); } -#else - #define dprintf(a...) -#endif - -#ifdef __attribute__ - /* an __attribute__ macro is defined in the system headers */ - #undef __attribute__ -#endif -#define FASTCALL __attribute__((regparm(3))) - -#ifdef _WIN32 -# define DLL_EXPORT __declspec(dllexport) -#else -# define DLL_EXPORT -#endif - -#if defined(__FreeBSD__) \ - || defined(__FreeBSD_kernel__) \ - || defined(__DragonFly__) \ - || defined(__OpenBSD__) \ - || defined(__NetBSD__) \ - || defined(__dietlibc__) - -#include -#define INIT_SEM() -#define EXIT_SEM() -#define WAIT_SEM() -#define POST_SEM() -#define TRY_SEM() -#define HAVE_MEMALIGN (0) -#define MALLOC_REDIR (0) -#define HAVE_PTHREAD_CREATE (0) -#define HAVE_CTYPE (0) -#define HAVE_ERRNO (0) -#define HAVE_SIGNAL (0) -#define HAVE_SIGACTION (0) -#define HAVE_FORK (0) -#define HAVE_TLS_FUNC (0) -#define HAVE_TLS_VAR (0) - -#elif defined(_WIN32) - -#include -#include -static CRITICAL_SECTION bounds_sem; -#define INIT_SEM() InitializeCriticalSection(&bounds_sem) -#define EXIT_SEM() DeleteCriticalSection(&bounds_sem) -#define WAIT_SEM() EnterCriticalSection(&bounds_sem) -#define POST_SEM() LeaveCriticalSection(&bounds_sem) -#define TRY_SEM() TryEnterCriticalSection(&bounds_sem) -#define HAVE_MEMALIGN (0) -#define MALLOC_REDIR (0) -#define HAVE_PTHREAD_CREATE (0) -#define HAVE_CTYPE (0) -#define HAVE_ERRNO (0) -#define HAVE_SIGNAL (1) -#define HAVE_SIGACTION (0) -#define HAVE_FORK (0) -#define HAVE_TLS_FUNC (1) -#define HAVE_TLS_VAR (0) - -#else - -#define __USE_GNU /* get RTLD_NEXT */ -#include -#include -#include -#include -#include -#include -#ifdef __APPLE__ -#include -static dispatch_semaphore_t bounds_sem; -#define INIT_SEM() bounds_sem = dispatch_semaphore_create(1) -#define EXIT_SEM() dispatch_release(*(dispatch_object_t*)&bounds_sem) -#define WAIT_SEM() if (use_sem) dispatch_semaphore_wait(bounds_sem, DISPATCH_TIME_FOREVER) -#define POST_SEM() if (use_sem) dispatch_semaphore_signal(bounds_sem) -#define TRY_SEM() if (use_sem) dispatch_semaphore_wait(bounds_sem, DISPATCH_TIME_NOW) -#elif 0 -#include -static sem_t bounds_sem; -#define INIT_SEM() sem_init (&bounds_sem, 0, 1) -#define EXIT_SEM() sem_destroy (&bounds_sem) -#define WAIT_SEM() if (use_sem) while (sem_wait (&bounds_sem) < 0 \ - && errno == EINTR) -#define POST_SEM() if (use_sem) sem_post (&bounds_sem) -#define TRY_SEM() if (use_sem) while (sem_trywait (&bounds_sem) < 0 \ - && errno == EINTR) -#elif 0 -static pthread_mutex_t bounds_mtx; -#define INIT_SEM() pthread_mutex_init (&bounds_mtx, NULL) -#define EXIT_SEM() pthread_mutex_destroy (&bounds_mtx) -#define WAIT_SEM() if (use_sem) pthread_mutex_lock (&bounds_mtx) -#define POST_SEM() if (use_sem) pthread_mutex_unlock (&bounds_mtx) -#define TRY_SEM() if (use_sem) pthread_mutex_trylock (&bounds_mtx) -#else -static pthread_spinlock_t bounds_spin; -/* about 25% faster then semaphore. */ -#define INIT_SEM() pthread_spin_init (&bounds_spin, 0) -#define EXIT_SEM() pthread_spin_destroy (&bounds_spin) -#define WAIT_SEM() if (use_sem) pthread_spin_lock (&bounds_spin) -#define POST_SEM() if (use_sem) pthread_spin_unlock (&bounds_spin) -#define TRY_SEM() if (use_sem) pthread_spin_trylock (&bounds_spin) -#endif -#define HAVE_MEMALIGN (1) -#define MALLOC_REDIR (1) -#define HAVE_PTHREAD_CREATE (1) -#define HAVE_CTYPE (1) -#define HAVE_ERRNO (1) -#define HAVE_SIGNAL (1) -#define HAVE_SIGACTION (1) -#define HAVE_FORK (1) -#if !defined(__APPLE__) && defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) -#define HAVE_TLS_FUNC (0) -#define HAVE_TLS_VAR (1) -#else -#define HAVE_TLS_FUNC (1) -#define HAVE_TLS_VAR (0) -#endif -#if defined CONFIG_TCC_MUSL || defined __ANDROID__ -# undef HAVE_CTYPE -#endif -#endif - -#if MALLOC_REDIR -static void *(*malloc_redir) (size_t); -static void *(*calloc_redir) (size_t, size_t); -static void (*free_redir) (void *); -static void *(*realloc_redir) (void *, size_t); -static unsigned int pool_index; -static unsigned char __attribute__((aligned(16))) initial_pool[256]; -#endif -#if HAVE_MEMALIGN -static void *(*memalign_redir) (size_t, size_t); -#endif -#if HAVE_PTHREAD_CREATE -static int (*pthread_create_redir) (pthread_t *thread, - const pthread_attr_t *attr, - void *(*start_routine)(void *), void *arg); -#endif -#if HAVE_SIGNAL -typedef void (*bound_sig)(int); -static bound_sig (*signal_redir) (int signum, bound_sig handler); -#endif -#if HAVE_SIGACTION -static int (*sigaction_redir) (int signum, const struct sigaction *act, - struct sigaction *oldact); -#endif -#if HAVE_FORK -static int (*fork_redir) (void); -#endif - -#define TCC_TYPE_NONE (0) -#define TCC_TYPE_MALLOC (1) -#define TCC_TYPE_CALLOC (2) -#define TCC_TYPE_REALLOC (3) -#define TCC_TYPE_MEMALIGN (4) -#define TCC_TYPE_STRDUP (5) - -/* this pointer is generated when bound check is incorrect */ -#define INVALID_POINTER ((void *)(-2)) - -typedef struct tree_node Tree; -struct tree_node { - Tree * left, * right; - size_t start; - size_t size; - unsigned char type; - unsigned char is_invalid; /* true if pointers outside region are invalid */ -}; - -typedef struct alloca_list_struct { - size_t fp; - void *p; - size_t size; - struct alloca_list_struct *next; -} alloca_list_type; - -#if defined(_WIN32) -#define BOUND_TID_TYPE DWORD -#define BOUND_GET_TID(id) id = GetCurrentThreadId() -#elif defined(__OpenBSD__) -#define BOUND_TID_TYPE pid_t -#define BOUND_GET_TID(id) id = getthrid() -#elif defined(__FreeBSD__) -#define BOUND_TID_TYPE pid_t -#define BOUND_GET_TID(id) syscall (SYS_thr_self, &id) -#elif defined(__NetBSD__) -#define BOUND_TID_TYPE pid_t -#define BOUND_GET_TID(id) id = syscall (SYS__lwp_self) -#elif defined(__linux__) -#define BOUND_TID_TYPE pid_t -#define BOUND_GET_TID(id) id = syscall (SYS_gettid) -#else -#define BOUND_TID_TYPE int -#define BOUND_GET_TID(id) id = 0 -#endif - -typedef struct jmp_list_struct { - void *penv; - size_t fp; - size_t end_fp; - BOUND_TID_TYPE tid; - struct jmp_list_struct *next; -} jmp_list_type; - -#define BOUND_STATISTIC_SPLAY (0) -static Tree * splay (size_t addr, Tree *t); -static Tree * splay_end (size_t addr, Tree *t); -static Tree * splay_insert(size_t addr, size_t size, Tree * t); -static Tree * splay_delete(size_t addr, Tree *t); -void splay_printtree(Tree * t, int d); - -/* external interface */ -void __bounds_checking (int no_check); -void __bound_checking_lock (void); -void __bound_checking_unlock (void); -void __bound_never_fatal (int no_check); -DLL_EXPORT void * __bound_ptr_add(void *p, size_t offset); -DLL_EXPORT void * __bound_ptr_indir1(void *p, size_t offset); -DLL_EXPORT void * __bound_ptr_indir2(void *p, size_t offset); -DLL_EXPORT void * __bound_ptr_indir4(void *p, size_t offset); -DLL_EXPORT void * __bound_ptr_indir8(void *p, size_t offset); -DLL_EXPORT void * __bound_ptr_indir12(void *p, size_t offset); -DLL_EXPORT void * __bound_ptr_indir16(void *p, size_t offset); -DLL_EXPORT void FASTCALL __bound_local_new(void *p1); -DLL_EXPORT void FASTCALL __bound_local_delete(void *p1); -void __bound_init(size_t *, int); -void __bound_main_arg(int argc, char **argv, char **envp); -void __bound_exit(void); -void __bound_exit_dll(size_t *); -#if !defined(_WIN32) -void *__bound_mmap (void *start, size_t size, int prot, int flags, int fd, - off_t offset); -int __bound_munmap (void *start, size_t size); -DLL_EXPORT void __bound_siglongjmp(jmp_buf env, int val); -#endif -DLL_EXPORT void __bound_new_region(void *p, size_t size); -DLL_EXPORT void __bound_setjmp(jmp_buf env); -DLL_EXPORT void __bound_longjmp(jmp_buf env, int val); -DLL_EXPORT void *__bound_memcpy(void *dst, const void *src, size_t size); -DLL_EXPORT int __bound_memcmp(const void *s1, const void *s2, size_t size); -DLL_EXPORT void *__bound_memmove(void *dst, const void *src, size_t size); -DLL_EXPORT void *__bound_memset(void *dst, int c, size_t size); -DLL_EXPORT int __bound_strlen(const char *s); -DLL_EXPORT char *__bound_strcpy(char *dst, const char *src); -DLL_EXPORT char *__bound_strncpy(char *dst, const char *src, size_t n); -DLL_EXPORT int __bound_strcmp(const char *s1, const char *s2); -DLL_EXPORT int __bound_strncmp(const char *s1, const char *s2, size_t n); -DLL_EXPORT char *__bound_strcat(char *dest, const char *src); -DLL_EXPORT char *__bound_strncat(char *dest, const char *src, size_t n); -DLL_EXPORT char *__bound_strchr(const char *string, int ch); -DLL_EXPORT char *__bound_strrchr(const char *string, int ch); -DLL_EXPORT char *__bound_strdup(const char *s); - -#if defined(__arm__) && defined(__ARM_EABI__) -DLL_EXPORT void *__bound___aeabi_memcpy(void *dst, const void *src, size_t size); -DLL_EXPORT void *__bound___aeabi_memmove(void *dst, const void *src, size_t size); -DLL_EXPORT void *__bound___aeabi_memmove4(void *dst, const void *src, size_t size); -DLL_EXPORT void *__bound___aeabi_memmove8(void *dst, const void *src, size_t size); -DLL_EXPORT void *__bound___aeabi_memset(void *dst, int c, size_t size); -DLL_EXPORT void *__aeabi_memcpy(void *dst, const void *src, size_t size); -DLL_EXPORT void *__aeabi_memmove(void *dst, const void *src, size_t size); -DLL_EXPORT void *__aeabi_memmove4(void *dst, const void *src, size_t size); -DLL_EXPORT void *__aeabi_memmove8(void *dst, const void *src, size_t size); -DLL_EXPORT void *__aeabi_memset(void *dst, int c, size_t size); -#endif - -#if MALLOC_REDIR -#define BOUND_MALLOC(a) malloc_redir(a) -#define BOUND_MEMALIGN(a,b) memalign_redir(a,b) -#define BOUND_FREE(a) free_redir(a) -#define BOUND_REALLOC(a,b) realloc_redir(a,b) -#define BOUND_CALLOC(a,b) calloc_redir(a,b) -#else -#define BOUND_MALLOC(a) malloc(a) -#define BOUND_MEMALIGN(a,b) memalign(a,b) -#define BOUND_FREE(a) free(a) -#define BOUND_REALLOC(a,b) realloc(a,b) -#define BOUND_CALLOC(a,b) calloc(a,b) -DLL_EXPORT void *__bound_malloc(size_t size, const void *caller); -DLL_EXPORT void *__bound_memalign(size_t align, size_t size, const void *caller); -DLL_EXPORT void __bound_free(void *ptr, const void *caller); -DLL_EXPORT void *__bound_realloc(void *ptr, size_t size, const void *caller); -DLL_EXPORT void *__bound_calloc(size_t nmemb, size_t size); -#endif - -#define FREE_REUSE_SIZE (100) -static unsigned int free_reuse_index; -static void *free_reuse_list[FREE_REUSE_SIZE]; - -static Tree *tree = NULL; -#define TREE_REUSE (1) -#if TREE_REUSE -static Tree *tree_free_list; -#endif -static alloca_list_type *alloca_list; -static jmp_list_type *jmp_list; - -static unsigned char inited; -static unsigned char print_warn_ptr_add; -static unsigned char print_calls; -static unsigned char print_heap; -static unsigned char print_statistic; -static unsigned char no_strdup; -static unsigned char use_sem; -static int never_fatal; -#if HAVE_TLS_FUNC -#if defined(_WIN32) -static int no_checking = 0; -static DWORD no_checking_key; -#define NO_CHECKING_CHECK() if (!p) { \ - p = (int *) LocalAlloc(LPTR, sizeof(int)); \ - if (!p) bound_alloc_error("tls malloc"); \ - *p = 0; \ - TlsSetValue(no_checking_key, p); \ - } -#define NO_CHECKING_GET() ({ int *p = TlsGetValue(no_checking_key); \ - NO_CHECKING_CHECK(); \ - *p; \ - }) -#define NO_CHECKING_SET(v) { int *p = TlsGetValue(no_checking_key); \ - NO_CHECKING_CHECK(); \ - *p = v; \ - } -#else -static int no_checking = 0; -static pthread_key_t no_checking_key; -#define NO_CHECKING_CHECK() if (!p) { \ - p = (int *) BOUND_MALLOC(sizeof(int)); \ - if (!p) bound_alloc_error("tls malloc"); \ - *p = 0; \ - pthread_setspecific(no_checking_key, p); \ - } -#define NO_CHECKING_GET() ({ int *p = pthread_getspecific(no_checking_key); \ - NO_CHECKING_CHECK(); \ - *p; \ - }) -#define NO_CHECKING_SET(v) { int *p = pthread_getspecific(no_checking_key); \ - NO_CHECKING_CHECK(); \ - *p = v; \ - } -#endif -#elif HAVE_TLS_VAR -static __thread int no_checking = 0; -#define NO_CHECKING_GET() no_checking -#define NO_CHECKING_SET(v) no_checking = v -#else -static int no_checking = 0; -#define NO_CHECKING_GET() no_checking -#define NO_CHECKING_SET(v) no_checking = v -#endif -static char exec[100]; - -#if BOUND_STATISTIC -static unsigned long long bound_ptr_add_count; -static unsigned long long bound_ptr_indir1_count; -static unsigned long long bound_ptr_indir2_count; -static unsigned long long bound_ptr_indir4_count; -static unsigned long long bound_ptr_indir8_count; -static unsigned long long bound_ptr_indir12_count; -static unsigned long long bound_ptr_indir16_count; -static unsigned long long bound_local_new_count; -static unsigned long long bound_local_delete_count; -static unsigned long long bound_malloc_count; -static unsigned long long bound_calloc_count; -static unsigned long long bound_realloc_count; -static unsigned long long bound_free_count; -static unsigned long long bound_memalign_count; -static unsigned long long bound_mmap_count; -static unsigned long long bound_munmap_count; -static unsigned long long bound_alloca_count; -static unsigned long long bound_setjmp_count; -static unsigned long long bound_longjmp_count; -static unsigned long long bound_mempcy_count; -static unsigned long long bound_memcmp_count; -static unsigned long long bound_memmove_count; -static unsigned long long bound_memset_count; -static unsigned long long bound_strlen_count; -static unsigned long long bound_strcpy_count; -static unsigned long long bound_strncpy_count; -static unsigned long long bound_strcmp_count; -static unsigned long long bound_strncmp_count; -static unsigned long long bound_strcat_count; -static unsigned long long bound_strncat_count; -static unsigned long long bound_strchr_count; -static unsigned long long bound_strrchr_count; -static unsigned long long bound_strdup_count; -static unsigned long long bound_not_found; -#define INCR_COUNT(x) ++x -#else -#define INCR_COUNT(x) -#endif -#if BOUND_STATISTIC_SPLAY -static unsigned long long bound_splay; -static unsigned long long bound_splay_end; -static unsigned long long bound_splay_insert; -static unsigned long long bound_splay_delete; -#define INCR_COUNT_SPLAY(x) ++x -#else -#define INCR_COUNT_SPLAY(x) -#endif - -int tcc_backtrace(const char *fmt, ...); - -/* print a bound error message */ -#define bound_warning(...) \ - do { \ - WAIT_SEM (); \ - tcc_backtrace("^bcheck.c^BCHECK: " __VA_ARGS__); \ - POST_SEM (); \ - } while (0) - -#define bound_error(...) \ - do { \ - bound_warning(__VA_ARGS__); \ - if (never_fatal == 0) \ - exit(255); \ - } while (0) - -#define bounds_loc(fp, ...) \ - do { \ - WAIT_SEM (); \ - tcc_backtrace("^bcheck.c^\001" __VA_ARGS__); \ - POST_SEM (); \ - } while (0) - -static void bound_alloc_error(const char *s) -{ - fprintf(stderr,"FATAL: %s\n",s); - exit (1); -} - -static void bound_not_found_warning(const char *file, const char *function, - void *ptr) -{ - dprintf(stderr, "%s%s, %s(): Not found %p\n", exec, file, function, ptr); -} - -static void fetch_and_add(int* variable, int value) -{ -#if defined __i386__ || defined __x86_64__ - __asm__ volatile("lock; addl %0, %1" - : "+r" (value), "+m" (*variable) // input+output - : // No input-only - : "memory" - ); -#elif defined __arm__ - extern void fetch_and_add_arm(int* variable, int value); - fetch_and_add_arm(variable, value); -#elif defined __aarch64__ - extern void fetch_and_add_arm64(int* variable, int value); - fetch_and_add_arm64(variable, value); -#elif defined __riscv - extern void fetch_and_add_riscv64(int* variable, int value); - fetch_and_add_riscv64(variable, value); -#else - *variable += value; -#endif -} - -/* enable/disable checking. This can be used in signal handlers. */ -void __bounds_checking (int no_check) -{ -#if HAVE_TLS_FUNC || HAVE_TLS_VAR - NO_CHECKING_SET(NO_CHECKING_GET() + no_check); -#else - fetch_and_add (&no_checking, no_check); -#endif -} - -void __bound_checking_lock(void) -{ - WAIT_SEM (); -} - -void __bound_checking_unlock(void) -{ - POST_SEM (); -} - -/* enable/disable checking. This can be used in signal handlers. */ -void __bound_never_fatal (int neverfatal) -{ - fetch_and_add (&never_fatal, neverfatal); -} - -/* return '(p + offset)' for pointer arithmetic (a pointer can reach - the end of a region in this case */ -void * __bound_ptr_add(void *p, size_t offset) -{ - size_t addr = (size_t)p; - - if (NO_CHECKING_GET()) - return p + offset; - - dprintf(stderr, "%s, %s(): %p 0x%lx\n", - __FILE__, __FUNCTION__, p, (unsigned long)offset); - - WAIT_SEM (); - INCR_COUNT(bound_ptr_add_count); - if (tree) { - addr -= tree->start; - if (addr >= tree->size) { - addr = (size_t)p; - tree = splay (addr, tree); - addr -= tree->start; - } - if (addr >= tree->size) { - addr = (size_t)p; - tree = splay_end (addr, tree); - addr -= tree->start; - } - if (addr <= tree->size) { - if (tree->is_invalid || addr + offset > tree->size) { - POST_SEM (); - if (print_warn_ptr_add) - bound_warning("%p is outside of the region (0x%lx..0x%lx)", - p + offset, (long)tree->start, - (long)(tree->start + tree->size - 1)); - if (never_fatal <= 0) - return INVALID_POINTER; /* return an invalid pointer */ - return p + offset; - } - } - else if (p) { /* Allow NULL + offset. offsetoff is using it. */ - INCR_COUNT(bound_not_found); - POST_SEM (); - bound_not_found_warning (__FILE__, __FUNCTION__, p); - return p + offset; - } - } - POST_SEM (); - return p + offset; -} - -/* return '(p + offset)' for pointer indirection (the resulting must - be strictly inside the region */ -#define BOUND_PTR_INDIR(dsize) \ -void * __bound_ptr_indir ## dsize (void *p, size_t offset) \ -{ \ - size_t addr = (size_t)p; \ - \ - if (NO_CHECKING_GET()) \ - return p + offset; \ - \ - dprintf(stderr, "%s, %s(): %p 0x%lx\n", \ - __FILE__, __FUNCTION__, p, (unsigned long)offset); \ - WAIT_SEM (); \ - INCR_COUNT(bound_ptr_indir ## dsize ## _count); \ - if (tree) { \ - addr -= tree->start; \ - if (addr >= tree->size) { \ - addr = (size_t)p; \ - tree = splay (addr, tree); \ - addr -= tree->start; \ - } \ - if (addr >= tree->size) { \ - addr = (size_t)p; \ - tree = splay_end (addr, tree); \ - addr -= tree->start; \ - } \ - if (addr <= tree->size) { \ - if (tree->is_invalid || addr + offset + dsize > tree->size) { \ - POST_SEM (); \ - bound_warning("%p is outside of the region (0x%lx..0x%lx)", \ - p + offset, (long)tree->start, \ - (long)(tree->start + tree->size - 1)); \ - if (never_fatal <= 0) \ - return INVALID_POINTER; /* return an invalid pointer */ \ - return p + offset; \ - } \ - } \ - else { \ - INCR_COUNT(bound_not_found); \ - POST_SEM (); \ - bound_not_found_warning (__FILE__, __FUNCTION__, p); \ - return p + offset; \ - } \ - } \ - POST_SEM (); \ - return p + offset; \ -} - -BOUND_PTR_INDIR(1) -BOUND_PTR_INDIR(2) -BOUND_PTR_INDIR(4) -BOUND_PTR_INDIR(8) -BOUND_PTR_INDIR(12) -BOUND_PTR_INDIR(16) - -/* Needed when using ...libtcc1-usegcc=yes in lib/Makefile */ -#if (defined(__GNUC__) && (__GNUC__ >= 6)) || defined(__clang__) -/* - * At least gcc 6.2 complains when __builtin_frame_address is used with - * nonzero argument. - */ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wframe-address" -#endif - -/* return the frame pointer of the caller */ -#define GET_CALLER_FP(fp)\ -{\ - fp = (size_t)__builtin_frame_address(1);\ -} - -/* called when entering a function to add all the local regions */ -void FASTCALL __bound_local_new(void *p1) -{ - size_t addr, fp, *p = p1; - - if (NO_CHECKING_GET()) - return; - GET_CALLER_FP(fp); - dprintf(stderr, "%s, %s(): p1=%p fp=%p\n", - __FILE__, __FUNCTION__, p, (void *)fp); - WAIT_SEM (); - while ((addr = p[0])) { - INCR_COUNT(bound_local_new_count); - tree = splay_insert(addr + fp, p[1], tree); - p += 2; - } - POST_SEM (); -#if BOUND_DEBUG - if (print_calls) { - p = p1; - while ((addr = p[0])) { - dprintf(stderr, "%s, %s(): %p 0x%lx\n", - __FILE__, __FUNCTION__, - (void *) (addr + fp), (unsigned long) p[1]); - p += 2; - } - } -#endif -} - -/* called when leaving a function to delete all the local regions */ -void FASTCALL __bound_local_delete(void *p1) -{ - size_t addr, fp, *p = p1; - - if (NO_CHECKING_GET()) - return; - GET_CALLER_FP(fp); - dprintf(stderr, "%s, %s(): p1=%p fp=%p\n", - __FILE__, __FUNCTION__, p, (void *)fp); - WAIT_SEM (); - while ((addr = p[0])) { - INCR_COUNT(bound_local_delete_count); - tree = splay_delete(addr + fp, tree); - p += 2; - } - if (alloca_list) { - alloca_list_type *last = NULL; - alloca_list_type *cur = alloca_list; - - do { - if (cur->fp == fp) { - if (last) - last->next = cur->next; - else - alloca_list = cur->next; - tree = splay_delete ((size_t) cur->p, tree); - dprintf(stderr, "%s, %s(): remove alloca/vla %p\n", - __FILE__, __FUNCTION__, cur->p); - BOUND_FREE (cur); - cur = last ? last->next : alloca_list; - } - else { - last = cur; - cur = cur->next; - } - } while (cur); - } - if (jmp_list) { - jmp_list_type *last = NULL; - jmp_list_type *cur = jmp_list; - - do { - if (cur->fp == fp) { - if (last) - last->next = cur->next; - else - jmp_list = cur->next; - dprintf(stderr, "%s, %s(): remove setjmp %p\n", - __FILE__, __FUNCTION__, cur->penv); - BOUND_FREE (cur); - cur = last ? last->next : jmp_list; - } - else { - last = cur; - cur = cur->next; - } - } while (cur); - } - - POST_SEM (); -#if BOUND_DEBUG - if (print_calls) { - p = p1; - while ((addr = p[0])) { - if (addr != 1) { - dprintf(stderr, "%s, %s(): %p 0x%lx\n", - __FILE__, __FUNCTION__, - (void *) (addr + fp), (unsigned long) p[1]); - } - p+= 2; - } - } -#endif -} - -/* used by alloca */ -void __bound_new_region(void *p, size_t size) -{ - size_t fp; - alloca_list_type *last; - alloca_list_type *cur; - alloca_list_type *new; - - if (NO_CHECKING_GET()) - return; - - dprintf(stderr, "%s, %s(): %p, 0x%lx\n", - __FILE__, __FUNCTION__, p, (unsigned long)size); - GET_CALLER_FP (fp); - new = BOUND_MALLOC (sizeof (alloca_list_type)); - WAIT_SEM (); - INCR_COUNT(bound_alloca_count); - last = NULL; - cur = alloca_list; - while (cur) { -#if defined(__i386__) || (defined(__arm__) && !defined(__ARM_EABI__)) - int align = 4; -#elif defined(__arm__) - int align = 8; -#else - int align = 16; -#endif - void *cure = (void *)((char *)cur->p + ((cur->size + align) & -align)); - void *pe = (void *)((char *)p + ((size + align) & -align)); - if (cur->fp == fp && ((cur->p <= p && cure > p) || - (p <= cur->p && pe > cur->p))) { - if (last) - last->next = cur->next; - else - alloca_list = cur->next; - tree = splay_delete((size_t)cur->p, tree); - break; - } - last = cur; - cur = cur->next; - } - tree = splay_insert((size_t)p, size, tree); - if (new) { - new->fp = fp; - new->p = p; - new->size = size; - new->next = alloca_list; - alloca_list = new; - } - POST_SEM (); - if (cur) { - dprintf(stderr, "%s, %s(): remove alloca/vla %p\n", - __FILE__, __FUNCTION__, cur->p); - BOUND_FREE (cur); - } -} - -void __bound_setjmp(jmp_buf env) -{ - jmp_list_type *jl; - void *e = (void *) env; - - if (NO_CHECKING_GET() == 0) { - dprintf(stderr, "%s, %s(): %p\n", __FILE__, __FUNCTION__, e); - WAIT_SEM (); - INCR_COUNT(bound_setjmp_count); - jl = jmp_list; - while (jl) { - if (jl->penv == e) - break; - jl = jl->next; - } - if (jl == NULL) { - jl = BOUND_MALLOC (sizeof (jmp_list_type)); - if (jl) { - jl->penv = e; - jl->next = jmp_list; - jmp_list = jl; - } - } - if (jl) { - size_t fp; - - GET_CALLER_FP (fp); - jl->fp = fp; - jl->end_fp = (size_t)__builtin_frame_address(0); - BOUND_GET_TID(jl->tid); - } - POST_SEM (); - } -} - -static void __bound_long_jump(jmp_buf env, int val, int sig, const char *func) -{ - jmp_list_type *jl; - void *e; - BOUND_TID_TYPE tid; - - if (NO_CHECKING_GET() == 0) { - e = (void *)env; - BOUND_GET_TID(tid); - dprintf(stderr, "%s, %s(): %p\n", __FILE__, func, e); - WAIT_SEM(); - INCR_COUNT(bound_longjmp_count); - jl = jmp_list; - while (jl) { - if (jl->penv == e && jl->tid == tid) { - size_t start_fp = (size_t)__builtin_frame_address(0); - size_t end_fp = jl->end_fp; - jmp_list_type *cur = jmp_list; - jmp_list_type *last = NULL; - - while (cur->penv != e || cur->tid != tid) { - if (cur->tid == tid) { - dprintf(stderr, "%s, %s(): remove setjmp %p\n", - __FILE__, func, cur->penv); - if (last) - last->next = cur->next; - else - jmp_list = cur->next; - BOUND_FREE (cur); - cur = last ? last->next : jmp_list; - } - else { - last = cur; - cur = cur->next; - } - } - for (;;) { - Tree *t = tree; - alloca_list_type *last; - alloca_list_type *cur; - - while (t && (t->start < start_fp || t->start > end_fp)) - if (t->start < start_fp) - t = t->right; - else - t = t->left; - if (t == NULL) - break; - last = NULL; - cur = alloca_list; - while (cur) { - if ((size_t) cur->p == t->start) { - dprintf(stderr, "%s, %s(): remove alloca/vla %p\n", - __FILE__, func, cur->p); - if (last) - last->next = cur->next; - else - alloca_list = cur->next; - BOUND_FREE (cur); - break; - } - last = cur; - cur = cur->next; - } - dprintf(stderr, "%s, %s(): delete %p\n", - __FILE__, func, (void *) t->start); - tree = splay_delete(t->start, tree); - } - break; - } - jl = jl->next; - } - POST_SEM(); - } -#if !defined(_WIN32) - sig ? siglongjmp(env, val) : -#endif - longjmp (env, val); -} - -void __bound_longjmp(jmp_buf env, int val) -{ - __bound_long_jump(env,val, 0, __FUNCTION__); -} - -#if !defined(_WIN32) -void __bound_siglongjmp(jmp_buf env, int val) -{ - __bound_long_jump(env,val, 1, __FUNCTION__); -} -#endif - -#if (defined(__GNUC__) && (__GNUC__ >= 6)) || defined(__clang__) -#pragma GCC diagnostic pop -#endif - -void __bound_init(size_t *p, int mode) -{ - dprintf(stderr, "%s, %s(): start %s\n", __FILE__, __FUNCTION__, - mode < 0 ? "lazy" : mode == 0 ? "normal use" : "for -run"); - - if (inited) { - WAIT_SEM(); - goto add_bounds; - } - inited = 1; - -#if HAVE_TLS_FUNC -#if defined(_WIN32) - no_checking_key = TlsAlloc(); - TlsSetValue(no_checking_key, &no_checking); -#else - pthread_key_create(&no_checking_key, NULL); - pthread_setspecific(no_checking_key, &no_checking); -#endif -#endif - NO_CHECKING_SET(1); - - print_warn_ptr_add = getenv ("TCC_BOUNDS_WARN_POINTER_ADD") != NULL; - print_calls = getenv ("TCC_BOUNDS_PRINT_CALLS") != NULL; - print_heap = getenv ("TCC_BOUNDS_PRINT_HEAP") != NULL; - print_statistic = getenv ("TCC_BOUNDS_PRINT_STATISTIC") != NULL; - never_fatal = getenv ("TCC_BOUNDS_NEVER_FATAL") != NULL; - - INIT_SEM (); - -#if MALLOC_REDIR - { - void *addr = mode > 0 ? RTLD_DEFAULT : RTLD_NEXT; - - /* tcc -run required RTLD_DEFAULT. Normal usage requires RTLD_NEXT, - but using RTLD_NEXT with -run segfaults on MacOS in dyld as the - generated code segment isn't registered with dyld and hence the - caller image of dlsym isn't known to it */ - *(void **) (&malloc_redir) = dlsym (addr, "malloc"); - if (malloc_redir == NULL) { - dprintf(stderr, "%s, %s(): use RTLD_DEFAULT\n", - __FILE__, __FUNCTION__); - addr = RTLD_DEFAULT; - *(void **) (&malloc_redir) = dlsym (addr, "malloc"); - } - *(void **) (&calloc_redir) = dlsym (addr, "calloc"); - *(void **) (&free_redir) = dlsym (addr, "free"); - *(void **) (&realloc_redir) = dlsym (addr, "realloc"); - *(void **) (&memalign_redir) = dlsym (addr, "memalign"); - dprintf(stderr, "%s, %s(): malloc_redir %p\n", - __FILE__, __FUNCTION__, malloc_redir); - dprintf(stderr, "%s, %s(): free_redir %p\n", - __FILE__, __FUNCTION__, free_redir); - dprintf(stderr, "%s, %s(): realloc_redir %p\n", - __FILE__, __FUNCTION__, realloc_redir); - dprintf(stderr, "%s, %s(): memalign_redir %p\n", - __FILE__, __FUNCTION__, memalign_redir); - if (malloc_redir == NULL || free_redir == NULL) - bound_alloc_error ("Cannot redirect malloc/free"); -#if HAVE_PTHREAD_CREATE - *(void **) (&pthread_create_redir) = dlsym (addr, "pthread_create"); - dprintf(stderr, "%s, %s(): pthread_create_redir %p\n", - __FILE__, __FUNCTION__, pthread_create_redir); - if (pthread_create_redir == NULL) - bound_alloc_error ("Cannot redirect pthread_create"); -#endif -#if HAVE_SIGNAL - *(void **) (&signal_redir) = dlsym (addr, "signal"); - dprintf(stderr, "%s, %s(): signal_redir %p\n", - __FILE__, __FUNCTION__, signal_redir); - if (signal_redir == NULL) - bound_alloc_error ("Cannot redirect signal"); -#endif -#if HAVE_SIGACTION - *(void **) (&sigaction_redir) = dlsym (addr, "sigaction"); - dprintf(stderr, "%s, %s(): sigaction_redir %p\n", - __FILE__, __FUNCTION__, sigaction_redir); - if (sigaction_redir == NULL) - bound_alloc_error ("Cannot redirect sigaction"); -#endif -#if HAVE_FORK - *(void **) (&fork_redir) = dlsym (addr, "fork"); - dprintf(stderr, "%s, %s(): fork_redir %p\n", - __FILE__, __FUNCTION__, fork_redir); - if (fork_redir == NULL) - bound_alloc_error ("Cannot redirect fork"); -#endif - } -#endif - -#ifdef __linux__ - { - FILE *fp; - unsigned char found; - unsigned long start; - unsigned long end; - unsigned long ad = - (unsigned long) __builtin_return_address(0); - char line[1000]; - - /* Display exec name. Usefull when a lot of code is compiled with tcc */ - fp = fopen ("/proc/self/comm", "r"); - if (fp) { - memset (exec, 0, sizeof(exec)); - fread (exec, 1, sizeof(exec) - 2, fp); - if (strchr(exec,'\n')) - *strchr(exec,'\n') = '\0'; - strcat (exec, ":"); - fclose (fp); - } - /* check if dlopen is used (is threre a better way?) */ - found = 0; - fp = fopen ("/proc/self/maps", "r"); - if (fp) { - while (fgets (line, sizeof(line), fp)) { - if (sscanf (line, "%lx-%lx", &start, &end) == 2 && - ad >= start && ad < end) { - found = 1; - break; - } - if (strstr (line,"[heap]")) - break; - } - fclose (fp); - } - if (found == 0) { - use_sem = 1; - no_strdup = 1; - } - } -#endif - - WAIT_SEM (); - -#if HAVE_CTYPE -#ifdef __APPLE__ - tree = splay_insert((size_t) &_DefaultRuneLocale, - sizeof (_DefaultRuneLocale), tree); -#else - /* XXX: Does not work if locale is changed */ - tree = splay_insert((size_t) __ctype_b_loc(), - sizeof (unsigned short *), tree); - tree = splay_insert((size_t) (*__ctype_b_loc() - 128), - 384 * sizeof (unsigned short), tree); - tree = splay_insert((size_t) __ctype_tolower_loc(), - sizeof (__int32_t *), tree); - tree = splay_insert((size_t) (*__ctype_tolower_loc() - 128), - 384 * sizeof (__int32_t), tree); - tree = splay_insert((size_t) __ctype_toupper_loc(), - sizeof (__int32_t *), tree); - tree = splay_insert((size_t) (*__ctype_toupper_loc() - 128), - 384 * sizeof (__int32_t), tree); -#endif -#endif -#if HAVE_ERRNO - tree = splay_insert((size_t) (&errno), sizeof (int), tree); -#endif - -add_bounds: - if (!p) - goto no_bounds; - - /* add all static bound check values */ - while (p[0] != 0) { - tree = splay_insert(p[0], p[1], tree); -#if BOUND_DEBUG - dprintf(stderr, "%s, %s(): static var %p 0x%lx\n", - __FILE__, __FUNCTION__, - (void *) p[0], (unsigned long) p[1]); -#endif - p += 2; - } -no_bounds: - - POST_SEM (); - NO_CHECKING_SET(0); - dprintf(stderr, "%s, %s(): end\n\n", __FILE__, __FUNCTION__); -} - -void -#if (defined(__GLIBC__) && (__GLIBC_MINOR__ >= 4)) || defined(_WIN32) -__attribute__((constructor)) -#endif -__bound_main_arg(int argc, char **argv, char **envp) -{ - __bound_init (0, -1); - if (argc && argv) { - int i; - - WAIT_SEM (); - for (i = 0; i < argc; i++) - tree = splay_insert((size_t) argv[i], strlen (argv[i]) + 1, tree); - tree = splay_insert((size_t) argv, (argc + 1) * sizeof(char *), tree); - POST_SEM (); -#if BOUND_DEBUG - if (print_calls) { - for (i = 0; i < argc; i++) - dprintf(stderr, "%s, %s(): arg %p 0x%lx\n", - __FILE__, __FUNCTION__, - argv[i], (unsigned long)(strlen (argv[i]) + 1)); - dprintf(stderr, "%s, %s(): argv %p %d\n", - __FILE__, __FUNCTION__, argv, - (int)((argc + 1) * sizeof(char *))); - } -#endif - } - - if (envp && *envp) { - char **p = envp; - - WAIT_SEM (); - while (*p) { - tree = splay_insert((size_t) *p, strlen (*p) + 1, tree); - ++p; - } - tree = splay_insert((size_t) envp, (++p - envp) * sizeof(char *), tree); - POST_SEM (); -#if BOUND_DEBUG - if (print_calls) { - p = envp; - while (*p) { - dprintf(stderr, "%s, %s(): env %p 0x%lx\n", - __FILE__, __FUNCTION__, - *p, (unsigned long)(strlen (*p) + 1)); - ++p; - } - dprintf(stderr, "%s, %s(): environ %p %d\n", - __FILE__, __FUNCTION__, envp, - (int)((++p - envp) * sizeof(char *))); - } -#endif - } -} - -void __attribute__((destructor)) __bound_exit(void) -{ - int i; - static const char * const alloc_type[] = { - "", "malloc", "calloc", "realloc", "memalign", "strdup" - }; - - dprintf(stderr, "%s, %s():\n", __FILE__, __FUNCTION__); - - if (inited) { -#if !defined(_WIN32) && !defined(__APPLE__) && !defined CONFIG_TCC_MUSL && \ - !defined(__OpenBSD__) && !defined(__FreeBSD__) && !defined(__NetBSD__) && \ - !defined(__ANDROID__) - if (print_heap) { - extern void __libc_freeres (void); - __libc_freeres (); - } -#endif - - NO_CHECKING_SET(1); - - TRY_SEM (); - while (alloca_list) { - alloca_list_type *next = alloca_list->next; - - tree = splay_delete ((size_t) alloca_list->p, tree); - BOUND_FREE (alloca_list); - alloca_list = next; - } - while (jmp_list) { - jmp_list_type *next = jmp_list->next; - - BOUND_FREE (jmp_list); - jmp_list = next; - } - for (i = 0; i < FREE_REUSE_SIZE; i++) { - if (free_reuse_list[i]) { - tree = splay_delete ((size_t) free_reuse_list[i], tree); - BOUND_FREE (free_reuse_list[i]); - } - } - while (tree) { - if (print_heap && tree->type != 0) - fprintf (stderr, "%s, %s(): %s found size %lu\n", - __FILE__, __FUNCTION__, alloc_type[tree->type], - (unsigned long) tree->size); - tree = splay_delete (tree->start, tree); - } -#if TREE_REUSE - while (tree_free_list) { - Tree *next = tree_free_list->left; - BOUND_FREE (tree_free_list); - tree_free_list = next; - } -#endif - POST_SEM (); - EXIT_SEM (); -#if HAVE_TLS_FUNC -#if defined(_WIN32) - TlsFree(no_checking_key); -#else - pthread_key_delete(no_checking_key); -#endif -#endif - inited = 0; - if (print_statistic) { -#if BOUND_STATISTIC - fprintf (stderr, "bound_ptr_add_count %llu\n", bound_ptr_add_count); - fprintf (stderr, "bound_ptr_indir1_count %llu\n", bound_ptr_indir1_count); - fprintf (stderr, "bound_ptr_indir2_count %llu\n", bound_ptr_indir2_count); - fprintf (stderr, "bound_ptr_indir4_count %llu\n", bound_ptr_indir4_count); - fprintf (stderr, "bound_ptr_indir8_count %llu\n", bound_ptr_indir8_count); - fprintf (stderr, "bound_ptr_indir12_count %llu\n", bound_ptr_indir12_count); - fprintf (stderr, "bound_ptr_indir16_count %llu\n", bound_ptr_indir16_count); - fprintf (stderr, "bound_local_new_count %llu\n", bound_local_new_count); - fprintf (stderr, "bound_local_delete_count %llu\n", bound_local_delete_count); - fprintf (stderr, "bound_malloc_count %llu\n", bound_malloc_count); - fprintf (stderr, "bound_calloc_count %llu\n", bound_calloc_count); - fprintf (stderr, "bound_realloc_count %llu\n", bound_realloc_count); - fprintf (stderr, "bound_free_count %llu\n", bound_free_count); - fprintf (stderr, "bound_memalign_count %llu\n", bound_memalign_count); - fprintf (stderr, "bound_mmap_count %llu\n", bound_mmap_count); - fprintf (stderr, "bound_munmap_count %llu\n", bound_munmap_count); - fprintf (stderr, "bound_alloca_count %llu\n", bound_alloca_count); - fprintf (stderr, "bound_setjmp_count %llu\n", bound_setjmp_count); - fprintf (stderr, "bound_longjmp_count %llu\n", bound_longjmp_count); - fprintf (stderr, "bound_mempcy_count %llu\n", bound_mempcy_count); - fprintf (stderr, "bound_memcmp_count %llu\n", bound_memcmp_count); - fprintf (stderr, "bound_memmove_count %llu\n", bound_memmove_count); - fprintf (stderr, "bound_memset_count %llu\n", bound_memset_count); - fprintf (stderr, "bound_strlen_count %llu\n", bound_strlen_count); - fprintf (stderr, "bound_strcpy_count %llu\n", bound_strcpy_count); - fprintf (stderr, "bound_strncpy_count %llu\n", bound_strncpy_count); - fprintf (stderr, "bound_strcmp_count %llu\n", bound_strcmp_count); - fprintf (stderr, "bound_strncmp_count %llu\n", bound_strncmp_count); - fprintf (stderr, "bound_strcat_count %llu\n", bound_strcat_count); - fprintf (stderr, "bound_strncat_count %llu\n", bound_strncat_count); - fprintf (stderr, "bound_strchr_count %llu\n", bound_strchr_count); - fprintf (stderr, "bound_strrchr_count %llu\n", bound_strrchr_count); - fprintf (stderr, "bound_strdup_count %llu\n", bound_strdup_count); - fprintf (stderr, "bound_not_found %llu\n", bound_not_found); -#endif -#if BOUND_STATISTIC_SPLAY - fprintf (stderr, "bound_splay %llu\n", bound_splay); - fprintf (stderr, "bound_splay_end %llu\n", bound_splay_end); - fprintf (stderr, "bound_splay_insert %llu\n", bound_splay_insert); - fprintf (stderr, "bound_splay_delete %llu\n", bound_splay_delete); -#endif - } - } -} - -void __bound_exit_dll(size_t *p) -{ - dprintf(stderr, "%s, %s()\n", __FILE__, __FUNCTION__); - - if (p) { - WAIT_SEM (); - while (p[0] != 0) { - tree = splay_delete(p[0], tree); -#if BOUND_DEBUG - if (print_calls) { - dprintf(stderr, "%s, %s(): remove static var %p 0x%lx\n", - __FILE__, __FUNCTION__, - (void *) p[0], (unsigned long) p[1]); - } -#endif - p += 2; - } - POST_SEM (); - } -} - -#if HAVE_PTHREAD_CREATE -typedef struct { - void *(*start_routine) (void *); - void *arg; - sigset_t old_mask; -} bound_thread_create_type; - -static void *bound_thread_create(void *bdata) -{ - bound_thread_create_type *data = (bound_thread_create_type *) bdata; - void *retval; -#if HAVE_TLS_FUNC - int *p = (int *) BOUND_MALLOC(sizeof(int)); - - if (!p) bound_alloc_error("bound_thread_create malloc"); - *p = 0; - pthread_setspecific(no_checking_key, p); -#endif - pthread_sigmask(SIG_SETMASK, &data->old_mask, NULL); - retval = data->start_routine(data->arg); -#if HAVE_TLS_FUNC - pthread_setspecific(no_checking_key, NULL); - BOUND_FREE (p); -#endif - BOUND_FREE (data); - return retval; -} - -int pthread_create(pthread_t *thread, const pthread_attr_t *attr, - void *(*start_routine) (void *), void *arg) -{ - int retval; - bound_thread_create_type *data; - sigset_t mask; - sigset_t old_mask; - - use_sem = 1; - dprintf (stderr, "%s, %s()\n", __FILE__, __FUNCTION__); - sigfillset(&mask); - pthread_sigmask(SIG_SETMASK, &mask, &old_mask); - data = (bound_thread_create_type *) BOUND_MALLOC(sizeof(bound_thread_create_type)); - if (!data) bound_alloc_error("bound_thread_create malloc"); - data->start_routine = start_routine; - data->arg = arg; - data->old_mask = old_mask; - retval = pthread_create_redir(thread, attr, bound_thread_create, data); - pthread_sigmask(SIG_SETMASK, &old_mask, NULL); - return retval; -} -#endif - -#if HAVE_SIGNAL || HAVE_SIGACTION -typedef union { -#if HAVE_SIGNAL - bound_sig signal_handler; -#endif -#if HAVE_SIGACTION - void (*sig_handler)(int); - void (*sig_sigaction)(int, siginfo_t *, void *); -#endif -} bound_sig_type; - -static unsigned char bound_sig_used[NSIG]; -static bound_sig_type bound_sig_data[NSIG]; -#endif - -#if HAVE_SIGNAL -static void signal_handler(int sig) -{ - __bounds_checking(1); - bound_sig_data[sig].signal_handler(sig); - __bounds_checking(-1); -} - -bound_sig signal(int signum, bound_sig handler) -{ - bound_sig retval; - - dprintf (stderr, "%s, %s() %d %p\n", __FILE__, __FUNCTION__, - signum, handler); - retval = signal_redir(signum, handler ? signal_handler : handler); - if (retval != SIG_ERR) { - if (bound_sig_used[signum]) - retval = bound_sig_data[signum].signal_handler; - if (handler) { - bound_sig_used[signum] = 1; - bound_sig_data[signum].signal_handler = handler; - } - } - return retval; -} -#endif - -#if HAVE_SIGACTION -static void sig_handler(int sig) -{ - __bounds_checking(1); - bound_sig_data[sig].sig_handler(sig); - __bounds_checking(-1); -} - -static void sig_sigaction(int sig, siginfo_t *info, void *ucontext) -{ - __bounds_checking(1); - bound_sig_data[sig].sig_sigaction(sig, info, ucontext); - __bounds_checking(-1); -} - -int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact) -{ - int retval; - struct sigaction nact, oact; - - dprintf (stderr, "%s, %s() %d %p %p\n", __FILE__, __FUNCTION__, - signum, act, oldact); - - if (sigaction_redir == NULL) - __bound_init(0,-1); - - if (act) { - nact = *act; - if (nact.sa_flags & SA_SIGINFO) - nact.sa_sigaction = sig_sigaction; - else - nact.sa_handler = sig_handler; - retval = sigaction_redir(signum, &nact, &oact); - } - else - retval = sigaction_redir(signum, act, &oact); - if (retval >= 0) { - if (bound_sig_used[signum]) { - if (oact.sa_flags & SA_SIGINFO) - oact.sa_sigaction = bound_sig_data[signum].sig_sigaction; - else - oact.sa_handler = bound_sig_data[signum].sig_handler; - } - if (oldact) { - *oldact = oact; - } - if (act) { - bound_sig_used[signum] = 1; - if (act->sa_flags & SA_SIGINFO) - bound_sig_data[signum].sig_sigaction = act->sa_sigaction; - else - bound_sig_data[signum].sig_handler = act->sa_handler; - } - } - return retval; -} -#endif - -#if HAVE_FORK -pid_t fork(void) -{ - pid_t retval; - - WAIT_SEM(); - retval = (*fork_redir)(); - if (retval == 0) - INIT_SEM(); - else - POST_SEM(); - return retval; -} -#endif - -#if MALLOC_REDIR -void *malloc(size_t size) -#else -void *__bound_malloc(size_t size, const void *caller) -#endif -{ - void *ptr; - -#if MALLOC_REDIR - /* This will catch the first dlsym call from __bound_init */ - if (malloc_redir == NULL) { - __bound_init (0, -1); - if (malloc_redir == NULL) { - ptr = &initial_pool[pool_index]; - pool_index = (pool_index + size + 15) & ~15; - if (pool_index >= sizeof (initial_pool)) - bound_alloc_error ("initial memory pool too small"); - dprintf (stderr, "%s, %s(): initial %p, 0x%lx\n", - __FILE__, __FUNCTION__, ptr, (unsigned long)size); - return ptr; - } - } -#endif - /* we allocate one more byte to ensure the regions will be - separated by at least one byte. With the glibc malloc, it may - be in fact not necessary */ - ptr = BOUND_MALLOC (size + 1); - dprintf(stderr, "%s, %s(): %p, 0x%lx\n", - __FILE__, __FUNCTION__, ptr, (unsigned long)size); - - if (inited && NO_CHECKING_GET() == 0) { - WAIT_SEM (); - INCR_COUNT(bound_malloc_count); - - if (ptr) { - tree = splay_insert ((size_t) ptr, size ? size : size + 1, tree); - if (tree && tree->start == (size_t) ptr) - tree->type = TCC_TYPE_MALLOC; - } - POST_SEM (); - } - return ptr; -} - -#if MALLOC_REDIR -void *memalign(size_t align, size_t size) -#else -void *__bound_memalign(size_t align, size_t size, const void *caller) -#endif -{ - void *ptr; - -#if HAVE_MEMALIGN - /* we allocate one more byte to ensure the regions will be - separated by at least one byte. With the glibc malloc, it may - be in fact not necessary */ - ptr = BOUND_MEMALIGN(align, size + 1); -#else - if (align > 4) { - /* XXX: handle it ? */ - ptr = NULL; - } else { - /* we suppose that malloc aligns to at least four bytes */ - ptr = BOUND_MALLOC(size + 1); - } -#endif - dprintf(stderr, "%s, %s(): %p, 0x%lx\n", - __FILE__, __FUNCTION__, ptr, (unsigned long)size); - - if (NO_CHECKING_GET() == 0) { - WAIT_SEM (); - INCR_COUNT(bound_memalign_count); - - if (ptr) { - tree = splay_insert((size_t) ptr, size ? size : size + 1, tree); - if (tree && tree->start == (size_t) ptr) - tree->type = TCC_TYPE_MEMALIGN; - } - POST_SEM (); - } - return ptr; -} - -#if MALLOC_REDIR -void free(void *ptr) -#else -void __bound_free(void *ptr, const void *caller) -#endif -{ - size_t addr = (size_t) ptr; - void *p; - - if (ptr == NULL || tree == NULL -#if MALLOC_REDIR - || ((unsigned char *) ptr >= &initial_pool[0] && - (unsigned char *) ptr < &initial_pool[sizeof(initial_pool)]) -#endif - ) - return; - - dprintf(stderr, "%s, %s(): %p\n", __FILE__, __FUNCTION__, ptr); - - if (inited && NO_CHECKING_GET() == 0) { - WAIT_SEM (); - INCR_COUNT(bound_free_count); - tree = splay (addr, tree); - if (tree->start == addr) { - if (tree->is_invalid) { - POST_SEM (); - bound_error("freeing invalid region"); - return; - } - tree->is_invalid = 1; - memset (ptr, 0x5a, tree->size); - p = free_reuse_list[free_reuse_index]; - free_reuse_list[free_reuse_index] = ptr; - free_reuse_index = (free_reuse_index + 1) % FREE_REUSE_SIZE; - if (p) - tree = splay_delete((size_t)p, tree); - ptr = p; - } - POST_SEM (); - } - BOUND_FREE (ptr); -} - -#if MALLOC_REDIR -void *realloc(void *ptr, size_t size) -#else -void *__bound_realloc(void *ptr, size_t size, const void *caller) -#endif -{ - void *new_ptr; - - if (size == 0) { -#if MALLOC_REDIR - free(ptr); -#else - __bound_free(ptr, caller); -#endif - return NULL; - } - - new_ptr = BOUND_REALLOC (ptr, size + 1); - dprintf(stderr, "%s, %s(): %p, 0x%lx\n", - __FILE__, __FUNCTION__, new_ptr, (unsigned long)size); - - if (NO_CHECKING_GET() == 0) { - WAIT_SEM (); - INCR_COUNT(bound_realloc_count); - - if (ptr) - tree = splay_delete ((size_t) ptr, tree); - if (new_ptr) { - tree = splay_insert ((size_t) new_ptr, size ? size : size + 1, tree); - if (tree && tree->start == (size_t) new_ptr) - tree->type = TCC_TYPE_REALLOC; - } - POST_SEM (); - } - return new_ptr; -} - -#if MALLOC_REDIR -void *calloc(size_t nmemb, size_t size) -#else -void *__bound_calloc(size_t nmemb, size_t size) -#endif -{ - void *ptr; - - size *= nmemb; -#if MALLOC_REDIR - /* This will catch the first dlsym call from __bound_init */ - if (malloc_redir == NULL) { - __bound_init (0, -1); - if (malloc_redir == NULL) { - ptr = &initial_pool[pool_index]; - pool_index = (pool_index + size + 15) & ~15; - if (pool_index >= sizeof (initial_pool)) - bound_alloc_error ("initial memory pool too small"); - dprintf (stderr, "%s, %s(): initial %p, 0x%lx\n", - __FILE__, __FUNCTION__, ptr, (unsigned long)size); - memset (ptr, 0, size); - return ptr; - } - } -#endif - ptr = BOUND_MALLOC(size + 1); - dprintf (stderr, "%s, %s(): %p, 0x%lx\n", - __FILE__, __FUNCTION__, ptr, (unsigned long)size); - - if (ptr) { - memset (ptr, 0, size); - if (NO_CHECKING_GET() == 0) { - WAIT_SEM (); - INCR_COUNT(bound_calloc_count); - tree = splay_insert ((size_t) ptr, size ? size : size + 1, tree); - if (tree && tree->start == (size_t) ptr) - tree->type = TCC_TYPE_CALLOC; - POST_SEM (); - } - } - return ptr; -} - -#if !defined(_WIN32) -void *__bound_mmap (void *start, size_t size, int prot, - int flags, int fd, off_t offset) -{ - void *result; - - dprintf(stderr, "%s, %s(): %p, 0x%lx\n", - __FILE__, __FUNCTION__, start, (unsigned long)size); - result = mmap (start, size, prot, flags, fd, offset); - if (result && NO_CHECKING_GET() == 0) { - WAIT_SEM (); - INCR_COUNT(bound_mmap_count); - tree = splay_insert((size_t)result, size, tree); - POST_SEM (); - } - return result; -} - -int __bound_munmap (void *start, size_t size) -{ - int result; - - dprintf(stderr, "%s, %s(): %p, 0x%lx\n", - __FILE__, __FUNCTION__, start, (unsigned long)size); - if (start && NO_CHECKING_GET() == 0) { - WAIT_SEM (); - INCR_COUNT(bound_munmap_count); - tree = splay_delete ((size_t) start, tree); - POST_SEM (); - } - result = munmap (start, size); - return result; -} -#endif - -/* some useful checked functions */ - -/* check that (p ... p + size - 1) lies inside 'p' region, if any */ -static void __bound_check(const void *p, size_t size, const char *function) -{ - if (size != 0 && __bound_ptr_add((void *)p, size) == INVALID_POINTER) { - bound_error("invalid pointer %p, size 0x%lx in %s", - p, (unsigned long)size, function); - } -} - -static int check_overlap (const void *p1, size_t n1, - const void *p2, size_t n2, - const char *function) -{ - const void *p1e = (const void *) ((const char *) p1 + n1); - const void *p2e = (const void *) ((const char *) p2 + n2); - - if (NO_CHECKING_GET() == 0 && n1 != 0 && n2 !=0 && - ((p1 <= p2 && p1e > p2) || /* p1----p2====p1e----p2e */ - (p2 <= p1 && p2e > p1))) { /* p2----p1====p2e----p1e */ - bound_error("overlapping regions %p(0x%lx), %p(0x%lx) in %s", - p1, (unsigned long)n1, p2, (unsigned long)n2, function); - return never_fatal < 0; - } - return 0; -} - -void *__bound_memcpy(void *dest, const void *src, size_t n) -{ - dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n", - __FILE__, __FUNCTION__, dest, src, (unsigned long)n); - INCR_COUNT(bound_mempcy_count); - __bound_check(dest, n, "memcpy dest"); - __bound_check(src, n, "memcpy src"); - if (check_overlap(dest, n, src, n, "memcpy")) - return dest; - return memcpy(dest, src, n); -} - -int __bound_memcmp(const void *s1, const void *s2, size_t n) -{ - const unsigned char *u1 = (const unsigned char *) s1; - const unsigned char *u2 = (const unsigned char *) s2; - int retval = 0; - - dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n", - __FILE__, __FUNCTION__, s1, s2, (unsigned long)n); - INCR_COUNT(bound_memcmp_count); - for (;;) { - if ((ssize_t) --n == -1) - break; - else if (*u1 != *u2) { - retval = *u1++ - *u2++; - break; - } - ++u1; - ++u2; - } - __bound_check(s1, (const void *)u1 - s1, "memcmp s1"); - __bound_check(s2, (const void *)u2 - s2, "memcmp s2"); - return retval; -} - -void *__bound_memmove(void *dest, const void *src, size_t n) -{ - dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n", - __FILE__, __FUNCTION__, dest, src, (unsigned long)n); - INCR_COUNT(bound_memmove_count); - __bound_check(dest, n, "memmove dest"); - __bound_check(src, n, "memmove src"); - return memmove(dest, src, n); -} - -void *__bound_memset(void *s, int c, size_t n) -{ - dprintf(stderr, "%s, %s(): %p, %d, 0x%lx\n", - __FILE__, __FUNCTION__, s, c, (unsigned long)n); - INCR_COUNT(bound_memset_count); - __bound_check(s, n, "memset"); - return memset(s, c, n); -} - -#if defined(__arm__) && defined(__ARM_EABI__) -void *__bound___aeabi_memcpy(void *dest, const void *src, size_t n) -{ - dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n", - __FILE__, __FUNCTION__, dest, src, (unsigned long)n); - INCR_COUNT(bound_mempcy_count); - __bound_check(dest, n, "memcpy dest"); - __bound_check(src, n, "memcpy src"); - if (check_overlap(dest, n, src, n, "memcpy")) - return dest; - return __aeabi_memcpy(dest, src, n); -} - -void *__bound___aeabi_memmove(void *dest, const void *src, size_t n) -{ - dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n", - __FILE__, __FUNCTION__, dest, src, (unsigned long)n); - INCR_COUNT(bound_memmove_count); - __bound_check(dest, n, "memmove dest"); - __bound_check(src, n, "memmove src"); - return __aeabi_memmove(dest, src, n); -} - -void *__bound___aeabi_memmove4(void *dest, const void *src, size_t n) -{ - dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n", - __FILE__, __FUNCTION__, dest, src, (unsigned long)n); - INCR_COUNT(bound_memmove_count); - __bound_check(dest, n, "memmove dest"); - __bound_check(src, n, "memmove src"); - return __aeabi_memmove4(dest, src, n); -} - -void *__bound___aeabi_memmove8(void *dest, const void *src, size_t n) -{ - dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n", - __FILE__, __FUNCTION__, dest, src, (unsigned long)n); - INCR_COUNT(bound_memmove_count); - __bound_check(dest, n, "memmove dest"); - __bound_check(src, n, "memmove src"); - return __aeabi_memmove8(dest, src, n); -} - -void *__bound___aeabi_memset(void *s, int c, size_t n) -{ - dprintf(stderr, "%s, %s(): %p, %d, 0x%lx\n", - __FILE__, __FUNCTION__, s, c, (unsigned long)n); - INCR_COUNT(bound_memset_count); - __bound_check(s, n, "memset"); - return __aeabi_memset(s, c, n); -} -#endif - -int __bound_strlen(const char *s) -{ - const char *p = s; - - dprintf(stderr, "%s, %s(): %p\n", - __FILE__, __FUNCTION__, s); - INCR_COUNT(bound_strlen_count); - while (*p++); - __bound_check(s, p - s, "strlen"); - return (p - s) - 1; -} - -char *__bound_strcpy(char *dest, const char *src) -{ - size_t len; - const char *p = src; - - dprintf(stderr, "%s, %s(): %p, %p\n", - __FILE__, __FUNCTION__, dest, src); - INCR_COUNT(bound_strcpy_count); - while (*p++); - len = p - src; - __bound_check(dest, len, "strcpy dest"); - __bound_check(src, len, "strcpy src"); - if (check_overlap(dest, len, src, len, "strcpy")) - return dest; - return strcpy (dest, src); -} - -char *__bound_strncpy(char *dest, const char *src, size_t n) -{ - size_t len = n; - const char *p = src; - - dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n", - __FILE__, __FUNCTION__, dest, src, (unsigned long)n); - INCR_COUNT(bound_strncpy_count); - while (len-- && *p++); - len = p - src; - __bound_check(dest, len, "strncpy dest"); - __bound_check(src, len, "strncpy src"); - if (check_overlap(dest, len, src, len, "strncpy")) - return dest; - return strncpy(dest, src, n); -} - -int __bound_strcmp(const char *s1, const char *s2) -{ - const unsigned char *u1 = (const unsigned char *) s1; - const unsigned char *u2 = (const unsigned char *) s2; - - dprintf(stderr, "%s, %s(): %p, %p\n", - __FILE__, __FUNCTION__, s1, s2); - INCR_COUNT(bound_strcmp_count); - while (*u1 && *u1 == *u2) { - ++u1; - ++u2; - } - __bound_check(s1, ((const char *)u1 - s1) + 1, "strcmp s1"); - __bound_check(s2, ((const char *)u2 - s2) + 1, "strcmp s2"); - return *u1 - *u2; -} - -int __bound_strncmp(const char *s1, const char *s2, size_t n) -{ - const unsigned char *u1 = (const unsigned char *) s1; - const unsigned char *u2 = (const unsigned char *) s2; - int retval = 0; - - dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n", - __FILE__, __FUNCTION__, s1, s2, (unsigned long)n); - INCR_COUNT(bound_strncmp_count); - do { - if ((ssize_t) --n == -1) - break; - else if (*u1 != *u2) { - retval = *u1++ - *u2++; - break; - } - ++u2; - } while (*u1++); - __bound_check(s1, (const char *)u1 - s1, "strncmp s1"); - __bound_check(s2, (const char *)u2 - s2, "strncmp s2"); - return retval; -} - -char *__bound_strcat(char *dest, const char *src) -{ - char *r = dest; - const char *s = src; - - dprintf(stderr, "%s, %s(): %p, %p\n", - __FILE__, __FUNCTION__, dest, src); - INCR_COUNT(bound_strcat_count); - while (*dest++); - while (*src++); - __bound_check(r, (dest - r) + (src - s) - 1, "strcat dest"); - __bound_check(s, src - s, "strcat src"); - if (check_overlap(r, (dest - r) + (src - s) - 1, s, src - s, "strcat")) - return dest; - return strcat(r, s); -} - -char *__bound_strncat(char *dest, const char *src, size_t n) -{ - char *r = dest; - const char *s = src; - size_t len = n; - - dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n", - __FILE__, __FUNCTION__, dest, src, (unsigned long)n); - INCR_COUNT(bound_strncat_count); - while (*dest++); - while (len-- && *src++); - __bound_check(r, (dest - r) + (src - s) - 1, "strncat dest"); - __bound_check(s, src - s, "strncat src"); - if (check_overlap(r, (dest - r) + (src - s) - 1, s, src - s, "strncat")) - return dest; - return strncat(r, s, n); -} - -char *__bound_strchr(const char *s, int c) -{ - const unsigned char *str = (const unsigned char *) s; - unsigned char ch = c; - - dprintf(stderr, "%s, %s(): %p, %d\n", - __FILE__, __FUNCTION__, s, ch); - INCR_COUNT(bound_strchr_count); - while (*str) { - if (*str == ch) - break; - ++str; - } - __bound_check(s, ((const char *)str - s) + 1, "strchr"); - return *str == ch ? (char *) str : NULL; -} - -char *__bound_strrchr(const char *s, int c) -{ - const unsigned char *str = (const unsigned char *) s; - unsigned char ch = c; - - dprintf(stderr, "%s, %s(): %p, %d\n", - __FILE__, __FUNCTION__, s, ch); - INCR_COUNT(bound_strrchr_count); - while (*str++); - __bound_check(s, (const char *)str - s, "strrchr"); - while (str != (const unsigned char *)s) { - if (*--str == ch) - break; - } - __bound_check(s, (const char *)str - s, "strrchr"); - return *str == ch ? (char *) str : NULL; -} - -char *__bound_strdup(const char *s) -{ - const char *p = s; - char *new; - - INCR_COUNT(bound_strdup_count); - while (*p++); - __bound_check(s, p - s, "strdup"); - new = BOUND_MALLOC ((p - s) + 1); - dprintf(stderr, "%s, %s(): %p, 0x%lx\n", - __FILE__, __FUNCTION__, new, (unsigned long)(p -s)); - if (new) { - if (NO_CHECKING_GET() == 0 && no_strdup == 0) { - WAIT_SEM (); - tree = splay_insert((size_t)new, p - s, tree); - if (tree && tree->start == (size_t) new) - tree->type = TCC_TYPE_STRDUP; - POST_SEM (); - } - memcpy (new, s, p - s); - } - return new; -} - -/* - An implementation of top-down splaying with sizes - D. Sleator , January 1994. - - This extends top-down-splay.c to maintain a size field in each node. - This is the number of nodes in the subtree rooted there. This makes - it possible to efficiently compute the rank of a key. (The rank is - the number of nodes to the left of the given key.) It it also - possible to quickly find the node of a given rank. Both of these - operations are illustrated in the code below. The remainder of this - introduction is taken from top-down-splay.c. - - "Splay trees", or "self-adjusting search trees" are a simple and - efficient data structure for storing an ordered set. The data - structure consists of a binary tree, with no additional fields. It - allows searching, insertion, deletion, deletemin, deletemax, - splitting, joining, and many other operations, all with amortized - logarithmic performance. Since the trees adapt to the sequence of - requests, their performance on real access patterns is typically even - better. Splay trees are described in a number of texts and papers - [1,2,3,4]. - - The code here is adapted from simple top-down splay, at the bottom of - page 669 of [2]. It can be obtained via anonymous ftp from - spade.pc.cs.cmu.edu in directory /usr/sleator/public. - - The chief modification here is that the splay operation works even if the - item being splayed is not in the tree, and even if the tree root of the - tree is NULL. So the line: - - t = splay(i, t); - - causes it to search for item with key i in the tree rooted at t. If it's - there, it is splayed to the root. If it isn't there, then the node put - at the root is the last one before NULL that would have been reached in a - normal binary search for i. (It's a neighbor of i in the tree.) This - allows many other operations to be easily implemented, as shown below. - - [1] "Data Structures and Their Algorithms", Lewis and Denenberg, - Harper Collins, 1991, pp 243-251. - [2] "Self-adjusting Binary Search Trees" Sleator and Tarjan, - JACM Volume 32, No 3, July 1985, pp 652-686. - [3] "Data Structure and Algorithm Analysis", Mark Weiss, - Benjamin Cummins, 1992, pp 119-130. - [4] "Data Structures, Algorithms, and Performance", Derick Wood, - Addison-Wesley, 1993, pp 367-375 -*/ - -/* Code adapted for tcc */ - -#define compare(start,tstart,tsize) (start < tstart ? -1 : \ - start >= tstart+tsize ? 1 : 0) - -static Tree * splay (size_t addr, Tree *t) -/* Splay using the key start (which may or may not be in the tree.) */ -/* The starting root is t, and the tree used is defined by rat */ -{ - Tree N, *l, *r, *y; - int comp; - - INCR_COUNT_SPLAY(bound_splay); - if (t == NULL) return t; - N.left = N.right = NULL; - l = r = &N; - - for (;;) { - comp = compare(addr, t->start, t->size); - if (comp < 0) { - y = t->left; - if (y == NULL) break; - if (compare(addr, y->start, y->size) < 0) { - t->left = y->right; /* rotate right */ - y->right = t; - t = y; - if (t->left == NULL) break; - } - r->left = t; /* link right */ - r = t; - t = t->left; - } else if (comp > 0) { - y = t->right; - if (y == NULL) break; - if (compare(addr, y->start, y->size) > 0) { - t->right = y->left; /* rotate left */ - y->left = t; - t = y; - if (t->right == NULL) break; - } - l->right = t; /* link left */ - l = t; - t = t->right; - } else { - break; - } - } - l->right = t->left; /* assemble */ - r->left = t->right; - t->left = N.right; - t->right = N.left; - - return t; -} - -#define compare_end(start,tend) (start < tend ? -1 : \ - start > tend ? 1 : 0) - -static Tree * splay_end (size_t addr, Tree *t) -/* Splay using the key start (which may or may not be in the tree.) */ -/* The starting root is t, and the tree used is defined by rat */ -{ - Tree N, *l, *r, *y; - int comp; - - INCR_COUNT_SPLAY(bound_splay_end); - if (t == NULL) return t; - N.left = N.right = NULL; - l = r = &N; - - for (;;) { - comp = compare_end(addr, t->start + t->size); - if (comp < 0) { - y = t->left; - if (y == NULL) break; - if (compare_end(addr, y->start + y->size) < 0) { - t->left = y->right; /* rotate right */ - y->right = t; - t = y; - if (t->left == NULL) break; - } - r->left = t; /* link right */ - r = t; - t = t->left; - } else if (comp > 0) { - y = t->right; - if (y == NULL) break; - if (compare_end(addr, y->start + y->size) > 0) { - t->right = y->left; /* rotate left */ - y->left = t; - t = y; - if (t->right == NULL) break; - } - l->right = t; /* link left */ - l = t; - t = t->right; - } else { - break; - } - } - l->right = t->left; /* assemble */ - r->left = t->right; - t->left = N.right; - t->right = N.left; - - return t; -} - -static Tree * splay_insert(size_t addr, size_t size, Tree * t) -/* Insert key start into the tree t, if it is not already there. */ -/* Return a pointer to the resulting tree. */ -{ - Tree * new; - - INCR_COUNT_SPLAY(bound_splay_insert); - if (t != NULL) { - t = splay(addr,t); - if (compare(addr, t->start, t->size)==0) { - return t; /* it's already there */ - } - } -#if TREE_REUSE - if (tree_free_list) { - new = tree_free_list; - tree_free_list = new->left; - } - else -#endif - { - new = (Tree *) BOUND_MALLOC (sizeof (Tree)); - } - if (new == NULL) { - bound_alloc_error("not enough memory for bound checking code"); - } - else { - if (t == NULL) { - new->left = new->right = NULL; - } else if (compare(addr, t->start, t->size) < 0) { - new->left = t->left; - new->right = t; - t->left = NULL; - } else { - new->right = t->right; - new->left = t; - t->right = NULL; - } - new->start = addr; - new->size = size; - new->type = TCC_TYPE_NONE; - new->is_invalid = 0; - } - return new; -} - -#define compare_destroy(start,tstart) (start < tstart ? -1 : \ - start > tstart ? 1 : 0) - -static Tree * splay_delete(size_t addr, Tree *t) -/* Deletes addr from the tree if it's there. */ -/* Return a pointer to the resulting tree. */ -{ - Tree * x; - - INCR_COUNT_SPLAY(bound_splay_delete); - if (t==NULL) return NULL; - t = splay(addr,t); - if (compare_destroy(addr, t->start) == 0) { /* found it */ - if (t->left == NULL) { - x = t->right; - } else { - x = splay(addr, t->left); - x->right = t->right; - } -#if TREE_REUSE - t->left = tree_free_list; - tree_free_list = t; -#else - BOUND_FREE(t); -#endif - return x; - } else { - return t; /* It wasn't there */ - } -} - -void splay_printtree(Tree * t, int d) -{ - int i; - if (t == NULL) return; - splay_printtree(t->right, d+1); - for (i=0; istart, (unsigned long) t->size, - (unsigned)t->type, (unsigned)t->is_invalid); - splay_printtree(t->left, d+1); -} diff --git a/libtcc1/bt-dll.c b/libtcc1/bt-dll.c deleted file mode 100644 index 7c62cefa..00000000 --- a/libtcc1/bt-dll.c +++ /dev/null @@ -1,74 +0,0 @@ -/* ------------------------------------------------------------- */ -/* stubs for calling bcheck functions from a dll. */ - -#include -#include - -#define REDIR_ALL \ - REDIR(__bt_init) \ - REDIR(__bt_exit) \ - REDIR(tcc_backtrace) \ - \ - REDIR(__bound_ptr_add) \ - REDIR(__bound_ptr_indir1) \ - REDIR(__bound_ptr_indir2) \ - REDIR(__bound_ptr_indir4) \ - REDIR(__bound_ptr_indir8) \ - REDIR(__bound_ptr_indir12) \ - REDIR(__bound_ptr_indir16) \ - REDIR(__bound_local_new) \ - REDIR(__bound_local_delete) \ - REDIR(__bound_new_region) \ - \ - REDIR(__bound_free) \ - REDIR(__bound_malloc) \ - REDIR(__bound_realloc) \ - REDIR(__bound_memcpy) \ - REDIR(__bound_memcmp) \ - REDIR(__bound_memmove) \ - REDIR(__bound_memset) \ - REDIR(__bound_strlen) \ - REDIR(__bound_strcpy) \ - REDIR(__bound_strncpy) \ - REDIR(__bound_strcmp) \ - REDIR(__bound_strncmp) \ - REDIR(__bound_strcat) \ - REDIR(__bound_strchr) \ - REDIR(__bound_strdup) - -#ifdef __leading_underscore -#define _(s) "_"#s -#else -#define _(s) #s -#endif - -#define REDIR(s) void *s; -static struct { REDIR_ALL } all_ptrs; -#undef REDIR -#define REDIR(s) #s"\0" -static const char all_names[] = REDIR_ALL; -#undef REDIR -#define REDIR(s) __asm__(".global " _(s) ";" _(s) ": jmp *%0" : : "m" (all_ptrs.s) ); -static void all_jmps() { REDIR_ALL } -#undef REDIR - -void __bt_init_dll(int bcheck) -{ - const char *s = all_names; - void **p = (void**)&all_ptrs; - do { - *p = (void*)GetProcAddress(GetModuleHandle(NULL), (char*)s); - if (NULL == *p) { - char buf[100]; - sprintf(buf, - "Error: function '%s()' not found in executable. " - "(Need -bt or -b for linking the exe.)", s); - if (GetStdHandle(STD_ERROR_HANDLE)) - fprintf(stderr, "TCC/BCHECK: %s\n", buf), fflush(stderr); - else - MessageBox(NULL, buf, "TCC/BCHECK", MB_ICONERROR); - ExitProcess(1); - } - s = strchr(s,'\0') + 1, ++p; - } while (*s && (bcheck || p < &all_ptrs.__bound_ptr_add)); -} diff --git a/libtcc1/bt-exe.c b/libtcc1/bt-exe.c deleted file mode 100644 index 71c9c19c..00000000 --- a/libtcc1/bt-exe.c +++ /dev/null @@ -1,68 +0,0 @@ -/* ------------------------------------------------------------- */ -/* for linking rt_printline and the signal/exception handler - from tccrun.c into executables. */ - -#define CONFIG_TCC_BACKTRACE_ONLY -#define ONE_SOURCE 1 -#define pstrcpy tcc_pstrcpy -#include "../tccrun.c" - -#ifndef _WIN32 -# define __declspec(n) -#endif - -__declspec(dllexport) -void __bt_init(rt_context *p, int is_exe) -{ - __attribute__((weak)) int main(); - __attribute__((weak)) void __bound_init(void*, int); - - //fprintf(stderr, "__bt_init %d %p %p %p\n", is_exe, p, p->stab_sym, p->bounds_start), fflush(stderr); - - /* call __bound_init here due to redirection of sigaction */ - /* needed to add global symbols */ - if (p->bounds_start) - __bound_init(p->bounds_start, -1); - - /* add to chain */ - rt_wait_sem(); - p->next = g_rc, g_rc = p; - rt_post_sem(); - if (is_exe) { - /* we are the executable (not a dll) */ - p->top_func = main; - set_exception_handler(); - } -} - -__declspec(dllexport) -void __bt_exit(rt_context *p) -{ - struct rt_context *rc, **pp; - __attribute__((weak)) void __bound_exit_dll(void*); - - //fprintf(stderr, "__bt_exit %d %p\n", !!p->top_func, p); - - if (p->bounds_start) - __bound_exit_dll(p->bounds_start); - - /* remove from chain */ - rt_wait_sem(); - for (pp = &g_rc; rc = *pp, rc; pp = &rc->next) - if (rc == p) { - *pp = rc->next; - break; - } - rt_post_sem(); -} - -/* copy a string and truncate it. */ -ST_FUNC char *pstrcpy(char *buf, size_t buf_size, const char *s) -{ - int l = strlen(s); - if (l >= buf_size) - l = buf_size - 1; - memcpy(buf, s, l); - buf[l] = 0; - return buf; -} diff --git a/libtcc1/bt-log.c b/libtcc1/bt-log.c deleted file mode 100644 index ace51170..00000000 --- a/libtcc1/bt-log.c +++ /dev/null @@ -1,56 +0,0 @@ -/* ------------------------------------------------------------- */ -/* function to get a stack backtrace on demand with a message */ - -#include -#include -#include -#undef __attribute__ - -#ifdef _WIN32 -# define DLL_EXPORT __declspec(dllexport) -#else -# define DLL_EXPORT -#endif - -/* Needed when using ...libtcc1-usegcc=yes in lib/Makefile */ -#if (defined(__GNUC__) && (__GNUC__ >= 6)) || defined(__clang__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wframe-address" -#endif - -typedef struct rt_frame { - void *ip, *fp, *sp; -} rt_frame; - -__attribute__((weak)) -int _tcc_backtrace(rt_frame *f, const char *fmt, va_list ap); - -DLL_EXPORT int tcc_backtrace(const char *fmt, ...) -{ - va_list ap; - int ret; - - if (_tcc_backtrace) { - rt_frame f; - f.fp = __builtin_frame_address(1); - f.ip = __builtin_return_address(0); - va_start(ap, fmt); - ret = _tcc_backtrace(&f, fmt, ap); - va_end(ap); - } else { - const char *p, *nl = "\n"; - if (fmt[0] == '^' && (p = strchr(fmt + 1, fmt[0]))) - fmt = p + 1; - if (fmt[0] == '\001') - ++fmt, nl = ""; - va_start(ap, fmt); - ret = vfprintf(stderr, fmt, ap); - va_end(ap); - fprintf(stderr, "%s", nl), fflush(stderr); - } - return ret; -} - -#if (defined(__GNUC__) && (__GNUC__ >= 6)) || defined(__clang__) -#pragma GCC diagnostic pop -#endif diff --git a/libtcc1/dsohandle.c b/libtcc1/dsohandle.c deleted file mode 100644 index 0993dbc2..00000000 --- a/libtcc1/dsohandle.c +++ /dev/null @@ -1 +0,0 @@ -void * __dso_handle __attribute((visibility("hidden"))) = &__dso_handle; diff --git a/include/float.h b/libtcc1/include/float.h similarity index 100% rename from include/float.h rename to libtcc1/include/float.h diff --git a/include/stdalign.h b/libtcc1/include/stdalign.h similarity index 100% rename from include/stdalign.h rename to libtcc1/include/stdalign.h diff --git a/include/stdarg.h b/libtcc1/include/stdarg.h similarity index 100% rename from include/stdarg.h rename to libtcc1/include/stdarg.h diff --git a/include/stdatomic.h b/libtcc1/include/stdatomic.h similarity index 100% rename from include/stdatomic.h rename to libtcc1/include/stdatomic.h diff --git a/include/stdbool.h b/libtcc1/include/stdbool.h similarity index 100% rename from include/stdbool.h rename to libtcc1/include/stdbool.h diff --git a/include/stddef.h b/libtcc1/include/stddef.h similarity index 100% rename from include/stddef.h rename to libtcc1/include/stddef.h diff --git a/include/stdnoreturn.h b/libtcc1/include/stdnoreturn.h similarity index 100% rename from include/stdnoreturn.h rename to libtcc1/include/stdnoreturn.h diff --git a/include/tccdefs.h b/libtcc1/include/tccdefs.h similarity index 60% rename from include/tccdefs.h rename to libtcc1/include/tccdefs.h index 3ad83d12..ecb34afe 100644 --- a/include/tccdefs.h +++ b/libtcc1/include/tccdefs.h @@ -57,102 +57,34 @@ #define __ORDER_LITTLE_ENDIAN__ 1234 #define __ORDER_BIG_ENDIAN__ 4321 #define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__ -#if defined _WIN32 - #define __WCHAR_TYPE__ unsigned short - #define __WINT_TYPE__ unsigned short -#elif defined __linux__ - #define __WCHAR_TYPE__ int - #define __WINT_TYPE__ unsigned int -#else #define __WCHAR_TYPE__ int #define __WINT_TYPE__ int -#endif - #if __STDC_VERSION__ >= 201112L + +#if __STDC_VERSION__ >= 201112L # define __STDC_NO_ATOMICS__ 1 # define __STDC_NO_COMPLEX__ 1 # define __STDC_NO_THREADS__ 1 -#if !defined _WIN32 # define __STDC_UTF_16__ 1 # define __STDC_UTF_32__ 1 -#endif - #endif - -#if defined _WIN32 - #define __declspec(x) __attribute__((x)) - #define __cdecl - -#elif defined __FreeBSD__ - #define __GNUC__ 9 - #define __GNUC_MINOR__ 3 - #define __GNUC_PATCHLEVEL__ 0 - #define __GNUC_STDC_INLINE__ 1 - #define __NO_TLS 1 - #define __RUNETYPE_INTERNAL 1 -# if __SIZEOF_POINTER__ == 8 - /* FIXME, __int128_t is used by setjump */ - #define __int128_t struct { unsigned char _dummy[16] __attribute((aligned(16))); } - #define __SIZEOF_SIZE_T__ 8 - #define __SIZEOF_PTRDIFF_T__ 8 -#else - #define __SIZEOF_SIZE_T__ 4 - #define __SIZEOF_PTRDIFF_T__ 4 -# endif - -#elif defined __FreeBSD_kernel__ - -#elif defined __NetBSD__ - #define __GNUC__ 4 - #define __GNUC_MINOR__ 1 - #define __GNUC_PATCHLEVEL__ 0 - #define _Pragma(x) - #define __ELF__ 1 -#if defined __aarch64__ - #define _LOCORE /* avoids usage of __asm */ -#endif - -#elif defined __OpenBSD__ - #define __GNUC__ 4 - #define _ANSI_LIBRARY 1 - -#elif defined __APPLE__ - /* emulate APPLE-GCC to make libc's headerfiles compile: */ - #define __GNUC__ 4 /* darwin emits warning on GCC<4 */ - #define __APPLE_CC__ 1 /* for */ - #define __LITTLE_ENDIAN__ 1 - #define _DONT_USE_CTYPE_INLINE_ 1 - /* avoids usage of GCC/clang specific builtins in libc-headerfiles: */ - #define __FINITE_MATH_ONLY__ 1 - #define _FORTIFY_SOURCE 0 - //#define __has_builtin(x) 0 - -#elif defined __ANDROID__ - #define BIONIC_IOCTL_NO_SIGNEDNESS_OVERLOAD - -#else - /* Linux */ - #endif /* Some derived integer types needed to get stdint.h to compile correctly on some platforms */ -#ifndef __NetBSD__ #define __UINTPTR_TYPE__ unsigned __PTRDIFF_TYPE__ #define __INTPTR_TYPE__ __PTRDIFF_TYPE__ -#endif #define __INT32_TYPE__ int -#if !defined _WIN32 /* glibc defines. We do not support __USER_NAME_PREFIX__ */ #define __REDIRECT(name, proto, alias) name proto __asm__ (#alias) #define __REDIRECT_NTH(name, proto, alias) name proto __asm__ (#alias) __THROW #define __REDIRECT_NTHNL(name, proto, alias) name proto __asm__ (#alias) __THROWNL -#endif /* not implemented */ #define __PRETTY_FUNCTION__ __FUNCTION__ #define __has_builtin(x) 0 #define __has_feature(x) 0 #define __has_attribute(x) 0 + /* C23 Keywords */ #define _Nonnull #define _Nullable @@ -181,67 +113,10 @@ #endif /* __builtin_va_list */ -#if defined __x86_64__ -#if !defined _WIN32 - /* GCC compatible definition of va_list. */ - /* This should be in sync with the declaration in our lib/libtcc1.c */ - typedef struct { - unsigned gp_offset, fp_offset; - union { - unsigned overflow_offset; - char *overflow_arg_area; - }; - char *reg_save_area; - } __builtin_va_list[1]; - - void *__va_arg(__builtin_va_list ap, int arg_type, int size, int align); - #define __builtin_va_start(ap, last) \ - (*(ap) = *(__builtin_va_list)((char*)__builtin_frame_address(0) - 24)) - #define __builtin_va_arg(ap, t) \ - (*(t *)(__va_arg(ap, __builtin_va_arg_types(t), sizeof(t), __alignof__(t)))) - #define __builtin_va_copy(dest, src) (*(dest) = *(src)) - -#else /* _WIN64 */ - typedef char *__builtin_va_list; - #define __builtin_va_arg(ap, t) ((sizeof(t) > 8 || (sizeof(t) & (sizeof(t) - 1))) \ - ? **(t **)((ap += 8) - 8) : *(t *)((ap += 8) - 8)) -#endif - -#elif defined __arm__ - typedef char *__builtin_va_list; - #define _tcc_alignof(type) ((int)&((struct {char c;type x;} *)0)->x) - #define _tcc_align(addr,type) (((unsigned)addr + _tcc_alignof(type) - 1) \ - & ~(_tcc_alignof(type) - 1)) - #define __builtin_va_start(ap,last) (ap = ((char *)&(last)) + ((sizeof(last)+3)&~3)) - #define __builtin_va_arg(ap,type) (ap = (void *) ((_tcc_align(ap,type)+sizeof(type)+3) \ - &~3), *(type *)(ap - ((sizeof(type)+3)&~3))) - -#elif defined __aarch64__ -#if defined __APPLE__ - typedef struct { - void *__stack; - } __builtin_va_list; - -#else - typedef struct { - void *__stack, *__gr_top, *__vr_top; - int __gr_offs, __vr_offs; - } __builtin_va_list; - -#endif -#elif defined __riscv - typedef char *__builtin_va_list; - #define __va_reg_size (__riscv_xlen >> 3) - #define _tcc_align(addr,type) (((unsigned long)addr + __alignof__(type) - 1) \ - & -(__alignof__(type))) - #define __builtin_va_arg(ap,type) (*(sizeof(type) > (2*__va_reg_size) ? *(type **)((ap += __va_reg_size) - __va_reg_size) : (ap = (va_list)(_tcc_align(ap,type) + (sizeof(type)+__va_reg_size - 1)& -__va_reg_size), (type *)(ap - ((sizeof(type)+ __va_reg_size - 1)& -__va_reg_size))))) - -#else /* __i386__ */ typedef char *__builtin_va_list; #define __builtin_va_start(ap,last) (ap = ((char *)&(last)) + ((sizeof(last)+3)&~3)) #define __builtin_va_arg(ap,t) (*(t*)((ap+=(sizeof(t)+3)&~3)-((sizeof(t)+3)&~3))) -#endif #define __builtin_va_end(ap) (void)(ap) #ifndef __builtin_va_copy # define __builtin_va_copy(dest, src) (dest) = (src) @@ -283,13 +158,6 @@ __BOTH(char*, strchr, (const char*, int)) __BOTH(char*, strrchr, (const char*, int)) __BOTH(char*, strdup, (const char*)) -#if defined __ARM_EABI__ - __BOUND(void*,__aeabi_memcpy,(void*,const void*,__SIZE_TYPE__)) - __BOUND(void*,__aeabi_memmove,(void*,const void*,__SIZE_TYPE__)) - __BOUND(void*,__aeabi_memmove4,(void*,const void*,__SIZE_TYPE__)) - __BOUND(void*,__aeabi_memmove8,(void*,const void*,__SIZE_TYPE__)) - __BOUND(void*,__aeabi_memset,(void*,int,__SIZE_TYPE__)) -#endif #if defined __linux__ || defined __APPLE__ // HAVE MALLOC_REDIR #define __MAYBE_REDIR __BUILTIN diff --git a/include/tgmath.h b/libtcc1/include/tgmath.h similarity index 100% rename from include/tgmath.h rename to libtcc1/include/tgmath.h diff --git a/include/varargs.h b/libtcc1/include/varargs.h similarity index 100% rename from include/varargs.h rename to libtcc1/include/varargs.h diff --git a/libtcc1/lib-arm64.c b/libtcc1/lib-arm64.c deleted file mode 100644 index 226827e9..00000000 --- a/libtcc1/lib-arm64.c +++ /dev/null @@ -1,677 +0,0 @@ -/* - * TCC runtime library for arm64. - * - * Copyright (c) 2015 Edmund Grimley Evans - * - * Copying and distribution of this file, with or without modification, - * are permitted in any medium without royalty provided the copyright - * notice and this notice are preserved. This file is offered as-is, - * without any warranty. - */ - -#ifdef __TINYC__ -typedef signed char int8_t; -typedef unsigned char uint8_t; -typedef short int16_t; -typedef unsigned short uint16_t; -typedef int int32_t; -typedef unsigned uint32_t; -typedef long long int64_t; -typedef unsigned long long uint64_t; -void *memcpy(void*,void*,__SIZE_TYPE__); -#else -#include -#include -#endif - -#if !defined __riscv && !defined __APPLE__ -void __clear_cache(void *beg, void *end) -{ - __arm64_clear_cache(beg, end); -} -#endif - -typedef struct { - uint64_t x0, x1; -} u128_t; - -static long double f3_zero(int sgn) -{ - long double f; - u128_t x = { 0, (uint64_t)sgn << 63 }; - memcpy(&f, &x, 16); - return f; -} - -static long double f3_infinity(int sgn) -{ - long double f; - u128_t x = { 0, (uint64_t)sgn << 63 | 0x7fff000000000000 }; - memcpy(&f, &x, 16); - return f; -} - -static long double f3_NaN(void) -{ - long double f; -#if 0 - // ARM's default NaN usually has just the top fraction bit set: - u128_t x = { 0, 0x7fff800000000000 }; -#else - // GCC's library sets all fraction bits: - u128_t x = { -1, 0x7fffffffffffffff }; -#endif - memcpy(&f, &x, 16); - return f; -} - -static int fp3_convert_NaN(long double *f, int sgn, u128_t mnt) -{ - u128_t x = { mnt.x0, - mnt.x1 | 0x7fff800000000000 | (uint64_t)sgn << 63 }; - memcpy(f, &x, 16); - return 1; -} - -static int fp3_detect_NaNs(long double *f, - int a_sgn, int a_exp, u128_t a, - int b_sgn, int b_exp, u128_t b) -{ - // Detect signalling NaNs: - if (a_exp == 32767 && (a.x0 | a.x1 << 16) && !(a.x1 >> 47 & 1)) - return fp3_convert_NaN(f, a_sgn, a); - if (b_exp == 32767 && (b.x0 | b.x1 << 16) && !(b.x1 >> 47 & 1)) - return fp3_convert_NaN(f, b_sgn, b); - - // Detect quiet NaNs: - if (a_exp == 32767 && (a.x0 | a.x1 << 16)) - return fp3_convert_NaN(f, a_sgn, a); - if (b_exp == 32767 && (b.x0 | b.x1 << 16)) - return fp3_convert_NaN(f, b_sgn, b); - - return 0; -} - -static void f3_unpack(int *sgn, int32_t *exp, u128_t *mnt, long double f) -{ - u128_t x; - memcpy(&x, &f, 16); - *sgn = x.x1 >> 63; - *exp = x.x1 >> 48 & 32767; - x.x1 = x.x1 << 16 >> 16; - if (*exp) - x.x1 |= (uint64_t)1 << 48; - else - *exp = 1; - *mnt = x; -} - -static u128_t f3_normalise(int32_t *exp, u128_t mnt) -{ - int sh; - if (!(mnt.x0 | mnt.x1)) - return mnt; - if (!mnt.x1) { - mnt.x1 = mnt.x0; - mnt.x0 = 0; - *exp -= 64; - } - for (sh = 32; sh; sh >>= 1) { - if (!(mnt.x1 >> (64 - sh))) { - mnt.x1 = mnt.x1 << sh | mnt.x0 >> (64 - sh); - mnt.x0 = mnt.x0 << sh; - *exp -= sh; - } - } - return mnt; -} - -static u128_t f3_sticky_shift(int32_t sh, u128_t x) -{ - if (sh >= 128) { - x.x0 = !!(x.x0 | x.x1); - x.x1 = 0; - return x; - } - if (sh >= 64) { - x.x0 = x.x1 | !!x.x0; - x.x1 = 0; - sh -= 64; - } - if (sh > 0) { - x.x0 = x.x0 >> sh | x.x1 << (64 - sh) | !!(x.x0 << (64 - sh)); - x.x1 = x.x1 >> sh; - } - return x; -} - -static long double f3_round(int sgn, int32_t exp, u128_t x) -{ - long double f; - int error; - - if (exp > 0) { - x = f3_sticky_shift(13, x); - } - else { - x = f3_sticky_shift(14 - exp, x); - exp = 0; - } - - error = x.x0 & 3; - x.x0 = x.x0 >> 2 | x.x1 << 62; - x.x1 = x.x1 >> 2; - - if (error == 3 || ((error == 2) & (x.x0 & 1))) { - if (!++x.x0) { - ++x.x1; - if (x.x1 == (uint64_t)1 << 48) - exp = 1; - else if (x.x1 == (uint64_t)1 << 49) { - ++exp; - x.x0 = x.x0 >> 1 | x.x1 << 63; - x.x1 = x.x1 >> 1; - } - } - } - - if (exp >= 32767) - return f3_infinity(sgn); - - x.x1 = x.x1 << 16 >> 16 | (uint64_t)exp << 48 | (uint64_t)sgn << 63; - memcpy(&f, &x, 16); - return f; -} - -static long double f3_add(long double fa, long double fb, int neg) -{ - u128_t a, b, x; - int32_t a_exp, b_exp, x_exp; - int a_sgn, b_sgn, x_sgn; - long double fx; - - f3_unpack(&a_sgn, &a_exp, &a, fa); - f3_unpack(&b_sgn, &b_exp, &b, fb); - - if (fp3_detect_NaNs(&fx, a_sgn, a_exp, a, b_sgn, b_exp, b)) - return fx; - - b_sgn ^= neg; - - // Handle infinities and zeroes: - if (a_exp == 32767 && b_exp == 32767 && a_sgn != b_sgn) - return f3_NaN(); - if (a_exp == 32767) - return f3_infinity(a_sgn); - if (b_exp == 32767) - return f3_infinity(b_sgn); - if (!(a.x0 | a.x1 | b.x0 | b.x1)) - return f3_zero(a_sgn & b_sgn); - - a.x1 = a.x1 << 3 | a.x0 >> 61; - a.x0 = a.x0 << 3; - b.x1 = b.x1 << 3 | b.x0 >> 61; - b.x0 = b.x0 << 3; - - if (a_exp <= b_exp) { - a = f3_sticky_shift(b_exp - a_exp, a); - a_exp = b_exp; - } - else { - b = f3_sticky_shift(a_exp - b_exp, b); - b_exp = a_exp; - } - - x_sgn = a_sgn; - x_exp = a_exp; - if (a_sgn == b_sgn) { - x.x0 = a.x0 + b.x0; - x.x1 = a.x1 + b.x1 + (x.x0 < a.x0); - } - else { - x.x0 = a.x0 - b.x0; - x.x1 = a.x1 - b.x1 - (x.x0 > a.x0); - if (x.x1 >> 63) { - x_sgn ^= 1; - x.x0 = -x.x0; - x.x1 = -x.x1 - !!x.x0; - } - } - - if (!(x.x0 | x.x1)) - return f3_zero(0); - - x = f3_normalise(&x_exp, x); - - return f3_round(x_sgn, x_exp + 12, x); -} - -long double __addtf3(long double a, long double b) -{ - return f3_add(a, b, 0); -} - -long double __subtf3(long double a, long double b) -{ - return f3_add(a, b, 1); -} - -long double __multf3(long double fa, long double fb) -{ - u128_t a, b, x; - int32_t a_exp, b_exp, x_exp; - int a_sgn, b_sgn, x_sgn; - long double fx; - - f3_unpack(&a_sgn, &a_exp, &a, fa); - f3_unpack(&b_sgn, &b_exp, &b, fb); - - if (fp3_detect_NaNs(&fx, a_sgn, a_exp, a, b_sgn, b_exp, b)) - return fx; - - // Handle infinities and zeroes: - if ((a_exp == 32767 && !(b.x0 | b.x1)) || - (b_exp == 32767 && !(a.x0 | a.x1))) - return f3_NaN(); - if (a_exp == 32767 || b_exp == 32767) - return f3_infinity(a_sgn ^ b_sgn); - if (!(a.x0 | a.x1) || !(b.x0 | b.x1)) - return f3_zero(a_sgn ^ b_sgn); - - a = f3_normalise(&a_exp, a); - b = f3_normalise(&b_exp, b); - - x_sgn = a_sgn ^ b_sgn; - x_exp = a_exp + b_exp - 16352; - - { - // Convert to base (1 << 30), discarding bottom 6 bits, which are zero, - // so there are (32, 30, 30, 30) bits in (a3, a2, a1, a0): - uint64_t a0 = a.x0 << 28 >> 34; - uint64_t b0 = b.x0 << 28 >> 34; - uint64_t a1 = a.x0 >> 36 | a.x1 << 62 >> 34; - uint64_t b1 = b.x0 >> 36 | b.x1 << 62 >> 34; - uint64_t a2 = a.x1 << 32 >> 34; - uint64_t b2 = b.x1 << 32 >> 34; - uint64_t a3 = a.x1 >> 32; - uint64_t b3 = b.x1 >> 32; - // Use 16 small multiplications and additions that do not overflow: - uint64_t x0 = a0 * b0; - uint64_t x1 = (x0 >> 30) + a0 * b1 + a1 * b0; - uint64_t x2 = (x1 >> 30) + a0 * b2 + a1 * b1 + a2 * b0; - uint64_t x3 = (x2 >> 30) + a0 * b3 + a1 * b2 + a2 * b1 + a3 * b0; - uint64_t x4 = (x3 >> 30) + a1 * b3 + a2 * b2 + a3 * b1; - uint64_t x5 = (x4 >> 30) + a2 * b3 + a3 * b2; - uint64_t x6 = (x5 >> 30) + a3 * b3; - // We now have (64, 30, 30, ...) bits in (x6, x5, x4, ...). - // Take the top 128 bits, setting bottom bit if any lower bits were set: - uint64_t y0 = (x5 << 34 | x4 << 34 >> 30 | x3 << 34 >> 60 | - !!(x3 << 38 | (x2 | x1 | x0) << 34)); - uint64_t y1 = x6; - // Top bit may be zero. Renormalise: - if (!(y1 >> 63)) { - y1 = y1 << 1 | y0 >> 63; - y0 = y0 << 1; - --x_exp; - } - x.x0 = y0; - x.x1 = y1; - } - - return f3_round(x_sgn, x_exp, x); -} - -long double __divtf3(long double fa, long double fb) -{ - u128_t a, b, x; - int32_t a_exp, b_exp, x_exp; - int a_sgn, b_sgn, x_sgn, i; - long double fx; - - f3_unpack(&a_sgn, &a_exp, &a, fa); - f3_unpack(&b_sgn, &b_exp, &b, fb); - - if (fp3_detect_NaNs(&fx, a_sgn, a_exp, a, b_sgn, b_exp, b)) - return fx; - - // Handle infinities and zeroes: - if ((a_exp == 32767 && b_exp == 32767) || - (!(a.x0 | a.x1) && !(b.x0 | b.x1))) - return f3_NaN(); - if (a_exp == 32767 || !(b.x0 | b.x1)) - return f3_infinity(a_sgn ^ b_sgn); - if (!(a.x0 | a.x1) || b_exp == 32767) - return f3_zero(a_sgn ^ b_sgn); - - a = f3_normalise(&a_exp, a); - b = f3_normalise(&b_exp, b); - - x_sgn = a_sgn ^ b_sgn; - x_exp = a_exp - b_exp + 16395; - - a.x0 = a.x0 >> 1 | a.x1 << 63; - a.x1 = a.x1 >> 1; - b.x0 = b.x0 >> 1 | b.x1 << 63; - b.x1 = b.x1 >> 1; - x.x0 = 0; - x.x1 = 0; - for (i = 0; i < 116; i++) { - x.x1 = x.x1 << 1 | x.x0 >> 63; - x.x0 = x.x0 << 1; - if (a.x1 > b.x1 || (a.x1 == b.x1 && a.x0 >= b.x0)) { - a.x1 = a.x1 - b.x1 - (a.x0 < b.x0); - a.x0 = a.x0 - b.x0; - x.x0 |= 1; - } - a.x1 = a.x1 << 1 | a.x0 >> 63; - a.x0 = a.x0 << 1; - } - x.x0 |= !!(a.x0 | a.x1); - - x = f3_normalise(&x_exp, x); - - return f3_round(x_sgn, x_exp, x); -} - -long double __extendsftf2(float f) -{ - long double fx; - u128_t x; - uint32_t a; - uint64_t aa; - memcpy(&a, &f, 4); - aa = a; - x.x0 = 0; - if (!(a << 1)) - x.x1 = aa << 32; - else if (a << 1 >> 24 == 255) - x.x1 = (0x7fff000000000000 | aa >> 31 << 63 | aa << 41 >> 16 | - (uint64_t)!!(a << 9) << 47); - else if (a << 1 >> 24 == 0) { - uint64_t adj = 0; - while (!(a << 1 >> 1 >> (23 - adj))) - adj++; - x.x1 = aa >> 31 << 63 | (16256 - adj + 1) << 48 | aa << adj << 41 >> 16; - } else - x.x1 = (aa >> 31 << 63 | ((aa >> 23 & 255) + 16256) << 48 | - aa << 41 >> 16); - memcpy(&fx, &x, 16); - return fx; -} - -long double __extenddftf2(double f) -{ - long double fx; - u128_t x; - uint64_t a; - memcpy(&a, &f, 8); - x.x0 = a << 60; - if (!(a << 1)) - x.x1 = a; - else if (a << 1 >> 53 == 2047) - x.x1 = (0x7fff000000000000 | a >> 63 << 63 | a << 12 >> 16 | - (uint64_t)!!(a << 12) << 47); - else if (a << 1 >> 53 == 0) { - uint64_t adj = 0; - while (!(a << 1 >> 1 >> (52 - adj))) - adj++; - x.x0 <<= adj; - x.x1 = a >> 63 << 63 | (15360 - adj + 1) << 48 | a << adj << 12 >> 16; - } else - x.x1 = a >> 63 << 63 | ((a >> 52 & 2047) + 15360) << 48 | a << 12 >> 16; - memcpy(&fx, &x, 16); - return fx; -} - -float __trunctfsf2(long double f) -{ - u128_t mnt; - int32_t exp; - int sgn; - uint32_t x; - float fx; - - f3_unpack(&sgn, &exp, &mnt, f); - - if (exp == 32767 && (mnt.x0 | mnt.x1 << 16)) - x = 0x7fc00000 | (uint32_t)sgn << 31 | (mnt.x1 >> 25 & 0x007fffff); - else if (exp > 16510) - x = 0x7f800000 | (uint32_t)sgn << 31; - else if (exp < 16233) - x = (uint32_t)sgn << 31; - else { - exp -= 16257; - x = mnt.x1 >> 23 | !!(mnt.x0 | mnt.x1 << 41); - if (exp < 0) { - x = x >> -exp | !!(x << (32 + exp)); - exp = 0; - } - if ((x & 3) == 3 || (x & 7) == 6) - x += 4; - x = ((x >> 2) + (exp << 23)) | (uint32_t)sgn << 31; - } - memcpy(&fx, &x, 4); - return fx; -} - -double __trunctfdf2(long double f) -{ - u128_t mnt; - int32_t exp; - int sgn; - uint64_t x; - double fx; - - f3_unpack(&sgn, &exp, &mnt, f); - - if (exp == 32767 && (mnt.x0 | mnt.x1 << 16)) - x = (0x7ff8000000000000 | (uint64_t)sgn << 63 | - mnt.x1 << 16 >> 12 | mnt.x0 >> 60); - else if (exp > 17406) - x = 0x7ff0000000000000 | (uint64_t)sgn << 63; - else if (exp < 15308) - x = (uint64_t)sgn << 63; - else { - exp -= 15361; - x = mnt.x1 << 6 | mnt.x0 >> 58 | !!(mnt.x0 << 6); - if (exp < 0) { - x = x >> -exp | !!(x << (64 + exp)); - exp = 0; - } - if ((x & 3) == 3 || (x & 7) == 6) - x += 4; - x = ((x >> 2) + ((uint64_t)exp << 52)) | (uint64_t)sgn << 63; - } - memcpy(&fx, &x, 8); - return fx; -} - -int32_t __fixtfsi(long double fa) -{ - u128_t a; - int32_t a_exp; - int a_sgn; - int32_t x; - f3_unpack(&a_sgn, &a_exp, &a, fa); - if (a_exp < 16369) - return 0; - if (a_exp > 16413) - return a_sgn ? -0x80000000 : 0x7fffffff; - x = a.x1 >> (16431 - a_exp); - return a_sgn ? -x : x; -} - -int64_t __fixtfdi(long double fa) -{ - u128_t a; - int32_t a_exp; - int a_sgn; - int64_t x; - f3_unpack(&a_sgn, &a_exp, &a, fa); - if (a_exp < 16383) - return 0; - if (a_exp > 16445) - return a_sgn ? -0x8000000000000000 : 0x7fffffffffffffff; - x = (a.x1 << 15 | a.x0 >> 49) >> (16446 - a_exp); - return a_sgn ? -x : x; -} - -uint32_t __fixunstfsi(long double fa) -{ - u128_t a; - int32_t a_exp; - int a_sgn; - f3_unpack(&a_sgn, &a_exp, &a, fa); - if (a_sgn || a_exp < 16369) - return 0; - if (a_exp > 16414) - return -1; - return a.x1 >> (16431 - a_exp); -} - -uint64_t __fixunstfdi(long double fa) -{ - u128_t a; - int32_t a_exp; - int a_sgn; - f3_unpack(&a_sgn, &a_exp, &a, fa); - if (a_sgn || a_exp < 16383) - return 0; - if (a_exp > 16446) - return -1; - return (a.x1 << 15 | a.x0 >> 49) >> (16446 - a_exp); -} - -long double __floatsitf(int32_t a) -{ - int sgn = 0; - int exp = 16414; - uint32_t mnt = a; - u128_t x = { 0, 0 }; - long double f; - int i; - if (a) { - if (a < 0) { - sgn = 1; - mnt = -mnt; - } - for (i = 16; i; i >>= 1) - if (!(mnt >> (32 - i))) { - mnt <<= i; - exp -= i; - } - x.x1 = ((uint64_t)sgn << 63 | (uint64_t)exp << 48 | - (uint64_t)(mnt << 1) << 16); - } - memcpy(&f, &x, 16); - return f; -} - -long double __floatditf(int64_t a) -{ - int sgn = 0; - int exp = 16446; - uint64_t mnt = a; - u128_t x = { 0, 0 }; - long double f; - int i; - if (a) { - if (a < 0) { - sgn = 1; - mnt = -mnt; - } - for (i = 32; i; i >>= 1) - if (!(mnt >> (64 - i))) { - mnt <<= i; - exp -= i; - } - x.x0 = mnt << 49; - x.x1 = (uint64_t)sgn << 63 | (uint64_t)exp << 48 | mnt << 1 >> 16; - } - memcpy(&f, &x, 16); - return f; -} - -long double __floatunsitf(uint32_t a) -{ - int exp = 16414; - uint32_t mnt = a; - u128_t x = { 0, 0 }; - long double f; - int i; - if (a) { - for (i = 16; i; i >>= 1) - if (!(mnt >> (32 - i))) { - mnt <<= i; - exp -= i; - } - x.x1 = (uint64_t)exp << 48 | (uint64_t)(mnt << 1) << 16; - } - memcpy(&f, &x, 16); - return f; -} - -long double __floatunditf(uint64_t a) -{ - int exp = 16446; - uint64_t mnt = a; - u128_t x = { 0, 0 }; - long double f; - int i; - if (a) { - for (i = 32; i; i >>= 1) - if (!(mnt >> (64 - i))) { - mnt <<= i; - exp -= i; - } - x.x0 = mnt << 49; - x.x1 = (uint64_t)exp << 48 | mnt << 1 >> 16; - } - memcpy(&f, &x, 16); - return f; -} - -static int f3_cmp(long double fa, long double fb) -{ - u128_t a, b; - memcpy(&a, &fa, 16); - memcpy(&b, &fb, 16); - return (!(a.x0 | a.x1 << 1 | b.x0 | b.x1 << 1) ? 0 : - ((a.x1 << 1 >> 49 == 0x7fff && (a.x0 | a.x1 << 16)) || - (b.x1 << 1 >> 49 == 0x7fff && (b.x0 | b.x1 << 16))) ? 2 : - a.x1 >> 63 != b.x1 >> 63 ? (int)(b.x1 >> 63) - (int)(a.x1 >> 63) : - a.x1 < b.x1 ? (int)(a.x1 >> 63 << 1) - 1 : - a.x1 > b.x1 ? 1 - (int)(a.x1 >> 63 << 1) : - a.x0 < b.x0 ? (int)(a.x1 >> 63 << 1) - 1 : - b.x0 < a.x0 ? 1 - (int)(a.x1 >> 63 << 1) : 0); -} - -int __eqtf2(long double a, long double b) -{ - return !!f3_cmp(a, b); -} - -int __netf2(long double a, long double b) -{ - return !!f3_cmp(a, b); -} - -int __lttf2(long double a, long double b) -{ - return f3_cmp(a, b); -} - -int __letf2(long double a, long double b) -{ - return f3_cmp(a, b); -} - -int __gttf2(long double a, long double b) -{ - return -f3_cmp(b, a); -} - -int __getf2(long double a, long double b) -{ - return -f3_cmp(b, a); -} diff --git a/libtcc1/libtcc1.c b/libtcc1/libtcc1.c index 9fb00aa6..e7e77496 100644 --- a/libtcc1/libtcc1.c +++ b/libtcc1/libtcc1.c @@ -106,11 +106,7 @@ union float_long { unsigned int l; }; -/* XXX: we don't support several builtin supports for now */ -#if !defined __x86_64__ && !defined __arm__ && !defined __riscv - /* XXX: use gcc/tcc intrinsic ? */ -#if defined __i386__ #define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("subl %5,%1\n\tsbbl %3,%0" \ : "=r" ((USItype) (sh)), \ @@ -139,9 +135,6 @@ union float_long { : "=r" (__cbtmp) : "rm" ((USItype) (x))); \ (count) = __cbtmp ^ 31; \ } while (0) -#else -#error unsupported CPU type -#endif /* most of this code is taken from libgcc2.c from gcc */ @@ -478,7 +471,6 @@ long long __ashldi3(long long a, int b) #endif } -#endif /* !__x86_64__ */ /* XXX: fix tcc's code generator to do this instead */ float __floatundisf(unsigned long long a) @@ -594,7 +586,6 @@ long long __fixdfdi (double a1) return s ? ret : -ret; } -#ifndef __arm__ unsigned long long __fixunsxfdi (long double a1) { register union ldouble_long dl1; @@ -624,18 +615,6 @@ long long __fixxfdi (long double a1) ret = __fixunsxfdi((s = a1 >= 0) ? a1 : -a1); return s ? ret : -ret; } -#endif /* !ARM */ -#if defined __x86_64__ -/* float constants used for unary minus operation */ -const float __mzerosf = -0.0; -const double __mzerodf = -0.0; -#endif -#if defined _WIN64 -/* MSVC x64 intrinsic */ -void __faststorefence(void) -{ - __asm__("lock; orl $0,(%rsp)"); -} -#endif + diff --git a/libtcc1/runmain.c b/libtcc1/runmain.c deleted file mode 100644 index ed089c87..00000000 --- a/libtcc1/runmain.c +++ /dev/null @@ -1,86 +0,0 @@ -/* ------------------------------------------------------------- */ -/* support for tcc_run() */ - -#ifdef __leading_underscore -# define _(s) s -#else -# define _(s) _##s -#endif - -#ifndef _WIN32 -extern void (*_(_init_array_start)[]) (int argc, char **argv, char **envp); -extern void (*_(_init_array_end)[]) (int argc, char **argv, char **envp); -static void run_ctors(int argc, char **argv, char **env) -{ - int i = 0; - while (&_(_init_array_start)[i] != _(_init_array_end)) - (*_(_init_array_start)[i++])(argc, argv, env); -} -#endif - -extern void (*_(_fini_array_start)[]) (void); -extern void (*_(_fini_array_end)[]) (void); -static void run_dtors(void) -{ - int i = 0; - while (&_(_fini_array_end)[i] != _(_fini_array_start)) - (*_(_fini_array_end)[--i])(); -} - -static void *rt_exitfunc[32]; -static void *rt_exitarg[32]; -static int __rt_nr_exit; - -void __run_on_exit(int ret) -{ - int n = __rt_nr_exit; - while (n) - --n, ((void(*)(int,void*))rt_exitfunc[n])(ret, rt_exitarg[n]); -} - -int on_exit(void *function, void *arg) -{ - int n = __rt_nr_exit; - if (n < 32) { - rt_exitfunc[n] = function; - rt_exitarg[n] = arg; - __rt_nr_exit = n + 1; - return 0; - } - return 1; -} - -int atexit(void (*function)(void)) -{ - return on_exit(function, 0); -} - -typedef struct rt_frame { - void *ip, *fp, *sp; -} rt_frame; - -__attribute__((noreturn)) void __rt_exit(rt_frame *, int); - -void exit(int code) -{ - rt_frame f; - run_dtors(); - __run_on_exit(code); - f.fp = 0; - f.ip = exit; - __rt_exit(&f, code); -} - -#ifndef _WIN32 -int main(int, char**, char**); - -int _runmain(int argc, char **argv, char **envp) -{ - int ret; - run_ctors(argc, argv, envp); - ret = main(argc, argv, envp); - run_dtors(); - __run_on_exit(ret); - return ret; -} -#endif diff --git a/libtcc1/stdatomic.c b/libtcc1/stdatomic.c index 732657a8..1a4cd58f 100644 --- a/libtcc1/stdatomic.c +++ b/libtcc1/stdatomic.c @@ -18,7 +18,6 @@ typedef __SIZE_TYPE__ size_t; void __atomic_thread_fence(int memorder); #define MemoryBarrier(memorder) __atomic_thread_fence(memorder) -#if defined __i386__ || defined __x86_64__ #define ATOMIC_COMPARE_EXCHANGE(TYPE, MODE, SUFFIX) \ bool __atomic_compare_exchange_##MODE \ (volatile void *atom, void *ref, TYPE xchg, \ @@ -35,12 +34,7 @@ void __atomic_thread_fence(int memorder); *(TYPE *)ref = rv; \ return (rv == cmp); \ } -#else -#define ATOMIC_COMPARE_EXCHANGE(TYPE, MODE, SUFFIX) \ - extern bool __atomic_compare_exchange_##MODE \ - (volatile void *atom, void *ref, TYPE xchg, \ - bool weak, int success_memorder, int failure_memorder); -#endif + #define ATOMIC_LOAD(TYPE, MODE) \ TYPE __atomic_load_##MODE(const volatile void *atom, int memorder) \ @@ -116,9 +110,6 @@ void __atomic_thread_fence(int memorder); ATOMIC_GEN(uint8_t, 1, "b") ATOMIC_GEN(uint16_t, 2, "w") ATOMIC_GEN(uint32_t, 4, "l") -#if defined __x86_64__ || defined __aarch64__ || defined __riscv -ATOMIC_GEN(uint64_t, 8, "q") -#endif /* uses alias to allow building with gcc/clang */ #ifdef __TINYC__ @@ -133,17 +124,7 @@ void ATOMIC(signal_fence) (int memorder) void ATOMIC(thread_fence) (int memorder) { -#if defined __i386__ __asm__ volatile("lock orl $0, (%esp)"); -#elif defined __x86_64__ - __asm__ volatile("lock orq $0, (%rsp)"); -#elif defined __arm__ - __asm__ volatile(".int 0xee070fba"); // mcr p15, 0, r0, c7, c10, 5 -#elif defined __aarch64__ - __asm__ volatile(".int 0xd5033bbf"); // dmb ish -#elif defined __riscv - __asm__ volatile(".int 0x0ff0000f"); // fence iorw,iorw -#endif } bool ATOMIC(is_lock_free) (unsigned long size, const volatile void *ptr) @@ -154,11 +135,7 @@ bool ATOMIC(is_lock_free) (unsigned long size, const volatile void *ptr) case 1: ret = true; break; case 2: ret = true; break; case 4: ret = true; break; -#if defined __x86_64__ || defined __aarch64__ || defined __riscv - case 8: ret = true; break; -#else case 8: ret = false; break; -#endif default: ret = false; break; } return ret; diff --git a/libtcc1/tcclib.h b/libtcc1/tcclib.h deleted file mode 100644 index 8d59e4c9..00000000 --- a/libtcc1/tcclib.h +++ /dev/null @@ -1,80 +0,0 @@ -/* Simple libc header for TCC - * - * Add any function you want from the libc there. This file is here - * only for your convenience so that you do not need to put the whole - * glibc include files on your floppy disk - */ -#ifndef _TCCLIB_H -#define _TCCLIB_H - -#include -#include - -/* stdlib.h */ -void *calloc(size_t nmemb, size_t size); -void *malloc(size_t size); -void free(void *ptr); -void *realloc(void *ptr, size_t size); -int atoi(const char *nptr); -long int strtol(const char *nptr, char **endptr, int base); -unsigned long int strtoul(const char *nptr, char **endptr, int base); -void exit(int); - -/* stdio.h */ -typedef struct __FILE FILE; -#define EOF (-1) -extern FILE *stdin; -extern FILE *stdout; -extern FILE *stderr; -FILE *fopen(const char *path, const char *mode); -FILE *fdopen(int fildes, const char *mode); -FILE *freopen(const char *path, const char *mode, FILE *stream); -int fclose(FILE *stream); -size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); -size_t fwrite(void *ptr, size_t size, size_t nmemb, FILE *stream); -int fgetc(FILE *stream); -char *fgets(char *s, int size, FILE *stream); -int getc(FILE *stream); -int getchar(void); -char *gets(char *s); -int ungetc(int c, FILE *stream); -int fflush(FILE *stream); -int putchar (int c); - -int printf(const char *format, ...); -int fprintf(FILE *stream, const char *format, ...); -int sprintf(char *str, const char *format, ...); -int snprintf(char *str, size_t size, const char *format, ...); -int asprintf(char **strp, const char *format, ...); -int dprintf(int fd, const char *format, ...); -int vprintf(const char *format, va_list ap); -int vfprintf(FILE *stream, const char *format, va_list ap); -int vsprintf(char *str, const char *format, va_list ap); -int vsnprintf(char *str, size_t size, const char *format, va_list ap); -int vasprintf(char **strp, const char *format, va_list ap); -int vdprintf(int fd, const char *format, va_list ap); - -void perror(const char *s); - -/* string.h */ -char *strcat(char *dest, const char *src); -char *strchr(const char *s, int c); -char *strrchr(const char *s, int c); -char *strcpy(char *dest, const char *src); -void *memcpy(void *dest, const void *src, size_t n); -void *memmove(void *dest, const void *src, size_t n); -void *memset(void *s, int c, size_t n); -char *strdup(const char *s); -size_t strlen(const char *s); - -/* dlfcn.h */ -#define RTLD_LAZY 0x001 -#define RTLD_NOW 0x002 -#define RTLD_GLOBAL 0x100 - -void *dlopen(const char *filename, int flag); -const char *dlerror(void); -void *dlsym(void *handle, char *symbol); -int dlclose(void *handle); - -#endif /* _TCCLIB_H */ diff --git a/libtcc1/tcov.c b/libtcc1/tcov.c deleted file mode 100644 index af09a734..00000000 --- a/libtcc1/tcov.c +++ /dev/null @@ -1,428 +0,0 @@ -#include -#include -#include -#include -#ifndef _WIN32 -#include -#include -#else -#include -#include -#endif - -/* section layout (all little endian): - 32bit offset to executable/so file name - filename \0 - function name \0 - align to 64 bits - 64bit function start line - 64bits end_line(28bits) / start_line(28bits) / flag=0xff(8bits) - 64bits counter - \0 - \0 - \0 - executable/so file name \0 - */ - -typedef struct tcov_line { - unsigned int fline; - unsigned int lline; - unsigned long long count; -} tcov_line; - -typedef struct tcov_function { - char *function; - unsigned int first_line; - unsigned int n_line; - unsigned int m_line; - tcov_line *line; -} tcov_function; - -typedef struct tcov_file { - char *filename; - unsigned int n_func; - unsigned int m_func; - tcov_function *func; - struct tcov_file *next; -} tcov_file; - -static FILE *open_tcov_file (char *cov_filename) -{ - int fd; -#ifndef _WIN32 - struct flock lock; - - lock.l_type = F_WRLCK; - lock.l_whence = SEEK_SET; - lock.l_start = 0; - lock.l_len = 0; /* Until EOF. */ - lock.l_pid = getpid (); -#endif - fd = open (cov_filename, O_RDWR | O_CREAT, 0666); - if (fd < 0) - return NULL; - -#ifndef _WIN32 - while (fcntl (fd, F_SETLKW, &lock) && errno == EINTR) - continue; -#else - { - OVERLAPPED overlapped = { 0 }; - LockFileEx((HANDLE)_get_osfhandle(fd), LOCKFILE_EXCLUSIVE_LOCK, - 0, 1, 0, &overlapped); - } -#endif - - return fdopen (fd, "r+"); -} - -static unsigned long long get_value(unsigned char *p, int size) -{ - unsigned long long value = 0; - - p += size; - while (size--) - value = (value << 8) | *--p; - return value; -} - -static int sort_func (const void *p, const void *q) -{ - const tcov_function *pp = (const tcov_function *) p; - const tcov_function *pq = (const tcov_function *) q; - - return pp->first_line > pq->first_line ? 1 : - pp->first_line < pq->first_line ? -1 : 0; -} - -static int sort_line (const void *p, const void *q) -{ - const tcov_line *pp = (const tcov_line *) p; - const tcov_line *pq = (const tcov_line *) q; - - return pp->fline > pq->fline ? 1 : - pp->fline < pq->fline ? -1 : - pp->count < pq->count ? 1 : - pp->count > pq->count ? -1 : 0; -} - -/* sort to let inline functions work */ -static tcov_file *sort_test_coverage (unsigned char *p) -{ - int i, j, k; - unsigned char *start = p; - tcov_file *file = NULL; - tcov_file *nfile; - - p += 4; - while (*p) { - char *filename = (char *)p; - size_t len = strlen (filename); - - nfile = file; - while (nfile) { - if (strcmp (nfile->filename, filename) == 0) - break; - nfile = nfile->next; - } - if (nfile == NULL) { - nfile = malloc (sizeof(tcov_file)); - if (nfile == NULL) { - fprintf (stderr, "Malloc error test_coverage\n"); - return file; - } - nfile->filename = filename; - nfile->n_func = 0; - nfile->m_func = 0; - nfile->func = NULL; - nfile->next = NULL; - if (file == NULL) - file = nfile; - else { - tcov_file *lfile = file; - - while (lfile->next) - lfile = lfile->next; - lfile->next = nfile; - } - } - p += len + 1; - while (*p) { - int i; - char *function = (char *)p; - tcov_function *func; - - p += strlen (function) + 1; - p += -(p - start) & 7; - for (i = 0; i < nfile->n_func; i++) { - func = &nfile->func[i]; - if (strcmp (func->function, function) == 0) - break; - } - if (i == nfile->n_func) { - if (nfile->n_func >= nfile->m_func) { - nfile->m_func = nfile->m_func == 0 ? 4 : nfile->m_func * 2; - nfile->func = realloc (nfile->func, - nfile->m_func * - sizeof (tcov_function)); - if (nfile->func == NULL) { - fprintf (stderr, "Realloc error test_coverage\n"); - return file; - } - } - func = &nfile->func[nfile->n_func++]; - func->function = function; - func->first_line = get_value (p, 8); - func->n_line = 0; - func->m_line = 0; - func->line = NULL; - } - p += 8; - while (*p) { - tcov_line *line; - unsigned long long val; - - if (func->n_line >= func->m_line) { - func->m_line = func->m_line == 0 ? 4 : func->m_line * 2; - func->line = realloc (func->line, - func->m_line * sizeof (tcov_line)); - if (func->line == NULL) { - fprintf (stderr, "Realloc error test_coverage\n"); - return file; - } - } - line = &func->line[func->n_line++]; - val = get_value (p, 8); - line->fline = (val >> 8) & 0xfffffffULL; - line->lline = val >> 36; - line->count = get_value (p + 8, 8); - p += 16; - } - p++; - } - p++; - } - nfile = file; - while (nfile) { - qsort (nfile->func, nfile->n_func, sizeof (tcov_function), sort_func); - for (i = 0; i < nfile->n_func; i++) { - tcov_function *func = &nfile->func[i]; - qsort (func->line, func->n_line, sizeof (tcov_line), sort_line); - } - nfile = nfile->next; - } - return file; -} - -/* merge with previous tcov file */ -static void merge_test_coverage (tcov_file *file, FILE *fp, - unsigned int *pruns) -{ - unsigned int runs; - char *p; - char str[10000]; - - *pruns = 1; - if (fp == NULL) - return; - if (fgets(str, sizeof(str), fp) && - (p = strrchr (str, ':')) && - (sscanf (p + 1, "%u", &runs) == 1)) - *pruns = runs + 1; - while (file) { - int i; - size_t len = strlen (file->filename); - - while (fgets(str, sizeof(str), fp) && - (p = strstr(str, "0:File:")) == NULL) {} - if ((p = strstr(str, "0:File:")) == NULL || - strncmp (p + strlen("0:File:"), file->filename, len) != 0 || - p[strlen("0:File:") + len] != ' ') - break; - for (i = 0; i < file->n_func; i++) { - int j; - tcov_function *func = &file->func[i]; - unsigned int next_zero = 0; - unsigned int curline = 0; - - for (j = 0; j < func->n_line; j++) { - tcov_line *line = &func->line[j]; - unsigned int fline = line->fline; - unsigned long long count; - unsigned int tmp; - char c; - - while (curline < fline && - fgets(str, sizeof(str), fp)) - if ((p = strchr(str, ':')) && - sscanf (p + 1, "%u", &tmp) == 1) - curline = tmp; - if (sscanf (str, "%llu%c\n", &count, &c) == 2) { - if (next_zero == 0) - line->count += count; - next_zero = c == '*'; - } - } - } - file = file->next; - } -} - -/* store tcov data in file */ -void __store_test_coverage (unsigned char * p) -{ - int i, j; - unsigned int files; - unsigned int funcs; - unsigned int blocks; - unsigned int blocks_run; - unsigned int runs; - char *cov_filename = (char *)p + get_value (p, 4); - FILE *fp; - char *q; - tcov_file *file; - tcov_file *nfile; - tcov_function *func; - - fp = open_tcov_file (cov_filename); - if (fp == NULL) { - fprintf (stderr, "Cannot create coverage file: %s\n", cov_filename); - return; - } - file = sort_test_coverage (p); - merge_test_coverage (file, fp, &runs); - fseek (fp, 0, SEEK_SET); - fprintf (fp, " -: 0:Runs:%u\n", runs); - files = 0; - funcs = 0; - blocks = 0; - blocks_run = 0; - nfile = file; - while (nfile) { - files++; - for (i = 0; i < nfile->n_func; i++) { - func = &nfile->func[i]; - funcs++; - for (j = 0; j < func->n_line; j++) { - blocks++; - blocks_run += func->line[j].count != 0; - } - } - nfile = nfile->next; - } - if (blocks == 0) - blocks = 1; - fprintf (fp, " -: 0:All:%s Files:%u Functions:%u %.02f%%\n", - cov_filename, files, funcs, 100.0 * (double) blocks_run / blocks); - nfile = file; - while (nfile) { - FILE *src = fopen (nfile->filename, "r"); - unsigned int curline = 1; - char str[10000]; - - if (src == NULL) - goto next; - funcs = 0; - blocks = 0; - blocks_run = 0; - for (i = 0; i < nfile->n_func; i++) { - func = &nfile->func[i]; - funcs++; - for (j = 0; j < func->n_line; j++) { - blocks++; - blocks_run += func->line[j].count != 0; - } - } - if (blocks == 0) - blocks = 1; - fprintf (fp, " -: 0:File:%s Functions:%u %.02f%%\n", - nfile->filename, funcs, 100.0 * (double) blocks_run / blocks); - for (i = 0; i < nfile->n_func; i++) { - func = &nfile->func[i]; - - while (curline < func->first_line && - fgets(str, sizeof(str), src)) - fprintf (fp, " -:%5u:%s", curline++, str); - blocks = 0; - blocks_run = 0; - for (j = 0; j < func->n_line; j++) { - blocks++; - blocks_run += func->line[j].count != 0; - } - if (blocks == 0) - blocks = 1; - fprintf (fp, " -: 0:Function:%s %.02f%%\n", - func->function, 100.0 * (double) blocks_run / blocks); -#if 0 - for (j = 0; j < func->n_line; j++) { - unsigned int fline = func->line[j].fline; - unsigned int lline = func->line[j].lline; - unsigned long long count = func->line[j].count; - - fprintf (fp, "%u %u %llu\n", fline, lline, count); - } -#endif - for (j = 0; j < func->n_line;) { - unsigned int fline = func->line[j].fline; - unsigned int lline = func->line[j].lline; - unsigned long long count = func->line[j].count; - unsigned int has_zero = 0; - unsigned int same_line = fline == lline; - - j++; - while (j < func->n_line) { - unsigned int nfline = func->line[j].fline; - unsigned int nlline = func->line[j].lline; - unsigned long long ncount = func->line[j].count; - - if (fline == nfline) { - if (ncount == 0) - has_zero = 1; - else if (ncount > count) - count = ncount; - same_line = nfline == nlline; - lline = nlline; - j++; - } - else - break; - } - if (same_line) - lline++; - - while (curline < fline && - fgets(str, sizeof(str), src)) - fprintf (fp, " -:%5u:%s", curline++, str); - while (curline < lline && - fgets(str, sizeof(str), src)) { - if (count == 0) - fprintf (fp, " #####:%5u:%s", - curline, str); - else if (has_zero) - fprintf (fp, "%8llu*:%5u:%s", - count, curline, str); - else - fprintf (fp, "%9llu:%5u:%s", - count, curline, str); - curline++; - } - } - } - while (fgets(str, sizeof(str), src)) - fprintf (fp, " -:%5u:%s", curline++, str); - fclose (src); -next: - nfile = nfile->next; - } - while (file) { - for (i = 0; i < file->n_func; i++) { - func = &file->func[i]; - free (func->line); - } - free (file->func); - nfile = file; - file = file->next; - free (nfile); - } - fclose (fp); -} diff --git a/libtcc1/va_list.c b/libtcc1/va_list.c deleted file mode 100644 index 1fb55127..00000000 --- a/libtcc1/va_list.c +++ /dev/null @@ -1,67 +0,0 @@ -/* va_list.c - tinycc support for va_list on X86_64 */ - -#if defined __x86_64__ - -/* Avoid include files, they may not be available when cross compiling */ -extern void abort(void); - -/* This should be in sync with our include/stdarg.h */ -enum __va_arg_type { - __va_gen_reg, __va_float_reg, __va_stack -}; - -/* GCC compatible definition of va_list. */ -/*predefined by TCC (tcc_predefs.h): -typedef struct { - unsigned int gp_offset; - unsigned int fp_offset; - union { - unsigned int overflow_offset; - char *overflow_arg_area; - }; - char *reg_save_area; -} __builtin_va_list[1]; -*/ - -extern void *memcpy(void *dest, const void *src, unsigned long n); - -void *__va_arg(__builtin_va_list ap, - int arg_type, - int size, int align) -{ - size = (size + 7) & ~7; - align = (align + 7) & ~7; - switch ((enum __va_arg_type)arg_type) { - case __va_gen_reg: - if (ap->gp_offset + size <= 48) { - ap->gp_offset += size; - return ap->reg_save_area + ap->gp_offset - size; - } - goto use_overflow_area; - - case __va_float_reg: - if (ap->fp_offset < 128 + 48) { - ap->fp_offset += 16; - if (size == 8) - return ap->reg_save_area + ap->fp_offset - 16; - if (ap->fp_offset < 128 + 48) { - memcpy(ap->reg_save_area + ap->fp_offset - 8, - ap->reg_save_area + ap->fp_offset, 8); - ap->fp_offset += 16; - return ap->reg_save_area + ap->fp_offset - 32; - } - } - goto use_overflow_area; - - case __va_stack: - use_overflow_area: - ap->overflow_arg_area += size; - ap->overflow_arg_area = (char*)((long long)(ap->overflow_arg_area + align - 1) & -align); - return ap->overflow_arg_area - size; - - default: /* should never happen */ - abort(); - return 0; - } -} -#endif diff --git a/tcc/Makefile.am b/tcc/Makefile.am index a268a1df..05738192 100644 --- a/tcc/Makefile.am +++ b/tcc/Makefile.am @@ -2,4 +2,4 @@ bin_PROGRAMS = tcc tcc_SOURCES = tcc.c tcctools.c tcc_LDADD = ../libtcc/libtcc.a -tcc_CPPFLAGS = -I$(top_srcdir) +tcc_CPPFLAGS = -I$(top_srcdir)/libtcc/include -I$(top_srcdir)/libtcc diff --git a/tcc/tcc.c b/tcc/tcc.c index 0d97bb3b..11182549 100644 --- a/tcc/tcc.c +++ b/tcc/tcc.c @@ -19,7 +19,7 @@ */ #include "config.h" -#include "libtcc/tcc.h" +#include #include "tcctools.h" static const char HELP_STR[] = @@ -136,7 +136,6 @@ static void print_search_dirs(TCCState *s) 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) @@ -215,8 +214,6 @@ redo: 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) diff --git a/tcc/tcc_new.c b/tcc/tcc_new.c index db8e12b0..e0031599 100644 --- a/tcc/tcc_new.c +++ b/tcc/tcc_new.c @@ -33,7 +33,6 @@ static const char help_str[] = "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" @@ -52,12 +51,7 @@ static const char help_str[] = " -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" @@ -81,12 +75,10 @@ static const char help_more_str[] = " -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" + " -arch -C --param -pedantic -pipe -s -traditional -g -static -shared\n" "-W[no-]... warnings:\n" " all turn on some (*) warnings\n" " error[=warning] stop after warning (any or specified)\n" @@ -104,20 +96,14 @@ static const char help_more_str[] = " 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" diff --git a/tcc/tcctools.c b/tcc/tcctools.c index e36a388a..57d22558 100644 --- a/tcc/tcctools.c +++ b/tcc/tcctools.c @@ -28,7 +28,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "libtcc/tcc.h" +#include "tcc.h" //#define ARMAG "!\n" #define ARFMAG "`\n" @@ -54,7 +54,7 @@ static int ar_usage(int ret) { return ret; } -ST_FUNC int tcc_tool_ar(TCCState *s1, int argc, char **argv) +int tcc_tool_ar(TCCState *s1, int argc, char **argv) { static const ArHdr arhdr_init = { "/ ", @@ -357,93 +357,6 @@ the_end: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* re-execute the i386/x86_64 cross-compilers with tcc -m32/-m64: */ - -#if !defined TCC_TARGET_I386 && !defined TCC_TARGET_X86_64 - -ST_FUNC int tcc_tool_cross(TCCState *s1, char **argv, int option) -{ - tcc_error_noabort("-m%d not implemented.", option); - return 1; -} - -#else -#ifdef _WIN32 -#include - -/* - Empty argument or with space/tab (not newline) requires quoting. - * - Double-quotes at the value require '\'-escape, regardless of quoting. - * - Consecutive (or 1) backslashes at the value all need '\'-escape only if - * followed by [escaped] double quote, else taken literally, e.g. - * remains literal without quoting or esc, but becomes . - * - This "before double quote" rule applies also before delimiting quoting, - * e.g. becomes <"x\y \\\"z\\"> (quoting required because space). - * - * https://learn.microsoft.com/en-us/cpp/c-language/parsing-c-command-line-arguments - */ -static char *quote_win32(const char *s) -{ - char *o, *r = tcc_malloc(2 * strlen(s) + 3); /* max-esc, quotes, \0 */ - int cbs = 0, quoted = !*s; /* consecutive backslashes before current */ - - for (o = r; *s; *o++ = *s++) { - quoted |= *s == ' ' || *s == '\t'; - if (*s == '\\' || *s == '"') - *o++ = '\\'; - else - o -= cbs; /* undo cbs escapes, if any (not followed by DQ) */ - cbs = *s == '\\' ? cbs + 1 : 0; - } - if (quoted) { - memmove(r + 1, r, o++ - r); - *r = *o++ = '"'; - } else { - o -= cbs; - } - - *o = 0; - return r; /* don't bother with realloc(r, o-r+1) */ -} - -static int execvp_win32(const char *prog, char **argv) -{ - int ret; char **p; - /* replace all " by \" */ - for (p = argv; *p; ++p) - *p = quote_win32(*p); - ret = _spawnvp(P_NOWAIT, prog, (const char *const*)argv); - if (-1 == ret) - return ret; - _cwait(&ret, ret, WAIT_CHILD); - exit(ret); -} -#define execvp execvp_win32 -#endif /* _WIN32 */ - -ST_FUNC int tcc_tool_cross(TCCState *s1, char **argv, int target) -{ - char program[4096]; - char *a0 = argv[0]; - int prefix = tcc_basename(a0) - a0; - - snprintf(program, sizeof program, - "%.*s%s" -#ifdef TCC_TARGET_PE - "-win32" -#endif - "-tcc" -#ifdef _WIN32 - ".exe" -#endif - , prefix, a0, target == 64 ? "x86_64" : "i386"); - - if (strcmp(a0, program)) - execvp(argv[0] = program, argv); - tcc_error_noabort("could not run '%s'", program); - return 1; -} - -#endif /* TCC_TARGET_I386 && TCC_TARGET_X86_64 */ /* -------------------------------------------------------------- */ /* enable commandline wildcard expansion (tcc -o x.exe *.c) */ @@ -470,7 +383,7 @@ static char *escape_target_dep(const char *s) { return res; } -ST_FUNC int gen_makedeps(TCCState *s1, const char *target, const char *filename) +int gen_makedeps(TCCState *s1, const char *target, const char *filename) { FILE *depout; char buf[1024]; diff --git a/tcc/tcctools.h b/tcc/tcctools.h index bcb0a7cf..2a4a9685 100644 --- a/tcc/tcctools.h +++ b/tcc/tcctools.h @@ -1,10 +1,9 @@ #ifndef TCC_TCCTOOLS_H # define TCC_TCCTOOLS_H 1 -# include "libtcc/libtcc.h" +# include "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 */ \ No newline at end of file