Further strip down tcc
This commit is contained in:
parent
94b74d446f
commit
c5d1e40ebe
30 changed files with 723 additions and 1881 deletions
|
@ -1,6 +1,7 @@
|
||||||
noinst_LIBRARIES = libtcc.a
|
noinst_LIBRARIES = libtcc.a
|
||||||
libtcc_a_SOURCES = libtcc.c option.c path.c memory.c tccpp.c tccgen.c \
|
libtcc_a_SOURCES = libtcc.c option.c path.c io.c memory.c \
|
||||||
tccasm.c tccelf.c \
|
cc/tccpp.c cc/tccgen.c \
|
||||||
i386/gen.c i386/link.c \
|
cc/tccasm.c tccelf.c \
|
||||||
i386/asm.c tcccoff.c
|
cc/i386/gen.c cc/i386/link.c \
|
||||||
|
cc/i386/asm.c tcccoff.c
|
||||||
libtcc_a_CPPFLAGS = -I$(top_srcdir) -I$(srcdir) -I$(srcdir)/include
|
libtcc_a_CPPFLAGS = -I$(top_srcdir) -I$(srcdir) -I$(srcdir)/include
|
275
libtcc/cc/cc.h
Normal file
275
libtcc/cc/cc.h
Normal file
|
@ -0,0 +1,275 @@
|
||||||
|
#ifndef TCC_CC_H
|
||||||
|
# define TCC_CC_H
|
||||||
|
|
||||||
|
# include <tcc.h>
|
||||||
|
|
||||||
|
/* ------------ tccpp.c ------------ */
|
||||||
|
|
||||||
|
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 */
|
||||||
|
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 */
|
||||||
|
#define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
|
||||||
|
|
||||||
|
#define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
|
||||||
|
#define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */
|
||||||
|
#define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a
|
||||||
|
token. line feed is also
|
||||||
|
returned at eof */
|
||||||
|
#define PARSE_FLAG_ASM_FILE 0x0008 /* we processing an asm file: '#' can be used for line comment, etc. */
|
||||||
|
#define PARSE_FLAG_SPACES 0x0010 /* next() returns space tokens (for -E) */
|
||||||
|
#define PARSE_FLAG_ACCEPT_STRAYS 0x0020 /* next() returns '\\' token */
|
||||||
|
#define PARSE_FLAG_TOK_STR 0x0040 /* return parsed strings instead of TOK_PPSTR */
|
||||||
|
|
||||||
|
/* isidnum_table flags: */
|
||||||
|
#define IS_SPC 1
|
||||||
|
#define IS_ID 2
|
||||||
|
#define IS_NUM 4
|
||||||
|
|
||||||
|
enum line_macro_output_format {
|
||||||
|
LINE_MACRO_OUTPUT_FORMAT_GCC,
|
||||||
|
LINE_MACRO_OUTPUT_FORMAT_NONE,
|
||||||
|
LINE_MACRO_OUTPUT_FORMAT_STD,
|
||||||
|
LINE_MACRO_OUTPUT_FORMAT_P10 = 11
|
||||||
|
};
|
||||||
|
|
||||||
|
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 */
|
||||||
|
static inline int is_space(int ch) {
|
||||||
|
return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
|
||||||
|
}
|
||||||
|
static inline int isid(int c) {
|
||||||
|
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';
|
||||||
|
}
|
||||||
|
static inline int isnum(int c) {
|
||||||
|
return c >= '0' && c <= '9';
|
||||||
|
}
|
||||||
|
static inline int isoct(int c) {
|
||||||
|
return c >= '0' && c <= '7';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------ tccgen.c ------------ */
|
||||||
|
|
||||||
|
#define SYM_POOL_NB (8192 / sizeof(Sym))
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
void tccgen_init(TCCState *s1);
|
||||||
|
int tccgen_compile(TCCState *s1);
|
||||||
|
void tccgen_finish(TCCState *s1);
|
||||||
|
void check_vstack(void);
|
||||||
|
|
||||||
|
int is_float(int t);
|
||||||
|
int ieee_finite(double d);
|
||||||
|
int exact_log2p1(int i);
|
||||||
|
void test_lvalue(void);
|
||||||
|
|
||||||
|
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
|
||||||
|
void greloc(Section *s, Sym *sym, unsigned long offset, int type);
|
||||||
|
#endif
|
||||||
|
void greloca(Section *s, Sym *sym, unsigned long offset, int type, addr_t addend);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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
|
||||||
|
void lexpand(void);
|
||||||
|
#endif
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* ------------ xxx-link.c ------------ */
|
||||||
|
|
||||||
|
#if !defined ELF_OBJ_ONLY
|
||||||
|
int code_reloc (int reloc_type);
|
||||||
|
#define NEED_RELOC_TYPE
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val);
|
||||||
|
|
||||||
|
|
||||||
|
/* ------------ xxx-gen.c ------------ */
|
||||||
|
extern const char * const target_machine_defs;
|
||||||
|
extern const int reg_classes[NB_REGS];
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
static inline void write16le(unsigned char *p, uint16_t x) {
|
||||||
|
p[0] = x & 255; p[1] = x >> 8 & 255;
|
||||||
|
}
|
||||||
|
static inline uint32_t read32le(unsigned char *p) {
|
||||||
|
return read16le(p) | (uint32_t)read16le(p + 2) << 16;
|
||||||
|
}
|
||||||
|
static inline void write32le(unsigned char *p, uint32_t x) {
|
||||||
|
write16le(p, x); write16le(p + 2, x >> 16);
|
||||||
|
}
|
||||||
|
static inline void add32le(unsigned char *p, int32_t x) {
|
||||||
|
write32le(p, read32le(p) + x);
|
||||||
|
}
|
||||||
|
static inline uint64_t read64le(unsigned char *p) {
|
||||||
|
return read32le(p) | (uint64_t)read32le(p + 4) << 32;
|
||||||
|
}
|
||||||
|
static inline void write64le(unsigned char *p, uint64_t x) {
|
||||||
|
write32le(p, x); write32le(p + 4, x >> 32);
|
||||||
|
}
|
||||||
|
static inline void add64le(unsigned char *p, int64_t x) {
|
||||||
|
write64le(p, read64le(p) + x);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------ i386-gen.c ------------ */
|
||||||
|
void g(int c);
|
||||||
|
void gen_le16(int c);
|
||||||
|
void gen_le32(int c);
|
||||||
|
|
||||||
|
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 ------------ */
|
||||||
|
void asm_instr(TCCState *s1);
|
||||||
|
void asm_global_instr(TCCState *s1);
|
||||||
|
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(TCCState *s1, int name, Sym *csym);
|
||||||
|
void asm_expr(TCCState *s1, ExprValue *pe);
|
||||||
|
int asm_int_expr(TCCState *s1);
|
||||||
|
|
||||||
|
/* ------------ i386-asm.c ------------ */
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* !TCC_CC_H */
|
|
@ -25,7 +25,9 @@
|
||||||
|
|
||||||
#define USING_GLOBALS
|
#define USING_GLOBALS
|
||||||
#include "tcc.h"
|
#include "tcc.h"
|
||||||
#include "token.h"
|
#define USING_GLOBALS
|
||||||
|
#include "cc/cc.h"
|
||||||
|
#include "cC/token.h"
|
||||||
|
|
||||||
#define MAX_OPERANDS 3
|
#define MAX_OPERANDS 3
|
||||||
|
|
||||||
|
@ -1268,7 +1270,7 @@ void subst_asm_operand(CString *add_str,
|
||||||
in the C symbol table when later looking up
|
in the C symbol table when later looking up
|
||||||
this name. So enter them now into the asm label
|
this name. So enter them now into the asm label
|
||||||
list when we still know the symbol. */
|
list when we still know the symbol. */
|
||||||
get_asm_sym(tok_alloc_const(name), sv->sym);
|
get_asm_sym(tcc_state, tok_alloc_const(name), sv->sym);
|
||||||
}
|
}
|
||||||
if (tcc_state->leading_underscore)
|
if (tcc_state->leading_underscore)
|
||||||
cstr_ccat(add_str, '_');
|
cstr_ccat(add_str, '_');
|
|
@ -20,7 +20,9 @@
|
||||||
|
|
||||||
#define USING_GLOBALS
|
#define USING_GLOBALS
|
||||||
#include <tcc.h>
|
#include <tcc.h>
|
||||||
#include "token.h"
|
#include "cc/token.h"
|
||||||
|
#define USING_GLOBALS
|
||||||
|
#include "cc/cc.h"
|
||||||
|
|
||||||
const char * const target_machine_defs =
|
const char * const target_machine_defs =
|
||||||
"__i386__\0"
|
"__i386__\0"
|
|
@ -1,4 +1,5 @@
|
||||||
#include <tcc.h>
|
#include <tcc.h>
|
||||||
|
#include "cc/cc.h"
|
||||||
|
|
||||||
#ifdef NEED_RELOC_TYPE
|
#ifdef NEED_RELOC_TYPE
|
||||||
/* Returns 1 for a code relocation, 0 for a data relocation. For unknown
|
/* Returns 1 for a code relocation, 0 for a data relocation. For unknown
|
||||||
|
@ -9,10 +10,6 @@ int code_reloc (int reloc_type)
|
||||||
case R_386_RELATIVE:
|
case R_386_RELATIVE:
|
||||||
case R_386_16:
|
case R_386_16:
|
||||||
case R_386_32:
|
case R_386_32:
|
||||||
case R_386_GOTPC:
|
|
||||||
case R_386_GOTOFF:
|
|
||||||
case R_386_GOT32:
|
|
||||||
case R_386_GOT32X:
|
|
||||||
case R_386_GLOB_DAT:
|
case R_386_GLOB_DAT:
|
||||||
case R_386_COPY:
|
case R_386_COPY:
|
||||||
case R_386_TLS_GD:
|
case R_386_TLS_GD:
|
||||||
|
@ -23,126 +20,12 @@ int code_reloc (int reloc_type)
|
||||||
|
|
||||||
case R_386_PC16:
|
case R_386_PC16:
|
||||||
case R_386_PC32:
|
case R_386_PC32:
|
||||||
case R_386_PLT32:
|
|
||||||
case R_386_JMP_SLOT:
|
case R_386_JMP_SLOT:
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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. */
|
|
||||||
int gotplt_entry_type (int reloc_type)
|
|
||||||
{
|
|
||||||
switch (reloc_type) {
|
|
||||||
case R_386_RELATIVE:
|
|
||||||
case R_386_16:
|
|
||||||
case R_386_GLOB_DAT:
|
|
||||||
case R_386_JMP_SLOT:
|
|
||||||
case R_386_COPY:
|
|
||||||
return NO_GOTPLT_ENTRY;
|
|
||||||
|
|
||||||
case R_386_32:
|
|
||||||
/* This relocations shouldn't normally need GOT or PLT
|
|
||||||
slots if it weren't for simplicity in the code generator.
|
|
||||||
See our caller for comments. */
|
|
||||||
return AUTO_GOTPLT_ENTRY;
|
|
||||||
|
|
||||||
case R_386_PC16:
|
|
||||||
case R_386_PC32:
|
|
||||||
return AUTO_GOTPLT_ENTRY;
|
|
||||||
|
|
||||||
case R_386_GOTPC:
|
|
||||||
case R_386_GOTOFF:
|
|
||||||
return BUILD_GOT_ONLY;
|
|
||||||
|
|
||||||
case R_386_GOT32:
|
|
||||||
case R_386_GOT32X:
|
|
||||||
case R_386_PLT32:
|
|
||||||
case R_386_TLS_GD:
|
|
||||||
case R_386_TLS_LDM:
|
|
||||||
case R_386_TLS_LDO_32:
|
|
||||||
case R_386_TLS_LE:
|
|
||||||
return ALWAYS_GOTPLT_ENTRY;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef NEED_BUILD_GOT
|
|
||||||
unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr)
|
|
||||||
{
|
|
||||||
Section *plt = s1->plt;
|
|
||||||
uint8_t *p;
|
|
||||||
int modrm;
|
|
||||||
unsigned plt_offset, relofs;
|
|
||||||
|
|
||||||
modrm = 0x25;
|
|
||||||
|
|
||||||
/* empty PLT: create PLT0 entry that pushes the library identifier
|
|
||||||
(GOT + PTR_SIZE) and jumps to ld.so resolution routine
|
|
||||||
(GOT + 2 * PTR_SIZE) */
|
|
||||||
if (plt->data_offset == 0) {
|
|
||||||
p = section_ptr_add(plt, 16);
|
|
||||||
p[0] = 0xff; /* pushl got + PTR_SIZE */
|
|
||||||
p[1] = modrm + 0x10;
|
|
||||||
write32le(p + 2, PTR_SIZE);
|
|
||||||
p[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
|
|
||||||
p[7] = modrm;
|
|
||||||
write32le(p + 8, PTR_SIZE * 2);
|
|
||||||
}
|
|
||||||
plt_offset = plt->data_offset;
|
|
||||||
|
|
||||||
/* The PLT slot refers to the relocation entry it needs via offset.
|
|
||||||
The reloc entry is created below, so its offset is the current
|
|
||||||
data_offset */
|
|
||||||
relofs = s1->plt->reloc ? s1->plt->reloc->data_offset : 0;
|
|
||||||
|
|
||||||
/* Jump to GOT entry where ld.so initially put the address of ip + 4 */
|
|
||||||
p = section_ptr_add(plt, 16);
|
|
||||||
p[0] = 0xff; /* jmp *(got + x) */
|
|
||||||
p[1] = modrm;
|
|
||||||
write32le(p + 2, got_offset);
|
|
||||||
p[6] = 0x68; /* push $xxx */
|
|
||||||
write32le(p + 7, relofs - sizeof (ElfW_Rel));
|
|
||||||
p[11] = 0xe9; /* jmp plt_start */
|
|
||||||
write32le(p + 12, -(plt->data_offset));
|
|
||||||
return plt_offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* relocate the PLT: compute addresses and offsets in the PLT now that final
|
|
||||||
address for PLT and GOT are known (see fill_program_header) */
|
|
||||||
void relocate_plt(TCCState *s1)
|
|
||||||
{
|
|
||||||
uint8_t *p, *p_end;
|
|
||||||
|
|
||||||
if (!s1->plt)
|
|
||||||
return;
|
|
||||||
|
|
||||||
p = s1->plt->data;
|
|
||||||
p_end = p + s1->plt->data_offset;
|
|
||||||
|
|
||||||
if (p < p_end) {
|
|
||||||
add32le(p + 2, s1->got->sh_addr);
|
|
||||||
add32le(p + 8, s1->got->sh_addr);
|
|
||||||
p += 16;
|
|
||||||
while (p < p_end) {
|
|
||||||
add32le(p + 2, s1->got->sh_addr);
|
|
||||||
p += 16;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s1->plt->reloc) {
|
|
||||||
ElfW_Rel *rel;
|
|
||||||
int x = s1->plt->sh_addr + 16 + 6;
|
|
||||||
p = s1->got->data;
|
|
||||||
for_each_elem(s1->plt->reloc, 0, rel, ElfW_Rel) {
|
|
||||||
write32le(p + rel->r_offset, x);
|
|
||||||
x += 16;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
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)
|
||||||
|
@ -158,24 +41,10 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
||||||
case R_386_PC32:
|
case R_386_PC32:
|
||||||
add32le(ptr, val - addr);
|
add32le(ptr, val - addr);
|
||||||
return;
|
return;
|
||||||
case R_386_PLT32:
|
|
||||||
add32le(ptr, val - addr);
|
|
||||||
return;
|
|
||||||
case R_386_GLOB_DAT:
|
case R_386_GLOB_DAT:
|
||||||
case R_386_JMP_SLOT:
|
case R_386_JMP_SLOT:
|
||||||
write32le(ptr, val);
|
write32le(ptr, val);
|
||||||
return;
|
return;
|
||||||
case R_386_GOTPC:
|
|
||||||
add32le(ptr, s1->got->sh_addr - addr);
|
|
||||||
return;
|
|
||||||
case R_386_GOTOFF:
|
|
||||||
add32le(ptr, val - s1->got->sh_addr);
|
|
||||||
return;
|
|
||||||
case R_386_GOT32:
|
|
||||||
case R_386_GOT32X:
|
|
||||||
/* we load the got offset */
|
|
||||||
add32le(ptr, get_sym_attr(s1, sym_index, 0)->got_offset);
|
|
||||||
return;
|
|
||||||
case R_386_16:
|
case R_386_16:
|
||||||
if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY) {
|
if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY) {
|
||||||
output_file:
|
output_file:
|
||||||
|
@ -220,7 +89,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
||||||
|
|
||||||
memcpy(ptr-3, replace, sizeof(replace));
|
memcpy(ptr-3, replace, sizeof(replace));
|
||||||
rel[1].r_info = ELFW(R_INFO)(0, R_386_NONE);
|
rel[1].r_info = ELFW(R_INFO)(0, R_386_NONE);
|
||||||
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
sym = &((ElfW(Sym) *)s1->symtab_section->data)[sym_index];
|
||||||
sec = s1->sections[sym->st_shndx];
|
sec = s1->sections[sym->st_shndx];
|
||||||
x = sym->st_value - sec->sh_addr - sec->data_offset;
|
x = sym->st_value - sec->sh_addr - sec->data_offset;
|
||||||
add32le(ptr + 5, -x);
|
add32le(ptr + 5, -x);
|
||||||
|
@ -259,7 +128,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
||||||
Section *sec;
|
Section *sec;
|
||||||
int32_t x;
|
int32_t x;
|
||||||
|
|
||||||
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
sym = &((ElfW(Sym) *)s1->symtab_section->data)[sym_index];
|
||||||
sec = s1->sections[sym->st_shndx];
|
sec = s1->sections[sym->st_shndx];
|
||||||
x = val - sec->sh_addr - sec->data_offset;
|
x = val - sec->sh_addr - sec->data_offset;
|
||||||
add32le(ptr, x);
|
add32le(ptr, x);
|
|
@ -17,16 +17,23 @@
|
||||||
* License along with this library; if not, write to the Free Software
|
* License along with this library; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
#include "libtcc.h"
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
# include "config.h"
|
# include "config.h"
|
||||||
#endif /* HAVE_CONFIG_H */
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#define USING_GLOBALS
|
|
||||||
#include "tcc.h"
|
#include "tcc.h"
|
||||||
#include "utils/string.h"
|
#include "utils/string.h"
|
||||||
#include "token.h"
|
#include "token.h"
|
||||||
|
#include "cc/cc.h"
|
||||||
|
|
||||||
|
#undef tcc_error
|
||||||
|
#undef _tcc_error
|
||||||
|
#define tcc_error _tcc_error
|
||||||
|
#undef tcc_warning
|
||||||
|
#define tcc_warning _tcc_warning
|
||||||
|
|
||||||
static Section *last_text_section; /* to handle .previous asm directive */
|
static Section *last_text_section; /* to handle .previous asm directive */
|
||||||
static int asmgoto_n;
|
static int asmgoto_n;
|
||||||
|
@ -53,11 +60,11 @@ static Sym* asm_new_label1(TCCState *s1, int label, int is_local, int sh_num, in
|
||||||
the global C symbol table to track ASM names as well, so we need to
|
the global C symbol table to track ASM names as well, so we need to
|
||||||
transform those into ones that don't conflict with a C name,
|
transform those into ones that don't conflict with a C name,
|
||||||
so prepend a '.' for them, but force the ELF asm name to be set. */
|
so prepend a '.' for them, but force the ELF asm name to be set. */
|
||||||
static int asm2cname(int v, int *addeddot)
|
static int asm2cname(TCCState *s1, int v, int *addeddot)
|
||||||
{
|
{
|
||||||
const char *name;
|
const char *name;
|
||||||
*addeddot = 0;
|
*addeddot = 0;
|
||||||
if (!tcc_state->leading_underscore)
|
if (!s1->leading_underscore)
|
||||||
return v;
|
return v;
|
||||||
name = get_tok_str(v, NULL);
|
name = get_tok_str(v, NULL);
|
||||||
if (!name)
|
if (!name)
|
||||||
|
@ -73,20 +80,20 @@ static int asm2cname(int v, int *addeddot)
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Sym *asm_label_find(int v)
|
static Sym *asm_label_find(TCCState *s1, int v)
|
||||||
{
|
{
|
||||||
Sym *sym;
|
Sym *sym;
|
||||||
int addeddot;
|
int addeddot;
|
||||||
v = asm2cname(v, &addeddot);
|
v = asm2cname(s1, v, &addeddot);
|
||||||
sym = sym_find(v);
|
sym = sym_find(v);
|
||||||
while (sym && sym->sym_scope && !(sym->type.t & VT_STATIC))
|
while (sym && sym->sym_scope && !(sym->type.t & VT_STATIC))
|
||||||
sym = sym->prev_tok;
|
sym = sym->prev_tok;
|
||||||
return sym;
|
return sym;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Sym *asm_label_push(int v)
|
static Sym *asm_label_push(TCCState *s1, int v)
|
||||||
{
|
{
|
||||||
int addeddot, v2 = asm2cname(v, &addeddot);
|
int addeddot, v2 = asm2cname(s1, v, &addeddot);
|
||||||
/* We always add VT_EXTERN, for sym definition that's tentative
|
/* We always add VT_EXTERN, for sym definition that's tentative
|
||||||
(for .set, removed for real defs), for mere references it's correct
|
(for .set, removed for real defs), for mere references it's correct
|
||||||
as is. */
|
as is. */
|
||||||
|
@ -106,11 +113,11 @@ static Sym *asm_label_push(int v)
|
||||||
are anonymous in C, in this case CSYM can be used to transfer
|
are anonymous in C, in this case CSYM can be used to transfer
|
||||||
all information from that symbol to the (possibly newly created)
|
all information from that symbol to the (possibly newly created)
|
||||||
asm symbol. */
|
asm symbol. */
|
||||||
Sym* get_asm_sym(int name, Sym *csym)
|
Sym* get_asm_sym(TCCState *s1, int name, Sym *csym)
|
||||||
{
|
{
|
||||||
Sym *sym = asm_label_find(name);
|
Sym *sym = asm_label_find(s1, name);
|
||||||
if (!sym) {
|
if (!sym) {
|
||||||
sym = asm_label_push(name);
|
sym = asm_label_push(s1, name);
|
||||||
if (csym)
|
if (csym)
|
||||||
sym->c = csym->c;
|
sym->c = csym->c;
|
||||||
}
|
}
|
||||||
|
@ -122,7 +129,7 @@ static Sym* asm_section_sym(TCCState *s1, Section *sec)
|
||||||
char buf[100]; int label; Sym *sym;
|
char buf[100]; int label; Sym *sym;
|
||||||
snprintf(buf, sizeof buf, "L.%s", sec->old_name);
|
snprintf(buf, sizeof buf, "L.%s", sec->old_name);
|
||||||
label = tok_alloc_const(buf);
|
label = tok_alloc_const(buf);
|
||||||
sym = asm_label_find(label);
|
sym = asm_label_find(s1, label);
|
||||||
return sym ? sym : asm_new_label1(s1, label, 1, sec->sh_num, 0);
|
return sym ? sym : asm_new_label1(s1, label, 1, sec->sh_num, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,7 +150,7 @@ static void asm_expr_unary(TCCState *s1, ExprValue *pe)
|
||||||
if (*p == 'b' || *p == 'f') {
|
if (*p == 'b' || *p == 'f') {
|
||||||
/* backward or forward label */
|
/* backward or forward label */
|
||||||
label = asm_get_local_label_name(s1, n);
|
label = asm_get_local_label_name(s1, n);
|
||||||
sym = asm_label_find(label);
|
sym = asm_label_find(s1, label);
|
||||||
if (*p == 'b') {
|
if (*p == 'b') {
|
||||||
/* backward : find the last corresponding defined label */
|
/* backward : find the last corresponding defined label */
|
||||||
if (sym && (!sym->c || elfsym(sym)->st_shndx == SHN_UNDEF))
|
if (sym && (!sym->c || elfsym(sym)->st_shndx == SHN_UNDEF))
|
||||||
|
@ -154,7 +161,7 @@ static void asm_expr_unary(TCCState *s1, ExprValue *pe)
|
||||||
/* forward */
|
/* forward */
|
||||||
if (!sym || (sym->c && elfsym(sym)->st_shndx != SHN_UNDEF)) {
|
if (!sym || (sym->c && elfsym(sym)->st_shndx != SHN_UNDEF)) {
|
||||||
/* if the last label is defined, then define a new one */
|
/* if the last label is defined, then define a new one */
|
||||||
sym = asm_label_push(label);
|
sym = asm_label_push(s1, label);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pe->v = 0;
|
pe->v = 0;
|
||||||
|
@ -199,7 +206,7 @@ static void asm_expr_unary(TCCState *s1, ExprValue *pe)
|
||||||
break;
|
break;
|
||||||
case '.':
|
case '.':
|
||||||
pe->v = ind;
|
pe->v = ind;
|
||||||
pe->sym = asm_section_sym(s1, tcc_state->cur_text_section);
|
pe->sym = asm_section_sym(s1, s1->cur_text_section);
|
||||||
pe->pcrel = 0;
|
pe->pcrel = 0;
|
||||||
next();
|
next();
|
||||||
break;
|
break;
|
||||||
|
@ -207,7 +214,7 @@ static void asm_expr_unary(TCCState *s1, ExprValue *pe)
|
||||||
if (tok >= TOK_IDENT) {
|
if (tok >= TOK_IDENT) {
|
||||||
ElfSym *esym;
|
ElfSym *esym;
|
||||||
/* label case : if the label was not found, add one */
|
/* label case : if the label was not found, add one */
|
||||||
sym = get_asm_sym(tok, NULL);
|
sym = get_asm_sym(s1, tok, NULL);
|
||||||
esym = elfsym(sym);
|
esym = elfsym(sym);
|
||||||
if (esym && esym->st_shndx == SHN_ABS) {
|
if (esym && esym->st_shndx == SHN_ABS) {
|
||||||
/* if absolute symbol, no need to put a symbol value */
|
/* if absolute symbol, no need to put a symbol value */
|
||||||
|
@ -336,7 +343,7 @@ static inline void asm_expr_sum(TCCState *s1, ExprValue *pe)
|
||||||
/* we also accept defined symbols in the same section */
|
/* we also accept defined symbols in the same section */
|
||||||
pe->v += esym1->st_value - esym2->st_value;
|
pe->v += esym1->st_value - esym2->st_value;
|
||||||
pe->sym = NULL;
|
pe->sym = NULL;
|
||||||
} else if (esym2->st_shndx == tcc_state->cur_text_section->sh_num) {
|
} else if (esym2->st_shndx == s1->cur_text_section->sh_num) {
|
||||||
/* When subtracting a defined symbol in current section
|
/* When subtracting a defined symbol in current section
|
||||||
this actually makes the value PC-relative. */
|
this actually makes the value PC-relative. */
|
||||||
pe->v += 0 - esym2->st_value;
|
pe->v += 0 - esym2->st_value;
|
||||||
|
@ -413,7 +420,7 @@ static Sym* asm_new_label1(TCCState *s1, int label, int is_local,
|
||||||
Sym *sym;
|
Sym *sym;
|
||||||
ElfSym *esym;
|
ElfSym *esym;
|
||||||
|
|
||||||
sym = asm_label_find(label);
|
sym = asm_label_find(s1, label);
|
||||||
if (sym) {
|
if (sym) {
|
||||||
esym = elfsym(sym);
|
esym = elfsym(sym);
|
||||||
/* A VT_EXTERN symbol, even if it has a section is considered
|
/* A VT_EXTERN symbol, even if it has a section is considered
|
||||||
|
@ -430,7 +437,7 @@ static Sym* asm_new_label1(TCCState *s1, int label, int is_local,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
new_label:
|
new_label:
|
||||||
sym = asm_label_push(label);
|
sym = asm_label_push(s1, label);
|
||||||
}
|
}
|
||||||
if (!sym->c)
|
if (!sym->c)
|
||||||
put_extern_sym2(sym, SHN_UNDEF, 0, 0, 1);
|
put_extern_sym2(sym, SHN_UNDEF, 0, 0, 1);
|
||||||
|
@ -444,7 +451,7 @@ static Sym* asm_new_label1(TCCState *s1, int label, int is_local,
|
||||||
|
|
||||||
static Sym* asm_new_label(TCCState *s1, int label, int is_local)
|
static Sym* asm_new_label(TCCState *s1, int label, int is_local)
|
||||||
{
|
{
|
||||||
return asm_new_label1(s1, label, is_local, tcc_state->cur_text_section->sh_num, ind);
|
return asm_new_label1(s1, label, is_local, s1->cur_text_section->sh_num, ind);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the value of LABEL to that of some expression (possibly
|
/* Set the value of LABEL to that of some expression (possibly
|
||||||
|
@ -468,9 +475,9 @@ static Sym* set_symbol(TCCState *s1, int label)
|
||||||
|
|
||||||
static void use_section1(TCCState *s1, Section *sec)
|
static void use_section1(TCCState *s1, Section *sec)
|
||||||
{
|
{
|
||||||
tcc_state->cur_text_section->data_offset = ind;
|
s1->cur_text_section->data_offset = ind;
|
||||||
tcc_state->cur_text_section = sec;
|
s1->cur_text_section = sec;
|
||||||
ind = tcc_state->cur_text_section->data_offset;
|
ind = s1->cur_text_section->data_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void use_section(TCCState *s1, const char *name)
|
static void use_section(TCCState *s1, const char *name)
|
||||||
|
@ -483,16 +490,16 @@ static void use_section(TCCState *s1, const char *name)
|
||||||
static void push_section(TCCState *s1, const char *name)
|
static void push_section(TCCState *s1, const char *name)
|
||||||
{
|
{
|
||||||
Section *sec = find_section(s1, name);
|
Section *sec = find_section(s1, name);
|
||||||
sec->prev = tcc_state->cur_text_section;
|
sec->prev = s1->cur_text_section;
|
||||||
use_section1(s1, sec);
|
use_section1(s1, sec);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pop_section(TCCState *s1)
|
static void pop_section(TCCState *s1)
|
||||||
{
|
{
|
||||||
Section *prev = tcc_state->cur_text_section->prev;
|
Section *prev = s1->cur_text_section->prev;
|
||||||
if (!prev)
|
if (!prev)
|
||||||
tcc_error(".popsection without .pushsection");
|
tcc_error(".popsection without .pushsection");
|
||||||
tcc_state->cur_text_section->prev = NULL;
|
s1->cur_text_section->prev = NULL;
|
||||||
use_section1(s1, prev);
|
use_section1(s1, prev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -503,7 +510,7 @@ static void asm_parse_directive(TCCState *s1, int global)
|
||||||
uint8_t *ptr;
|
uint8_t *ptr;
|
||||||
|
|
||||||
/* assembler directive */
|
/* assembler directive */
|
||||||
sec = tcc_state->cur_text_section;
|
sec = s1->cur_text_section;
|
||||||
switch(tok) {
|
switch(tok) {
|
||||||
case TOK_ASMDIR_align:
|
case TOK_ASMDIR_align:
|
||||||
case TOK_ASMDIR_balign:
|
case TOK_ASMDIR_balign:
|
||||||
|
@ -682,7 +689,7 @@ static void asm_parse_directive(TCCState *s1, int global)
|
||||||
n = e.v;
|
n = e.v;
|
||||||
esym = elfsym(e.sym);
|
esym = elfsym(e.sym);
|
||||||
if (esym) {
|
if (esym) {
|
||||||
if (esym->st_shndx != tcc_state->cur_text_section->sh_num)
|
if (esym->st_shndx != s1->cur_text_section->sh_num)
|
||||||
expect("constant or same-section symbol");
|
expect("constant or same-section symbol");
|
||||||
n += esym->st_value;
|
n += esym->st_value;
|
||||||
}
|
}
|
||||||
|
@ -710,7 +717,7 @@ static void asm_parse_directive(TCCState *s1, int global)
|
||||||
do {
|
do {
|
||||||
Sym *sym;
|
Sym *sym;
|
||||||
next();
|
next();
|
||||||
sym = get_asm_sym(tok, NULL);
|
sym = get_asm_sym(s1, tok, NULL);
|
||||||
if (tok1 != TOK_ASMDIR_hidden)
|
if (tok1 != TOK_ASMDIR_hidden)
|
||||||
sym->type.t &= ~VT_STATIC;
|
sym->type.t &= ~VT_STATIC;
|
||||||
if (tok1 == TOK_ASMDIR_weak)
|
if (tok1 == TOK_ASMDIR_weak)
|
||||||
|
@ -806,7 +813,7 @@ static void asm_parse_directive(TCCState *s1, int global)
|
||||||
Sym *sym;
|
Sym *sym;
|
||||||
|
|
||||||
next();
|
next();
|
||||||
sym = asm_label_find(tok);
|
sym = asm_label_find(s1, tok);
|
||||||
if (!sym) {
|
if (!sym) {
|
||||||
tcc_error("label not found: %s", get_tok_str(tok, NULL));
|
tcc_error("label not found: %s", get_tok_str(tok, NULL));
|
||||||
}
|
}
|
||||||
|
@ -826,7 +833,7 @@ static void asm_parse_directive(TCCState *s1, int global)
|
||||||
int st_type;
|
int st_type;
|
||||||
|
|
||||||
next();
|
next();
|
||||||
sym = get_asm_sym(tok, NULL);
|
sym = get_asm_sym(s1, tok, NULL);
|
||||||
next();
|
next();
|
||||||
skip(',');
|
skip(',');
|
||||||
if (tok == TOK_STR) {
|
if (tok == TOK_STR) {
|
||||||
|
@ -894,7 +901,7 @@ static void asm_parse_directive(TCCState *s1, int global)
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
last_text_section = tcc_state->cur_text_section;
|
last_text_section = s1->cur_text_section;
|
||||||
if (tok1 == TOK_ASMDIR_section)
|
if (tok1 == TOK_ASMDIR_section)
|
||||||
use_section(s1, sname);
|
use_section(s1, sname);
|
||||||
else
|
else
|
||||||
|
@ -903,8 +910,8 @@ static void asm_parse_directive(TCCState *s1, int global)
|
||||||
1. new_section normally acts for GCC compatibility and
|
1. new_section normally acts for GCC compatibility and
|
||||||
sets alignment to PTR_SIZE. The assembler behaves different. */
|
sets alignment to PTR_SIZE. The assembler behaves different. */
|
||||||
if (old_nb_section != s1->nb_sections) {
|
if (old_nb_section != s1->nb_sections) {
|
||||||
tcc_state->cur_text_section->sh_addralign = 1;
|
s1->cur_text_section->sh_addralign = 1;
|
||||||
tcc_state->cur_text_section->sh_flags = flags;
|
s1->cur_text_section->sh_flags = flags;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -914,7 +921,7 @@ static void asm_parse_directive(TCCState *s1, int global)
|
||||||
next();
|
next();
|
||||||
if (!last_text_section)
|
if (!last_text_section)
|
||||||
tcc_error("no previous section referenced");
|
tcc_error("no previous section referenced");
|
||||||
sec = tcc_state->cur_text_section;
|
sec = s1->cur_text_section;
|
||||||
use_section1(s1, last_text_section);
|
use_section1(s1, last_text_section);
|
||||||
last_text_section = sec;
|
last_text_section = sec;
|
||||||
}
|
}
|
||||||
|
@ -926,13 +933,11 @@ static void asm_parse_directive(TCCState *s1, int global)
|
||||||
case TOK_ASMDIR_code16:
|
case TOK_ASMDIR_code16:
|
||||||
{
|
{
|
||||||
next();
|
next();
|
||||||
s1->seg_size = 16;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TOK_ASMDIR_code32:
|
case TOK_ASMDIR_code32:
|
||||||
{
|
{
|
||||||
next();
|
next();
|
||||||
s1->seg_size = 32;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
/* TODO: Implement symvar support. FreeBSD >= 14 needs this */
|
/* TODO: Implement symvar support. FreeBSD >= 14 needs this */
|
||||||
|
@ -1015,11 +1020,11 @@ int tcc_assemble(TCCState *s1, int do_preprocess)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
/* default section is text */
|
/* default section is text */
|
||||||
tcc_state->cur_text_section = tcc_state->text_section;
|
s1->cur_text_section = s1->text_section;
|
||||||
ind = tcc_state->cur_text_section->data_offset;
|
ind = s1->cur_text_section->data_offset;
|
||||||
nocode_wanted = 0;
|
nocode_wanted = 0;
|
||||||
ret = tcc_assemble_internal(s1, do_preprocess, 1);
|
ret = tcc_assemble_internal(s1, do_preprocess, 1);
|
||||||
tcc_state->cur_text_section->data_offset = ind;
|
s1->cur_text_section->data_offset = ind;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1187,7 +1192,7 @@ static void parse_asm_operands(ASMOperand *operands, int *nb_operands_ptr,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* parse the GCC asm() instruction */
|
/* parse the GCC asm() instruction */
|
||||||
void asm_instr(void)
|
void asm_instr(TCCState *s1)
|
||||||
{
|
{
|
||||||
CString astr, *astr1;
|
CString astr, *astr1;
|
||||||
|
|
||||||
|
@ -1262,11 +1267,11 @@ void asm_instr(void)
|
||||||
csym->r = LABEL_FORWARD;
|
csym->r = LABEL_FORWARD;
|
||||||
}
|
}
|
||||||
next();
|
next();
|
||||||
asmname = asm_get_prefix_name(tcc_state, "LG.",
|
asmname = asm_get_prefix_name(s1, "LG.",
|
||||||
++asmgoto_n);
|
++asmgoto_n);
|
||||||
if (!csym->c)
|
if (!csym->c)
|
||||||
put_extern_sym2(csym, SHN_UNDEF, 0, 0, 1);
|
put_extern_sym2(csym, SHN_UNDEF, 0, 0, 1);
|
||||||
get_asm_sym(asmname, csym);
|
get_asm_sym(s1, asmname, csym);
|
||||||
operands[nb_operands + nb_labels - 1].is_label = asmname;
|
operands[nb_operands + nb_labels - 1].is_label = asmname;
|
||||||
|
|
||||||
if (tok != ',')
|
if (tok != ',')
|
||||||
|
@ -1312,13 +1317,13 @@ void asm_instr(void)
|
||||||
|
|
||||||
/* We don't allow switching section within inline asm to
|
/* We don't allow switching section within inline asm to
|
||||||
bleed out to surrounding code. */
|
bleed out to surrounding code. */
|
||||||
sec = tcc_state->cur_text_section;
|
sec = s1->cur_text_section;
|
||||||
/* assemble the string with tcc internal assembler */
|
/* assemble the string with tcc internal assembler */
|
||||||
tcc_assemble_inline(tcc_state, astr.data, astr.size - 1, 0);
|
tcc_assemble_inline(s1, astr.data, astr.size - 1, 0);
|
||||||
cstr_free_s(&astr);
|
cstr_free_s(&astr);
|
||||||
if (sec != tcc_state->cur_text_section) {
|
if (sec != s1->cur_text_section) {
|
||||||
tcc_warning("inline asm tries to change current section");
|
tcc_warning("inline asm tries to change current section");
|
||||||
use_section1(tcc_state, sec);
|
use_section1(s1, sec);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* restore the current C token */
|
/* restore the current C token */
|
||||||
|
@ -1335,7 +1340,7 @@ void asm_instr(void)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void asm_global_instr(void)
|
void asm_global_instr(TCCState *s1)
|
||||||
{
|
{
|
||||||
CString *astr;
|
CString *astr;
|
||||||
int saved_nocode_wanted = nocode_wanted;
|
int saved_nocode_wanted = nocode_wanted;
|
||||||
|
@ -1353,13 +1358,13 @@ void asm_global_instr(void)
|
||||||
#ifdef ASM_DEBUG
|
#ifdef ASM_DEBUG
|
||||||
printf("asm_global: \"%s\"\n", (char *)astr->data);
|
printf("asm_global: \"%s\"\n", (char *)astr->data);
|
||||||
#endif
|
#endif
|
||||||
tcc_state->cur_text_section = tcc_state->text_section;
|
s1->cur_text_section = s1->text_section;
|
||||||
ind = tcc_state->cur_text_section->data_offset;
|
ind = s1->cur_text_section->data_offset;
|
||||||
|
|
||||||
/* assemble the string with tcc internal assembler */
|
/* assemble the string with tcc internal assembler */
|
||||||
tcc_assemble_inline(tcc_state, astr->data, astr->size - 1, 1);
|
tcc_assemble_inline(s1, astr->data, astr->size - 1, 1);
|
||||||
|
|
||||||
tcc_state->cur_text_section->data_offset = ind;
|
s1->cur_text_section->data_offset = ind;
|
||||||
|
|
||||||
/* restore the current C token */
|
/* restore the current C token */
|
||||||
next();
|
next();
|
|
@ -26,6 +26,8 @@
|
||||||
|
|
||||||
#define USING_GLOBALS
|
#define USING_GLOBALS
|
||||||
#include <tcc.h>
|
#include <tcc.h>
|
||||||
|
#define USING_GLOBALS
|
||||||
|
#include "cc/cc.h"
|
||||||
#include <tcc/memory.h>
|
#include <tcc/memory.h>
|
||||||
#include "utils/string.h"
|
#include "utils/string.h"
|
||||||
#include "token.h"
|
#include "token.h"
|
||||||
|
@ -408,7 +410,7 @@ ElfSym *elfsym(Sym *s)
|
||||||
{
|
{
|
||||||
if (!s || !s->c)
|
if (!s || !s->c)
|
||||||
return NULL;
|
return NULL;
|
||||||
return &((ElfSym *)symtab_section->data)[s->c];
|
return &((ElfSym *)tcc_state->symtab_section->data)[s->c];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* apply storage attributes to Elf symbol */
|
/* apply storage attributes to Elf symbol */
|
||||||
|
@ -435,23 +437,6 @@ void update_storage(Sym *sym)
|
||||||
if (sym_bind != old_sym_bind) {
|
if (sym_bind != old_sym_bind) {
|
||||||
esym->st_info = ELFW(ST_INFO)(sym_bind, ELFW(ST_TYPE)(esym->st_info));
|
esym->st_info = ELFW(ST_INFO)(sym_bind, ELFW(ST_TYPE)(esym->st_info));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TCC_TARGET_PE
|
|
||||||
if (sym->a.dllimport)
|
|
||||||
esym->st_other |= ST_PE_IMPORT;
|
|
||||||
if (sym->a.dllexport)
|
|
||||||
esym->st_other |= ST_PE_EXPORT;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
printf("storage %s: bind=%c vis=%d exp=%d imp=%d\n",
|
|
||||||
get_tok_str(sym->v, NULL),
|
|
||||||
sym_bind == STB_WEAK ? 'w' : sym_bind == STB_LOCAL ? 'l' : 'g',
|
|
||||||
sym->a.visibility,
|
|
||||||
sym->a.dllexport,
|
|
||||||
sym->a.dllimport
|
|
||||||
);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
|
@ -512,7 +497,7 @@ void put_extern_sym2(Sym *sym, int sh_num,
|
||||||
}
|
}
|
||||||
|
|
||||||
info = ELFW(ST_INFO)(sym_bind, sym_type);
|
info = ELFW(ST_INFO)(sym_bind, sym_type);
|
||||||
sym->c = put_elf_sym(symtab_section, value, size, info, other, sh_num, name);
|
sym->c = put_elf_sym(tcc_state->symtab_section, value, size, info, other, sh_num, name);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
esym = elfsym(sym);
|
esym = elfsym(sym);
|
||||||
|
@ -546,7 +531,7 @@ void greloca(Section *s, Sym *sym, unsigned long offset, int type,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* now we can add ELF relocation info */
|
/* now we can add ELF relocation info */
|
||||||
put_elf_reloca(symtab_section, s, offset, type, c, addend);
|
put_elf_reloca(tcc_state->symtab_section, s, offset, type, c, addend);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if PTR_SIZE == 4
|
#if PTR_SIZE == 4
|
||||||
|
@ -5186,7 +5171,7 @@ void unary(void)
|
||||||
t = (LONG_SIZE == 8 ? VT_LLONG : VT_INT) | VT_LONG | VT_UNSIGNED;
|
t = (LONG_SIZE == 8 ? VT_LLONG : VT_INT) | VT_LONG | VT_UNSIGNED;
|
||||||
goto push_tokc;
|
goto push_tokc;
|
||||||
case TOK___FUNCTION__:
|
case TOK___FUNCTION__:
|
||||||
if (!gnu_ext)
|
if (!tcc_state->gnu_ext)
|
||||||
goto tok_identifier;
|
goto tok_identifier;
|
||||||
/* fall thru */
|
/* fall thru */
|
||||||
case TOK___FUNC__:
|
case TOK___FUNC__:
|
||||||
|
@ -5462,7 +5447,7 @@ void unary(void)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TOK_LAND:
|
case TOK_LAND:
|
||||||
if (!gnu_ext)
|
if (!tcc_state->gnu_ext)
|
||||||
goto tok_identifier;
|
goto tok_identifier;
|
||||||
next();
|
next();
|
||||||
/* allow to take the address of a label */
|
/* allow to take the address of a label */
|
||||||
|
@ -5598,13 +5583,6 @@ special_math_val:
|
||||||
|
|
||||||
if (r & VT_SYM) {
|
if (r & VT_SYM) {
|
||||||
vtop->c.i = 0;
|
vtop->c.i = 0;
|
||||||
#ifdef TCC_TARGET_PE
|
|
||||||
if (s->a.dllimport) {
|
|
||||||
mk_pointer(&vtop->type);
|
|
||||||
vtop->r |= VT_LVAL;
|
|
||||||
indir();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
} else if (r == VT_CONST && IS_ENUM_VAL(s->type.t)) {
|
} else if (r == VT_CONST && IS_ENUM_VAL(s->type.t)) {
|
||||||
vtop->c.i = s->enum_val;
|
vtop->c.i = s->enum_val;
|
||||||
}
|
}
|
||||||
|
@ -6035,7 +6013,7 @@ static void expr_cond(void)
|
||||||
if (tok == '?') {
|
if (tok == '?') {
|
||||||
next();
|
next();
|
||||||
c = condition_3way();
|
c = condition_3way();
|
||||||
g = (tok == ':' && gnu_ext);
|
g = (tok == ':' && tcc_state->gnu_ext);
|
||||||
tt = 0;
|
tt = 0;
|
||||||
if (!g) {
|
if (!g) {
|
||||||
if (c < 0) {
|
if (c < 0) {
|
||||||
|
@ -6776,7 +6754,7 @@ again:
|
||||||
dynarray_add(&cur_switch->p, &cur_switch->n, cr);
|
dynarray_add(&cur_switch->p, &cur_switch->n, cr);
|
||||||
t = cur_switch->sv.type.t;
|
t = cur_switch->sv.type.t;
|
||||||
cr->v1 = cr->v2 = value64(expr_const64(), t);
|
cr->v1 = cr->v2 = value64(expr_const64(), t);
|
||||||
if (tok == TOK_DOTS && gnu_ext) {
|
if (tok == TOK_DOTS && tcc_state->gnu_ext) {
|
||||||
next();
|
next();
|
||||||
cr->v2 = value64(expr_const64(), t);
|
cr->v2 = value64(expr_const64(), t);
|
||||||
if (case_cmp(cr->v2, cr->v1) < 0)
|
if (case_cmp(cr->v2, cr->v1) < 0)
|
||||||
|
@ -6800,7 +6778,7 @@ again:
|
||||||
|
|
||||||
} else if (t == TOK_GOTO) {
|
} else if (t == TOK_GOTO) {
|
||||||
vla_restore(cur_scope->vla.locorig);
|
vla_restore(cur_scope->vla.locorig);
|
||||||
if (tok == '*' && gnu_ext) {
|
if (tok == '*' && tcc_state->gnu_ext) {
|
||||||
/* computed goto */
|
/* computed goto */
|
||||||
next();
|
next();
|
||||||
gexpr();
|
gexpr();
|
||||||
|
@ -6837,7 +6815,7 @@ again:
|
||||||
skip(';');
|
skip(';');
|
||||||
|
|
||||||
} else if (t == TOK_ASM1 || t == TOK_ASM2 || t == TOK_ASM3) {
|
} else if (t == TOK_ASM1 || t == TOK_ASM2 || t == TOK_ASM3) {
|
||||||
asm_instr();
|
asm_instr(tcc_state);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (tok == ':' && t >= TOK_UIDENT) {
|
if (tok == ':' && t >= TOK_UIDENT) {
|
||||||
|
@ -6954,11 +6932,7 @@ static void parse_init_elem(int expr_type)
|
||||||
(compound literals). */
|
(compound literals). */
|
||||||
if (((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST
|
if (((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST
|
||||||
&& ((vtop->r & (VT_SYM|VT_LVAL)) != (VT_SYM|VT_LVAL)
|
&& ((vtop->r & (VT_SYM|VT_LVAL)) != (VT_SYM|VT_LVAL)
|
||||||
|| vtop->sym->v < SYM_FIRST_ANOM))
|
|| vtop->sym->v < SYM_FIRST_ANOM)))
|
||||||
#ifdef TCC_TARGET_PE
|
|
||||||
|| ((vtop->r & VT_SYM) && vtop->sym->a.dllimport)
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
tcc_error("initializer element is not constant");
|
tcc_error("initializer element is not constant");
|
||||||
break;
|
break;
|
||||||
case EXPR_ANY:
|
case EXPR_ANY:
|
||||||
|
@ -7047,7 +7021,7 @@ static int decl_designator(init_params *p, CType *type, unsigned long c,
|
||||||
if (flags & DIF_HAVE_ELEM)
|
if (flags & DIF_HAVE_ELEM)
|
||||||
goto no_designator;
|
goto no_designator;
|
||||||
|
|
||||||
if (gnu_ext && tok >= TOK_UIDENT) {
|
if (tcc_state->gnu_ext && tok >= TOK_UIDENT) {
|
||||||
l = tok, next();
|
l = tok, next();
|
||||||
if (tok == ':')
|
if (tok == ':')
|
||||||
goto struct_field;
|
goto struct_field;
|
||||||
|
@ -7061,7 +7035,7 @@ static int decl_designator(init_params *p, CType *type, unsigned long c,
|
||||||
expect("array type");
|
expect("array type");
|
||||||
next();
|
next();
|
||||||
index = index_last = expr_const();
|
index = index_last = expr_const();
|
||||||
if (tok == TOK_DOTS && gnu_ext) {
|
if (tok == TOK_DOTS && tcc_state->gnu_ext) {
|
||||||
next();
|
next();
|
||||||
index_last = expr_const();
|
index_last = expr_const();
|
||||||
}
|
}
|
||||||
|
@ -7093,7 +7067,7 @@ static int decl_designator(init_params *p, CType *type, unsigned long c,
|
||||||
if (!cur_field) {
|
if (!cur_field) {
|
||||||
if (tok == '=') {
|
if (tok == '=') {
|
||||||
next();
|
next();
|
||||||
} else if (!gnu_ext) {
|
} else if (!tcc_state->gnu_ext) {
|
||||||
expect("=");
|
expect("=");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -7234,7 +7208,7 @@ static void init_putv(init_params *p, CType *type, unsigned long c)
|
||||||
continue;
|
continue;
|
||||||
if (rel->r_offset < esym->st_value)
|
if (rel->r_offset < esym->st_value)
|
||||||
break;
|
break;
|
||||||
put_elf_reloca(symtab_section, sec,
|
put_elf_reloca(tcc_state->symtab_section, sec,
|
||||||
c + rel->r_offset - esym->st_value,
|
c + rel->r_offset - esym->st_value,
|
||||||
ELFW(R_TYPE)(rel->r_info),
|
ELFW(R_TYPE)(rel->r_info),
|
||||||
ELFW(R_SYM)(rel->r_info),
|
ELFW(R_SYM)(rel->r_info),
|
||||||
|
@ -7728,17 +7702,11 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
|
||||||
sec = tcc_state->rodata_section;
|
sec = tcc_state->rodata_section;
|
||||||
} else if (has_init) {
|
} else if (has_init) {
|
||||||
sec = tcc_state->data_section;
|
sec = tcc_state->data_section;
|
||||||
} else if (tcc_state->nocommon)
|
} else {
|
||||||
sec = tcc_state->bss_section;
|
sec = tcc_state->bss_section;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
addr = section_add(sec, size, align);
|
||||||
if (sec) {
|
|
||||||
addr = section_add(sec, size, align);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
addr = align; /* SHN_COMMON is special, symbol value is align */
|
|
||||||
sec = common_section;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (v) {
|
if (v) {
|
||||||
if (!sym) {
|
if (!sym) {
|
||||||
|
@ -7997,7 +7965,7 @@ static int decl(int l)
|
||||||
break;
|
break;
|
||||||
if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
|
if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
|
||||||
/* global asm block */
|
/* global asm block */
|
||||||
asm_global_instr();
|
asm_global_instr(tcc_state);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (tok >= TOK_UIDENT) {
|
if (tok >= TOK_UIDENT) {
|
||||||
|
@ -8063,34 +8031,12 @@ static int decl(int l)
|
||||||
tcc_warning("type defaults to int");
|
tcc_warning("type defaults to int");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gnu_ext && (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3)) {
|
if (tcc_state->gnu_ext && (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3)) {
|
||||||
ad.asm_label = asm_label_instr();
|
ad.asm_label = asm_label_instr();
|
||||||
/* parse one last attribute list, after asm label */
|
/* parse one last attribute list, after asm label */
|
||||||
parse_attribute(&ad);
|
parse_attribute(&ad);
|
||||||
#if 0
|
|
||||||
/* gcc does not allow __asm__("label") with function definition,
|
|
||||||
but why not ... */
|
|
||||||
if (tok == '{')
|
|
||||||
expect(";");
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TCC_TARGET_PE
|
|
||||||
if (ad.a.dllimport || ad.a.dllexport) {
|
|
||||||
if (type.t & VT_STATIC)
|
|
||||||
tcc_error("cannot have dll linkage with static");
|
|
||||||
if (type.t & VT_TYPEDEF) {
|
|
||||||
tcc_warning("'%s' attribute ignored for typedef",
|
|
||||||
ad.a.dllimport ? (ad.a.dllimport = 0, "dllimport") :
|
|
||||||
(ad.a.dllexport = 0, "dllexport"));
|
|
||||||
} else if (ad.a.dllimport) {
|
|
||||||
if ((type.t & VT_BTYPE) == VT_FUNC)
|
|
||||||
ad.a.dllimport = 0;
|
|
||||||
else
|
|
||||||
type.t |= VT_EXTERN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (tok == '{') {
|
if (tok == '{') {
|
||||||
if (l != VT_CONST)
|
if (l != VT_CONST)
|
||||||
tcc_error("cannot use local functions");
|
tcc_error("cannot use local functions");
|
|
@ -23,9 +23,12 @@
|
||||||
#endif /* HAVE_CONFIG_H */
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
#define USING_GLOBALS
|
#define USING_GLOBALS
|
||||||
#include <tcc.h>
|
#include <tcc.h>
|
||||||
|
#define USING_GLOBALS
|
||||||
|
#include "cc/cc.h"
|
||||||
#include <tcc/path.h>
|
#include <tcc/path.h>
|
||||||
#include <tcc/memory.h>
|
#include <tcc/memory.h>
|
||||||
#include "utils/string.h"
|
#include "utils/string.h"
|
||||||
|
@ -1555,7 +1558,7 @@ void parse_define(void)
|
||||||
if (varg == TOK_DOTS) {
|
if (varg == TOK_DOTS) {
|
||||||
varg = TOK___VA_ARGS__;
|
varg = TOK___VA_ARGS__;
|
||||||
is_vaargs = 1;
|
is_vaargs = 1;
|
||||||
} else if (tok == TOK_DOTS && gnu_ext) {
|
} else if (tok == TOK_DOTS && tcc_state->gnu_ext) {
|
||||||
is_vaargs = 1;
|
is_vaargs = 1;
|
||||||
next_nomacro();
|
next_nomacro();
|
||||||
}
|
}
|
||||||
|
@ -2066,7 +2069,7 @@ static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long
|
||||||
c = '\v';
|
c = '\v';
|
||||||
break;
|
break;
|
||||||
case 'e':
|
case 'e':
|
||||||
if (!gnu_ext)
|
if (!tcc_state->gnu_ext)
|
||||||
goto invalid_escape;
|
goto invalid_escape;
|
||||||
c = 27;
|
c = 27;
|
||||||
break;
|
break;
|
||||||
|
@ -2357,7 +2360,7 @@ static void parse_number(const char *p)
|
||||||
/* XXX: should patch directly float number */
|
/* XXX: should patch directly float number */
|
||||||
d = (double)bn[1] * 4294967296.0 + (double)bn[0];
|
d = (double)bn[1] * 4294967296.0 + (double)bn[0];
|
||||||
d = ldexp(d, exp_val - frac_bits);
|
d = ldexp(d, exp_val - frac_bits);
|
||||||
t = toup(ch);
|
t = toupper(ch);
|
||||||
if (t == 'F') {
|
if (t == 'F') {
|
||||||
ch = *p++;
|
ch = *p++;
|
||||||
tok = TOK_CFLOAT;
|
tok = TOK_CFLOAT;
|
||||||
|
@ -2412,7 +2415,7 @@ static void parse_number(const char *p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*q = '\0';
|
*q = '\0';
|
||||||
t = toup(ch);
|
t = toupper(ch);
|
||||||
errno = 0;
|
errno = 0;
|
||||||
if (t == 'F') {
|
if (t == 'F') {
|
||||||
ch = *p++;
|
ch = *p++;
|
||||||
|
@ -2469,7 +2472,7 @@ static void parse_number(const char *p)
|
||||||
lcount = ucount = 0;
|
lcount = ucount = 0;
|
||||||
p1 = p;
|
p1 = p;
|
||||||
for(;;) {
|
for(;;) {
|
||||||
t = toup(ch);
|
t = toupper(ch);
|
||||||
if (t == 'L') {
|
if (t == 'L') {
|
||||||
if (lcount >= 2)
|
if (lcount >= 2)
|
||||||
tcc_error("three 'l's in integer constant");
|
tcc_error("three 'l's in integer constant");
|
||||||
|
@ -2737,7 +2740,7 @@ maybe_newline:
|
||||||
&& !(parse_flags & PARSE_FLAG_ASM_FILE
|
&& !(parse_flags & PARSE_FLAG_ASM_FILE
|
||||||
/* 0xe+1 is 3 tokens in asm */
|
/* 0xe+1 is 3 tokens in asm */
|
||||||
&& ((char*)tokcstr.data)[0] == '0'
|
&& ((char*)tokcstr.data)[0] == '0'
|
||||||
&& toup(((char*)tokcstr.data)[1]) == 'X'))
|
&& toupper(((char*)tokcstr.data)[1]) == 'X'))
|
||||||
|| t == 'p' || t == 'P'))))
|
|| t == 'p' || t == 'P'))))
|
||||||
break;
|
break;
|
||||||
t = c;
|
t = c;
|
||||||
|
@ -3036,7 +3039,7 @@ static int *macro_arg_subst(Sym **nested_list, const int *macro_str, Sym *args)
|
||||||
if (t2 == TOK_PPJOIN || t1 == TOK_PPJOIN) {
|
if (t2 == TOK_PPJOIN || t1 == TOK_PPJOIN) {
|
||||||
/* special case for var arg macros : ## eats the ','
|
/* special case for var arg macros : ## eats the ','
|
||||||
if empty VA_ARGS variable. */
|
if empty VA_ARGS variable. */
|
||||||
if (t1 == TOK_PPJOIN && t0 == ',' && gnu_ext && s->type.t) {
|
if (t1 == TOK_PPJOIN && t0 == ',' && tcc_state->gnu_ext && s->type.t) {
|
||||||
int c = str.str[str.len - 1];
|
int c = str.str[str.len - 1];
|
||||||
while (str.str[--str.len] != ',')
|
while (str.str[--str.len] != ',')
|
||||||
;
|
;
|
||||||
|
@ -3305,7 +3308,7 @@ static int macro_subst_tok(
|
||||||
break;
|
break;
|
||||||
/* special case for gcc var args: add an empty
|
/* special case for gcc var args: add an empty
|
||||||
var arg argument if it is omitted */
|
var arg argument if it is omitted */
|
||||||
if (sa->type.t && gnu_ext)
|
if (sa->type.t && tcc_state->gnu_ext)
|
||||||
goto empty_arg;
|
goto empty_arg;
|
||||||
tcc_error("macro '%s' used with too few args",
|
tcc_error("macro '%s' used with too few args",
|
||||||
get_tok_str(v, 0));
|
get_tok_str(v, 0));
|
||||||
|
@ -3554,8 +3557,6 @@ static void tcc_predefs(TCCState *s1, CString *cs, int is_asm)
|
||||||
putdef(cs, "__ASSEMBLER__");
|
putdef(cs, "__ASSEMBLER__");
|
||||||
if (s1->output_type == TCC_OUTPUT_PREPROCESS)
|
if (s1->output_type == TCC_OUTPUT_PREPROCESS)
|
||||||
putdef(cs, "__TCC_PP__");
|
putdef(cs, "__TCC_PP__");
|
||||||
if (s1->output_type == TCC_OUTPUT_MEMORY)
|
|
||||||
putdef(cs, "__TCC_RUN__");
|
|
||||||
if (s1->char_is_unsigned)
|
if (s1->char_is_unsigned)
|
||||||
putdef(cs, "__CHAR_UNSIGNED__");
|
putdef(cs, "__CHAR_UNSIGNED__");
|
||||||
if (s1->optimize > 0)
|
if (s1->optimize > 0)
|
||||||
|
@ -3832,7 +3833,7 @@ static int pp_need_space(int a, int b)
|
||||||
/* maybe hex like 0x1e */
|
/* maybe hex like 0x1e */
|
||||||
static int pp_check_he0xE(int t, const char *p)
|
static int pp_check_he0xE(int t, const char *p)
|
||||||
{
|
{
|
||||||
if (t == TOK_PPNUM && toup(strchr(p, 0)[-1]) == 'E')
|
if (t == TOK_PPNUM && toupper(strchr(p, 0)[-1]) == 'E')
|
||||||
return 'E';
|
return 'E';
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
|
@ -81,14 +81,6 @@ void tcc_undefine_symbol(TCCState *s, const char *sym);
|
||||||
*/
|
*/
|
||||||
int tcc_add_file(TCCState *s, const char *filename);
|
int tcc_add_file(TCCState *s, const char *filename);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief compile a string containing a C source. Return -1 if error.
|
|
||||||
*
|
|
||||||
* Tip: to have more specific errors/warnings from tcc_compile_string(),
|
|
||||||
* you can prefix the string with "#line <num> \"<filename>\"\n"
|
|
||||||
*/
|
|
||||||
int tcc_compile_string(TCCState *s, const char *buf);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
|
@ -97,7 +89,6 @@ int tcc_compile_string(TCCState *s, const char *buf);
|
||||||
* @defgroup linking Linking commands
|
* @defgroup linking Linking commands
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
# define TCC_OUTPUT_MEMORY 1 /** output will be run in memory */
|
|
||||||
# define TCC_OUTPUT_EXE 2 /** executable file */
|
# define TCC_OUTPUT_EXE 2 /** executable file */
|
||||||
# define TCC_OUTPUT_OBJ 3 /** object file */
|
# define TCC_OUTPUT_OBJ 3 /** object file */
|
||||||
# define TCC_OUTPUT_PREPROCESS 5 /** only preprocess */
|
# define TCC_OUTPUT_PREPROCESS 5 /** only preprocess */
|
||||||
|
@ -117,35 +108,11 @@ int tcc_add_library_path(TCCState *s, const char *pathname);
|
||||||
*/
|
*/
|
||||||
int tcc_add_library(TCCState *s, const char *libraryname);
|
int tcc_add_library(TCCState *s, const char *libraryname);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief add a symbol to the compiled program.
|
|
||||||
*/
|
|
||||||
int tcc_add_symbol(TCCState *s, const char *name, const void *val);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief output an executable, library or object file.
|
* @brief output an executable, library or object file.
|
||||||
*
|
|
||||||
* DO NOT call tcc_relocate() before.
|
|
||||||
*/
|
*/
|
||||||
int tcc_output_file(TCCState *s, const char *filename);
|
int tcc_output_file(TCCState *s, const char *filename);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief do all relocations (needed before using tcc_get_symbol()).
|
|
||||||
*/
|
|
||||||
int tcc_relocate(TCCState *s1);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief return symbol value or NULL if not found.
|
|
||||||
*/
|
|
||||||
void *tcc_get_symbol(TCCState *s, const char *name);
|
|
||||||
|
|
||||||
typedef void (TCCSymbolFunc)(void *ctx, const char *name, const void *val);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief list all (global) symbols and their values via 'symbol_cb()'.
|
|
||||||
*/
|
|
||||||
void tcc_list_symbols(TCCState *s, void *ctx, TCCSymbolFunc *symbol_cb);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -57,12 +57,6 @@ extern long double strtold (const char *__nptr, char **__endptr);
|
||||||
#define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
|
#define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
|
|
||||||
#ifdef CONFIG_TCC_PIE
|
|
||||||
# define CONFIG_TCC_PIC 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* ------------ path configuration ------------ */
|
/* ------------ path configuration ------------ */
|
||||||
|
|
||||||
#ifndef CONFIG_SYSROOT
|
#ifndef CONFIG_SYSROOT
|
||||||
|
@ -348,28 +342,7 @@ typedef struct Section {
|
||||||
#define TYPE_PARAM 4 /* type declares function parameter */
|
#define TYPE_PARAM 4 /* type declares function parameter */
|
||||||
#define TYPE_NEST 8 /* nested call to post_type */
|
#define TYPE_NEST 8 /* nested call to post_type */
|
||||||
|
|
||||||
#define IO_BUF_SIZE 8192
|
#include <tcc/io.h>
|
||||||
|
|
||||||
typedef struct BufferedFile {
|
|
||||||
uint8_t *buf_ptr;
|
|
||||||
uint8_t *buf_end;
|
|
||||||
int fd;
|
|
||||||
struct BufferedFile *prev;
|
|
||||||
int line_num; /* current line number - here to simplify code */
|
|
||||||
int line_ref; /* tcc -E: last printed line */
|
|
||||||
int ifndef_macro; /* #ifndef macro / #endif search */
|
|
||||||
int ifndef_macro_saved; /* saved ifndef_macro */
|
|
||||||
int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */
|
|
||||||
int include_next_index; /* next search path */
|
|
||||||
int prev_tok_flags; /* saved tok_flags */
|
|
||||||
char filename[1024]; /* filename */
|
|
||||||
char *true_filename; /* filename not modified by # line directive */
|
|
||||||
unsigned char unget[4];
|
|
||||||
unsigned char buffer[1]; /* extra size for CH_EOB char */
|
|
||||||
} BufferedFile;
|
|
||||||
|
|
||||||
#define CH_EOB '\\' /* end of buffer or '\0' char in file */
|
|
||||||
#define CH_EOF (-1) /* end of file */
|
|
||||||
|
|
||||||
/* used to record tokens */
|
/* used to record tokens */
|
||||||
typedef struct TokenString {
|
typedef struct TokenString {
|
||||||
|
@ -436,24 +409,14 @@ typedef struct ASMOperand {
|
||||||
int is_label; /* for asm goto */
|
int is_label; /* for asm goto */
|
||||||
} ASMOperand;
|
} ASMOperand;
|
||||||
|
|
||||||
/* extra symbol attributes (not in symbol table) */
|
|
||||||
struct sym_attr {
|
|
||||||
unsigned got_offset;
|
|
||||||
unsigned plt_offset;
|
|
||||||
int plt_sym;
|
|
||||||
int dyn_index;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TCCState {
|
struct TCCState {
|
||||||
unsigned char verbose; /* if true, display some information during compilation */
|
unsigned char verbose; /* if true, display some information during compilation */
|
||||||
unsigned char nostdinc; /* if true, no standard headers are added */
|
unsigned char nostdinc; /* if true, no standard headers are added */
|
||||||
unsigned char nostdlib; /* if true, no standard libraries 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 symbolic; /* if true, resolve symbols in the current module first */
|
unsigned char symbolic; /* if true, resolve symbols in the current module first */
|
||||||
unsigned char filetype; /* file type for compilation (NONE,C,ASM) */
|
unsigned char filetype; /* file type for compilation (NONE,C,ASM) */
|
||||||
unsigned char optimize; /* only to #define __OPTIMIZE__ */
|
unsigned char optimize; /* only to #define __OPTIMIZE__ */
|
||||||
unsigned char option_pthread; /* -pthread option */
|
unsigned char option_pthread; /* -pthread option */
|
||||||
unsigned char enable_new_dtags; /* -Wl,--enable-new-dtags */
|
|
||||||
unsigned int cversion; /* supported C ISO version, 199901 (the default), 201112, ... */
|
unsigned int cversion; /* supported C ISO version, 199901 (the default), 201112, ... */
|
||||||
|
|
||||||
/* C language options */
|
/* C language options */
|
||||||
|
@ -464,7 +427,6 @@ struct TCCState {
|
||||||
unsigned char ms_bitfields; /* if true, emulate MS algorithm for aligning bitfields */
|
unsigned char ms_bitfields; /* if true, emulate MS algorithm for aligning bitfields */
|
||||||
unsigned char reverse_funcargs; /* if true, evaluate last function arg first */
|
unsigned char reverse_funcargs; /* if true, evaluate last function arg first */
|
||||||
unsigned char gnu89_inline; /* treat 'extern inline' like 'static inline' */
|
unsigned char gnu89_inline; /* treat 'extern inline' like 'static inline' */
|
||||||
unsigned char unwind_tables; /* create eh_frame section */
|
|
||||||
|
|
||||||
/* warning switches */
|
/* warning switches */
|
||||||
unsigned char warn_none;
|
unsigned char warn_none;
|
||||||
|
@ -496,10 +458,7 @@ struct TCCState {
|
||||||
addr_t text_addr; /* address of text section */
|
addr_t text_addr; /* address of text section */
|
||||||
unsigned section_align; /* section alignment */
|
unsigned section_align; /* section alignment */
|
||||||
|
|
||||||
int seg_size; /* 32. Can be 16 with i386 assembler (.code16) */
|
|
||||||
|
|
||||||
char *tcc_lib_path; /* CONFIG_TCCDIR or -B option */
|
char *tcc_lib_path; /* CONFIG_TCCDIR or -B option */
|
||||||
char *rpath; /* as specified on the command line (-Wl,-rpath=) */
|
|
||||||
char *entryname; /* "_start" unless set */
|
char *entryname; /* "_start" unless set */
|
||||||
|
|
||||||
/* output type, see TCC_OUTPUT_XXX */
|
/* output type, see TCC_OUTPUT_XXX */
|
||||||
|
@ -573,47 +532,23 @@ struct TCCState {
|
||||||
|
|
||||||
/* predefined sections */
|
/* predefined sections */
|
||||||
Section *text_section, *data_section, *rodata_section, *bss_section;
|
Section *text_section, *data_section, *rodata_section, *bss_section;
|
||||||
Section *common_section;
|
|
||||||
Section *cur_text_section; /* current section where function code is generated */
|
Section *cur_text_section; /* current section where function code is generated */
|
||||||
/* symbol section */
|
/* symbol section */
|
||||||
union { Section *symtab_section, *symtab; }; /* historical alias */
|
Section *symtab_section;
|
||||||
/* exported dynamic symbol section */
|
|
||||||
Section *dynsym;
|
|
||||||
/* got & plt handling */
|
|
||||||
Section *got, *plt;
|
|
||||||
/* exception handling */
|
|
||||||
Section *eh_frame_section;
|
|
||||||
Section *eh_frame_hdr_section;
|
|
||||||
unsigned long eh_start;
|
|
||||||
|
|
||||||
/* Is there a new undefined sym since last new_undef_sym() */
|
/* Is there a new undefined sym since last new_undef_sym() */
|
||||||
int new_undef_sym;
|
int new_undef_sym;
|
||||||
/* extra attributes (eg. GOT/PLT value) for symtab symbols */
|
|
||||||
struct sym_attr *sym_attrs;
|
|
||||||
int nb_sym_attrs;
|
|
||||||
/* ptr to next reloc entry reused */
|
/* ptr to next reloc entry reused */
|
||||||
ElfW_Rel *qrel;
|
ElfW_Rel *qrel;
|
||||||
#define qrel s1->qrel
|
#define qrel s1->qrel
|
||||||
|
|
||||||
#ifndef ELF_OBJ_ONLY
|
|
||||||
int nb_sym_versions;
|
|
||||||
struct sym_version *sym_versions;
|
|
||||||
int nb_sym_to_version;
|
|
||||||
int *sym_to_version;
|
|
||||||
int dt_verneednum;
|
|
||||||
Section *versym_section;
|
|
||||||
Section *verneed_section;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* benchmark info */
|
/* benchmark info */
|
||||||
int total_idents;
|
int total_idents;
|
||||||
int total_lines;
|
int total_lines;
|
||||||
unsigned int total_bytes;
|
unsigned int total_bytes;
|
||||||
unsigned int total_output[4];
|
unsigned int total_output[4];
|
||||||
|
|
||||||
/* used by tcc_load_ldscript */
|
|
||||||
int fd, cc;
|
|
||||||
|
|
||||||
/* for warnings/errors for object files */
|
/* for warnings/errors for object files */
|
||||||
const char *current_filename;
|
const char *current_filename;
|
||||||
|
|
||||||
|
@ -772,184 +707,6 @@ char *tcc_load_text(int fd);
|
||||||
/* for #pragma once */
|
/* for #pragma once */
|
||||||
int normalized_PATHCMP(const char *f1, const char *f2);
|
int normalized_PATHCMP(const char *f1, const char *f2);
|
||||||
|
|
||||||
/* ------------ tccpp.c ------------ */
|
|
||||||
|
|
||||||
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 */
|
|
||||||
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 */
|
|
||||||
#define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
|
|
||||||
|
|
||||||
#define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
|
|
||||||
#define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */
|
|
||||||
#define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a
|
|
||||||
token. line feed is also
|
|
||||||
returned at eof */
|
|
||||||
#define PARSE_FLAG_ASM_FILE 0x0008 /* we processing an asm file: '#' can be used for line comment, etc. */
|
|
||||||
#define PARSE_FLAG_SPACES 0x0010 /* next() returns space tokens (for -E) */
|
|
||||||
#define PARSE_FLAG_ACCEPT_STRAYS 0x0020 /* next() returns '\\' token */
|
|
||||||
#define PARSE_FLAG_TOK_STR 0x0040 /* return parsed strings instead of TOK_PPSTR */
|
|
||||||
|
|
||||||
/* isidnum_table flags: */
|
|
||||||
#define IS_SPC 1
|
|
||||||
#define IS_ID 2
|
|
||||||
#define IS_NUM 4
|
|
||||||
|
|
||||||
enum line_macro_output_format {
|
|
||||||
LINE_MACRO_OUTPUT_FORMAT_GCC,
|
|
||||||
LINE_MACRO_OUTPUT_FORMAT_NONE,
|
|
||||||
LINE_MACRO_OUTPUT_FORMAT_STD,
|
|
||||||
LINE_MACRO_OUTPUT_FORMAT_P10 = 11
|
|
||||||
};
|
|
||||||
|
|
||||||
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 */
|
|
||||||
static inline int is_space(int ch) {
|
|
||||||
return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
|
|
||||||
}
|
|
||||||
static inline int isid(int c) {
|
|
||||||
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';
|
|
||||||
}
|
|
||||||
static inline int isnum(int c) {
|
|
||||||
return c >= '0' && c <= '9';
|
|
||||||
}
|
|
||||||
static inline int isoct(int c) {
|
|
||||||
return c >= '0' && c <= '7';
|
|
||||||
}
|
|
||||||
static inline int toup(int c) {
|
|
||||||
return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------ tccgen.c ------------ */
|
|
||||||
|
|
||||||
#define SYM_POOL_NB (8192 / sizeof(Sym))
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
void tccgen_init(TCCState *s1);
|
|
||||||
int tccgen_compile(TCCState *s1);
|
|
||||||
void tccgen_finish(TCCState *s1);
|
|
||||||
void check_vstack(void);
|
|
||||||
|
|
||||||
int is_float(int t);
|
|
||||||
int ieee_finite(double d);
|
|
||||||
int exact_log2p1(int i);
|
|
||||||
void test_lvalue(void);
|
|
||||||
|
|
||||||
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
|
|
||||||
void greloc(Section *s, Sym *sym, unsigned long offset, int type);
|
|
||||||
#endif
|
|
||||||
void greloca(Section *s, Sym *sym, unsigned long offset, int type, addr_t addend);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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
|
|
||||||
void lexpand(void);
|
|
||||||
#endif
|
|
||||||
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 ------------ */
|
/* ------------ tccelf.c ------------ */
|
||||||
|
|
||||||
#define TCC_OUTPUT_FORMAT_ELF 0 /* default output format: ELF */
|
#define TCC_OUTPUT_FORMAT_ELF 0 /* default output format: ELF */
|
||||||
|
@ -988,10 +745,7 @@ int tcc_load_object_file(TCCState *s1, int fd, unsigned long file_offset);
|
||||||
int tcc_load_archive(TCCState *s1, int fd, int alacarte);
|
int tcc_load_archive(TCCState *s1, int fd, int alacarte);
|
||||||
void add_array(TCCState *s1, const char *sec, int c);
|
void add_array(TCCState *s1, const char *sec, int c);
|
||||||
|
|
||||||
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);
|
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));
|
|
||||||
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 <type> in section <sec> starting at elem <startoff>
|
/* Browse each elem of type <type> in section <sec> starting at elem <startoff>
|
||||||
|
@ -1001,7 +755,6 @@ int set_global_sym(TCCState *s1, const char *name, Section *sec, addr_t offs);
|
||||||
elem < (type *) (sec->data + sec->data_offset); elem++)
|
elem < (type *) (sec->data + sec->data_offset); elem++)
|
||||||
|
|
||||||
#ifndef ELF_OBJ_ONLY
|
#ifndef ELF_OBJ_ONLY
|
||||||
int tcc_load_ldscript(TCCState *s1, int fd);
|
|
||||||
void tccelf_add_crtbegin(TCCState *s1);
|
void tccelf_add_crtbegin(TCCState *s1);
|
||||||
void tccelf_add_crtend(TCCState *s1);
|
void tccelf_add_crtend(TCCState *s1);
|
||||||
#endif
|
#endif
|
||||||
|
@ -1011,120 +764,7 @@ void tcc_add_runtime(TCCState *s1);
|
||||||
|
|
||||||
int coff_load_file(TCCState *s1, int fd, const char *fname);
|
int coff_load_file(TCCState *s1, int fd, const char *fname);
|
||||||
|
|
||||||
/* ------------ xxx-link.c ------------ */
|
|
||||||
|
|
||||||
#if !defined ELF_OBJ_ONLY
|
|
||||||
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 {
|
|
||||||
NO_GOTPLT_ENTRY, /* never generate (eg. GLOB_DAT & JMP_SLOT relocs) */
|
|
||||||
BUILD_GOT_ONLY, /* only build GOT (eg. TPOFF relocs) */
|
|
||||||
AUTO_GOTPLT_ENTRY, /* generate if sym is UNDEF */
|
|
||||||
ALWAYS_GOTPLT_ENTRY /* always generate (eg. PLTOFF relocs) */
|
|
||||||
};
|
|
||||||
#define NEED_RELOC_TYPE
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val);
|
|
||||||
|
|
||||||
/* ------------ xxx-gen.c ------------ */
|
|
||||||
extern const char * const target_machine_defs;
|
|
||||||
extern const int reg_classes[NB_REGS];
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
static inline void write16le(unsigned char *p, uint16_t x) {
|
|
||||||
p[0] = x & 255; p[1] = x >> 8 & 255;
|
|
||||||
}
|
|
||||||
static inline uint32_t read32le(unsigned char *p) {
|
|
||||||
return read16le(p) | (uint32_t)read16le(p + 2) << 16;
|
|
||||||
}
|
|
||||||
static inline void write32le(unsigned char *p, uint32_t x) {
|
|
||||||
write16le(p, x); write16le(p + 2, x >> 16);
|
|
||||||
}
|
|
||||||
static inline void add32le(unsigned char *p, int32_t x) {
|
|
||||||
write32le(p, read32le(p) + x);
|
|
||||||
}
|
|
||||||
static inline uint64_t read64le(unsigned char *p) {
|
|
||||||
return read32le(p) | (uint64_t)read32le(p + 4) << 32;
|
|
||||||
}
|
|
||||||
static inline void write64le(unsigned char *p, uint64_t x) {
|
|
||||||
write32le(p, x); write32le(p + 4, x >> 32);
|
|
||||||
}
|
|
||||||
static inline void add64le(unsigned char *p, int64_t x) {
|
|
||||||
write64le(p, read64le(p) + x);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------ i386-gen.c ------------ */
|
|
||||||
void g(int c);
|
|
||||||
void gen_le16(int c);
|
|
||||||
void gen_le32(int c);
|
|
||||||
|
|
||||||
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 ------------ */
|
|
||||||
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 ------------ */
|
|
||||||
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 ------------ */
|
/* ------------ tccdbg.c ------------ */
|
||||||
#define eh_frame_hdr_section s1->eh_frame_hdr_section
|
|
||||||
|
|
||||||
#define common_section TCC_STATE_VAR(common_section)
|
|
||||||
#define bounds_section TCC_STATE_VAR(bounds_section)
|
|
||||||
#define lbounds_section TCC_STATE_VAR(lbounds_section)
|
|
||||||
#define symtab_section TCC_STATE_VAR(symtab_section)
|
|
||||||
#define gnu_ext TCC_STATE_VAR(gnu_ext)
|
|
||||||
#define tcc_error_noabort TCC_SET_STATE(_tcc_error_noabort)
|
#define tcc_error_noabort TCC_SET_STATE(_tcc_error_noabort)
|
||||||
#define tcc_error TCC_SET_STATE(_tcc_error)
|
#define tcc_error TCC_SET_STATE(_tcc_error)
|
||||||
#define tcc_warning TCC_SET_STATE(_tcc_warning)
|
#define tcc_warning TCC_SET_STATE(_tcc_warning)
|
||||||
|
|
|
@ -371,7 +371,6 @@ typedef struct
|
||||||
#define PT_TLS 7 /* Thread-local storage segment */
|
#define PT_TLS 7 /* Thread-local storage segment */
|
||||||
#define PT_NUM 8 /* Number of defined types */
|
#define PT_NUM 8 /* Number of defined types */
|
||||||
#define PT_LOOS 0x60000000 /* Start of OS-specific */
|
#define PT_LOOS 0x60000000 /* Start of OS-specific */
|
||||||
#define PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */
|
|
||||||
#define PT_GNU_STACK 0x6474e551 /* Indicates stack executability */
|
#define PT_GNU_STACK 0x6474e551 /* Indicates stack executability */
|
||||||
#define PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */
|
#define PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */
|
||||||
#define PT_LOSUNW 0x6ffffffa
|
#define PT_LOSUNW 0x6ffffffa
|
||||||
|
@ -432,19 +431,6 @@ typedef struct
|
||||||
|
|
||||||
#define NT_VERSION 1 /* Contains a version string. */
|
#define NT_VERSION 1 /* Contains a version string. */
|
||||||
|
|
||||||
|
|
||||||
/* Dynamic section entry. */
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
Elf32_Sword d_tag; /* Dynamic entry type */
|
|
||||||
union
|
|
||||||
{
|
|
||||||
Elf32_Word d_val; /* Integer value */
|
|
||||||
Elf32_Addr d_ptr; /* Address value */
|
|
||||||
} d_un;
|
|
||||||
} Elf32_Dyn;
|
|
||||||
|
|
||||||
/* Legal values for d_tag (dynamic entry type). */
|
/* Legal values for d_tag (dynamic entry type). */
|
||||||
|
|
||||||
#define DT_NULL 0 /* Marks end of dynamic section */
|
#define DT_NULL 0 /* Marks end of dynamic section */
|
||||||
|
@ -462,7 +448,6 @@ typedef struct
|
||||||
#define DT_INIT 12 /* Address of init function */
|
#define DT_INIT 12 /* Address of init function */
|
||||||
#define DT_FINI 13 /* Address of termination function */
|
#define DT_FINI 13 /* Address of termination function */
|
||||||
#define DT_SONAME 14 /* Name of shared object */
|
#define DT_SONAME 14 /* Name of shared object */
|
||||||
#define DT_RPATH 15 /* Library search path (deprecated) */
|
|
||||||
#define DT_SYMBOLIC 16 /* Start symbol search here */
|
#define DT_SYMBOLIC 16 /* Start symbol search here */
|
||||||
#define DT_REL 17 /* Address of Rel relocs */
|
#define DT_REL 17 /* Address of Rel relocs */
|
||||||
#define DT_RELSZ 18 /* Total size of Rel relocs */
|
#define DT_RELSZ 18 /* Total size of Rel relocs */
|
||||||
|
@ -837,14 +822,10 @@ typedef struct
|
||||||
#define R_386_NONE 0 /* No reloc */
|
#define R_386_NONE 0 /* No reloc */
|
||||||
#define R_386_32 1 /* Direct 32 bit */
|
#define R_386_32 1 /* Direct 32 bit */
|
||||||
#define R_386_PC32 2 /* PC relative 32 bit */
|
#define R_386_PC32 2 /* PC relative 32 bit */
|
||||||
#define R_386_GOT32 3 /* 32 bit GOT entry */
|
|
||||||
#define R_386_PLT32 4 /* 32 bit PLT address */
|
|
||||||
#define R_386_COPY 5 /* Copy symbol at runtime */
|
#define R_386_COPY 5 /* Copy symbol at runtime */
|
||||||
#define R_386_GLOB_DAT 6 /* Create GOT entry */
|
#define R_386_GLOB_DAT 6 /* Create GOT entry */
|
||||||
#define R_386_JMP_SLOT 7 /* Create PLT entry */
|
#define R_386_JMP_SLOT 7 /* Create PLT entry */
|
||||||
#define R_386_RELATIVE 8 /* Adjust by program base */
|
#define R_386_RELATIVE 8 /* Adjust by program base */
|
||||||
#define R_386_GOTOFF 9 /* 32 bit offset to GOT */
|
|
||||||
#define R_386_GOTPC 10 /* 32 bit PC relative offset to GOT */
|
|
||||||
#define R_386_32PLT 11
|
#define R_386_32PLT 11
|
||||||
#define R_386_TLS_TPOFF 14 /* Offset in static TLS block */
|
#define R_386_TLS_TPOFF 14 /* Offset in static TLS block */
|
||||||
#define R_386_TLS_IE 15 /* Address of GOT entry for static TLS
|
#define R_386_TLS_IE 15 /* Address of GOT entry for static TLS
|
||||||
|
@ -896,17 +877,5 @@ typedef struct
|
||||||
/* Keep this the last entry. */
|
/* Keep this the last entry. */
|
||||||
#define R_386_NUM 44
|
#define R_386_NUM 44
|
||||||
|
|
||||||
/* AMD x86-64 relocations. */
|
|
||||||
#define R_X86_64_GOT32 3 /* 32 bit GOT entry */
|
|
||||||
#define R_X86_64_PLT32 4 /* 32 bit PLT address */
|
|
||||||
#define R_X86_64_GOTPCREL 9 /* 32 bit signed PC relative
|
|
||||||
offset to GOT */
|
|
||||||
#define R_X86_64_GOTPCRELX 41 /* like GOTPCREL, but optionally with
|
|
||||||
linker optimizations */
|
|
||||||
#define R_X86_64_REX_GOTPCRELX 42 /* like GOTPCRELX, but a REX prefix
|
|
||||||
is present */
|
|
||||||
|
|
||||||
/* x86-64 sh_type values. */
|
|
||||||
#define SHT_X86_64_UNWIND 0x70000001 /* Unwind information. */
|
|
||||||
|
|
||||||
#endif /* elf.h */
|
#endif /* elf.h */
|
||||||
|
|
|
@ -14,7 +14,4 @@
|
||||||
# define ELF_START_ADDR 0x08048000
|
# define ELF_START_ADDR 0x08048000
|
||||||
# define ELF_PAGE_SIZE 0x1000
|
# define ELF_PAGE_SIZE 0x1000
|
||||||
|
|
||||||
# define PCRELATIVE_DLLPLT 0
|
|
||||||
# define RELOCATE_DLLPLT 1
|
|
||||||
|
|
||||||
#endif /* !TCC_I386_LINK_H */
|
#endif /* !TCC_I386_LINK_H */
|
|
@ -17,7 +17,7 @@ typedef struct BufferedFile {
|
||||||
int *ifdef_stack_ptr; /** ifdef_stack value at the start of the file */
|
int *ifdef_stack_ptr; /** ifdef_stack value at the start of the file */
|
||||||
int include_next_index; /** next search path */
|
int include_next_index; /** next search path */
|
||||||
int prev_tok_flags; /** saved tok_flags */
|
int prev_tok_flags; /** saved tok_flags */
|
||||||
char *filename[1024]; /** filename */
|
char filename[1024]; /** filename */
|
||||||
char *true_filename; /** filename not modified by # line directive */
|
char *true_filename; /** filename not modified by # line directive */
|
||||||
unsigned char unget[4];
|
unsigned char unget[4];
|
||||||
unsigned char buffer[1]; /** extra size for CH_EOB char */
|
unsigned char buffer[1]; /** extra size for CH_EOB char */
|
||||||
|
|
|
@ -71,6 +71,7 @@ typedef struct COFFSectionHeader {
|
||||||
# define COFF_STYP_TEXT 0x020
|
# define COFF_STYP_TEXT 0x020
|
||||||
# define COFF_STYP_DATA 0x040
|
# define COFF_STYP_DATA 0x040
|
||||||
# define COFF_STYP_BSS 0x080
|
# define COFF_STYP_BSS 0x080
|
||||||
|
# define COFF_STYP_RODATA 0x100 /** stupidos extension */
|
||||||
# define COFF_STYP_INFO 0x200
|
# define COFF_STYP_INFO 0x200
|
||||||
# define COFF_STYP_OVER 0x400
|
# define COFF_STYP_OVER 0x400
|
||||||
# define COFF_STYP_LIB 0x800
|
# define COFF_STYP_LIB 0x800
|
||||||
|
@ -103,6 +104,9 @@ typedef struct COFFSym {
|
||||||
int8_t numaux;
|
int8_t numaux;
|
||||||
} COFFSym;
|
} COFFSym;
|
||||||
|
|
||||||
|
# define COFF_N_UNDEF 0
|
||||||
|
# define COFF_N_ABS -1
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
# define TCC_OPT_HELP_MORE 'm'
|
# define TCC_OPT_HELP_MORE 'm'
|
||||||
# define TCC_OPT_ARCHIVE 'a'
|
# define TCC_OPT_ARCHIVE 'a'
|
||||||
# define TCC_OPT_VERSION 'V'
|
# define TCC_OPT_VERSION 'V'
|
||||||
# define TCC_OPT_PRINT_DIRS 'P'
|
|
||||||
|
|
||||||
typedef struct TCCOption {
|
typedef struct TCCOption {
|
||||||
const char *name;
|
const char *name;
|
||||||
|
|
|
@ -22,7 +22,7 @@ typedef struct InlineFunc InlineFunc;
|
||||||
|
|
||||||
typedef struct TCCStrtab {
|
typedef struct TCCStrtab {
|
||||||
size_t len;
|
size_t len;
|
||||||
uint8_t *tab;
|
char *tab;
|
||||||
} TCCStrtab;
|
} TCCStrtab;
|
||||||
|
|
||||||
typedef struct TCCSymtab {
|
typedef struct TCCSymtab {
|
||||||
|
@ -41,6 +41,8 @@ typedef struct TCCSection {
|
||||||
char name[8]; /** section name */
|
char name[8]; /** section name */
|
||||||
int32_t flags;
|
int32_t flags;
|
||||||
int16_t secnum;
|
int16_t secnum;
|
||||||
|
int16_t addralign;
|
||||||
|
size_t offset;
|
||||||
} TCCSection;
|
} TCCSection;
|
||||||
|
|
||||||
struct TCCState2 {
|
struct TCCState2 {
|
||||||
|
@ -89,8 +91,6 @@ struct TCCState2 {
|
||||||
uint32_t text_addr; /** address of text section */
|
uint32_t text_addr; /** address of text section */
|
||||||
unsigned section_align; /** section alignment */
|
unsigned section_align; /** section alignment */
|
||||||
|
|
||||||
int seg_size; /** 32. Can be 16 with i386 assembler (.code16) */
|
|
||||||
|
|
||||||
char *tcc_lib_path; /** CONFIG_TCCDIR or -B option */
|
char *tcc_lib_path; /** CONFIG_TCCDIR or -B option */
|
||||||
char *entryname; /** "_start" unless set */
|
char *entryname; /** "_start" unless set */
|
||||||
|
|
||||||
|
@ -161,12 +161,7 @@ struct TCCState2 {
|
||||||
TCCSection *cur_text_section; /** current section where function code is generated */
|
TCCSection *cur_text_section; /** current section where function code is generated */
|
||||||
|
|
||||||
/* symbol data */
|
/* symbol data */
|
||||||
TCCSymtab symtab;
|
TCCSymtab *symtab;
|
||||||
|
|
||||||
/* exception handling */
|
|
||||||
TCCSection *eh_frame_section;
|
|
||||||
TCCSection *eh_frame_hdr_section;
|
|
||||||
uint32_t eh_start;
|
|
||||||
|
|
||||||
/* benchmark info */
|
/* benchmark info */
|
||||||
int total_idents;
|
int total_idents;
|
||||||
|
@ -174,10 +169,6 @@ struct TCCState2 {
|
||||||
uint32_t total_bytes;
|
uint32_t total_bytes;
|
||||||
uint32_t total_output[4];
|
uint32_t total_output[4];
|
||||||
|
|
||||||
/* used by tcc_load_ldscript */
|
|
||||||
int fd;
|
|
||||||
int cc;
|
|
||||||
|
|
||||||
/* for warnings/errors for object files */
|
/* for warnings/errors for object files */
|
||||||
const char *current_filename;
|
const char *current_filename;
|
||||||
};
|
};
|
||||||
|
|
53
libtcc/io.c
Normal file
53
libtcc/io.c
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
|
||||||
|
#include "libtcc.h"
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include "config.h"
|
||||||
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
|
#include <tcc.h>
|
||||||
|
#include <tcc/memory.h>
|
||||||
|
#include <tcc/io.h>
|
||||||
|
#include "utils/string.h"
|
||||||
|
#include "cc/cc.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
tcc_open_bf(TCCState *s1, const char *filename, int initlen)
|
||||||
|
{
|
||||||
|
BufferedFile *bf;
|
||||||
|
int buflen;
|
||||||
|
|
||||||
|
buflen = initlen ? initlen : IO_BUF_SIZE;
|
||||||
|
bf = tcc_mallocz(sizeof(BufferedFile) + buflen);
|
||||||
|
bf->buf_ptr = bf->buffer;
|
||||||
|
bf->buf_end = bf->buffer + initlen;
|
||||||
|
bf->buf_end[0] = CH_EOB; /* put eob symbol */
|
||||||
|
pstrcpy(bf->filename, sizeof(bf->filename), filename);
|
||||||
|
|
||||||
|
bf->true_filename = bf->filename;
|
||||||
|
bf->line_num = 1;
|
||||||
|
bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
|
||||||
|
bf->fd = -1;
|
||||||
|
bf->prev = file;
|
||||||
|
bf->prev_tok_flags = tok_flags;
|
||||||
|
file = bf;
|
||||||
|
tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tcc_close(void)
|
||||||
|
{
|
||||||
|
TCCState *s1 = tcc_state;
|
||||||
|
BufferedFile *bf = file;
|
||||||
|
|
||||||
|
if (bf->fd > 0)
|
||||||
|
{
|
||||||
|
close(bf->fd);
|
||||||
|
total_lines += bf->line_num - 1;
|
||||||
|
}
|
||||||
|
if (bf->true_filename != bf->filename)
|
||||||
|
{
|
||||||
|
tcc_free(bf->true_filename);
|
||||||
|
}
|
||||||
|
file = bf->prev;
|
||||||
|
tok_flags = bf->prev_tok_flags;
|
||||||
|
tcc_free(bf);
|
||||||
|
}
|
|
@ -29,6 +29,7 @@
|
||||||
#include <tcc/memory.h>
|
#include <tcc/memory.h>
|
||||||
#include <tcc/object.h>
|
#include <tcc/object.h>
|
||||||
#include "utils/string.h"
|
#include "utils/string.h"
|
||||||
|
#include "cc/cc.h"
|
||||||
|
|
||||||
/********************************************************/
|
/********************************************************/
|
||||||
/* global variables */
|
/* global variables */
|
||||||
|
@ -64,9 +65,6 @@ char *tcc_load_text(int fd)
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************/
|
|
||||||
/* memory management */
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
# define realpath(file, buf) _fullpath(buf, file, 260)
|
# define realpath(file, buf) _fullpath(buf, file, 260)
|
||||||
#endif
|
#endif
|
||||||
|
@ -278,42 +276,6 @@ PUB_FUNC void _tcc_warning(const char *fmt, ...)
|
||||||
/********************************************************/
|
/********************************************************/
|
||||||
/* I/O layer */
|
/* I/O layer */
|
||||||
|
|
||||||
void tcc_open_bf(TCCState *s1, const char *filename, int initlen)
|
|
||||||
{
|
|
||||||
BufferedFile *bf;
|
|
||||||
int buflen = initlen ? initlen : IO_BUF_SIZE;
|
|
||||||
|
|
||||||
bf = tcc_mallocz(sizeof(BufferedFile) + buflen);
|
|
||||||
bf->buf_ptr = bf->buffer;
|
|
||||||
bf->buf_end = bf->buffer + initlen;
|
|
||||||
bf->buf_end[0] = CH_EOB; /* put eob symbol */
|
|
||||||
pstrcpy(bf->filename, sizeof(bf->filename), filename);
|
|
||||||
|
|
||||||
bf->true_filename = bf->filename;
|
|
||||||
bf->line_num = 1;
|
|
||||||
bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
|
|
||||||
bf->fd = -1;
|
|
||||||
bf->prev = file;
|
|
||||||
bf->prev_tok_flags = tok_flags;
|
|
||||||
file = bf;
|
|
||||||
tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
|
|
||||||
}
|
|
||||||
|
|
||||||
void tcc_close(void)
|
|
||||||
{
|
|
||||||
TCCState *s1 = tcc_state;
|
|
||||||
BufferedFile *bf = file;
|
|
||||||
if (bf->fd > 0) {
|
|
||||||
close(bf->fd);
|
|
||||||
total_lines += bf->line_num - 1;
|
|
||||||
}
|
|
||||||
if (bf->true_filename != bf->filename)
|
|
||||||
tcc_free(bf->true_filename);
|
|
||||||
file = bf->prev;
|
|
||||||
tok_flags = bf->prev_tok_flags;
|
|
||||||
tcc_free(bf);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _tcc_open(TCCState *s1, const char *filename)
|
static int _tcc_open(TCCState *s1, const char *filename)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
@ -384,11 +346,6 @@ static int tcc_compile(TCCState *s1, int filetype, const char *str, int fd)
|
||||||
return s1->nb_errors != 0 ? -1 : 0;
|
return s1->nb_errors != 0 ? -1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int tcc_compile_string(TCCState *s, const char *str)
|
|
||||||
{
|
|
||||||
return tcc_compile(s, s->filetype, str, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* define a preprocessor symbol. value can be NULL, sym can be "sym=val" */
|
/* define a preprocessor symbol. value can be NULL, sym can be "sym=val" */
|
||||||
void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
|
void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
|
||||||
{
|
{
|
||||||
|
@ -419,22 +376,16 @@ TCCState *tcc_new(void)
|
||||||
#undef gnu_ext
|
#undef gnu_ext
|
||||||
s->gnu_ext = 1;
|
s->gnu_ext = 1;
|
||||||
s->tcc_ext = 1;
|
s->tcc_ext = 1;
|
||||||
s->nocommon = 1;
|
|
||||||
s->dollars_in_identifiers = 1; /*on by default like in gcc/clang*/
|
s->dollars_in_identifiers = 1; /*on by default like in gcc/clang*/
|
||||||
s->cversion = 199901; /* default unless -std=c11 is supplied */
|
s->cversion = 199901; /* default unless -std=c11 is supplied */
|
||||||
s->warn_implicit_function_declaration = 1;
|
s->warn_implicit_function_declaration = 1;
|
||||||
s->warn_discarded_qualifiers = 1;
|
s->warn_discarded_qualifiers = 1;
|
||||||
s->ms_extensions = 1;
|
s->ms_extensions = 1;
|
||||||
s->unwind_tables = 1;
|
|
||||||
|
|
||||||
#ifdef __CHAR_UNSIGNED__
|
#ifdef __CHAR_UNSIGNED__
|
||||||
s->char_is_unsigned = 1;
|
s->char_is_unsigned = 1;
|
||||||
#endif
|
#endif
|
||||||
s->seg_size = 32;
|
|
||||||
|
|
||||||
#ifdef CONFIG_NEW_DTAGS
|
|
||||||
s->enable_new_dtags = 1;
|
|
||||||
#endif
|
|
||||||
s->ppfp = stdout;
|
s->ppfp = stdout;
|
||||||
/* might be used in error() before preprocess_start() */
|
/* might be used in error() before preprocess_start() */
|
||||||
s->include_stack_ptr = s->include_stack;
|
s->include_stack_ptr = s->include_stack;
|
||||||
|
@ -457,7 +408,6 @@ void tcc_delete(TCCState *s1)
|
||||||
dynarray_reset(&s1->sysinclude_paths, &s1->nb_sysinclude_paths);
|
dynarray_reset(&s1->sysinclude_paths, &s1->nb_sysinclude_paths);
|
||||||
|
|
||||||
tcc_free(s1->tcc_lib_path);;
|
tcc_free(s1->tcc_lib_path);;
|
||||||
tcc_free(s1->rpath);
|
|
||||||
tcc_free(s1->entryname);
|
tcc_free(s1->entryname);
|
||||||
tcc_free(s1->outfile);
|
tcc_free(s1->outfile);
|
||||||
tcc_free(s1->deps_outfile);
|
tcc_free(s1->deps_outfile);
|
||||||
|
@ -501,7 +451,7 @@ int tcc_set_output_type(TCCState *s, int output_type)
|
||||||
|
|
||||||
/* paths for crt objects */
|
/* paths for crt objects */
|
||||||
tcc_split_path(s, &s->crt_paths, &s->nb_crt_paths, CONFIG_TCC_CRTPREFIX);
|
tcc_split_path(s, &s->crt_paths, &s->nb_crt_paths, CONFIG_TCC_CRTPREFIX);
|
||||||
if (output_type != TCC_OUTPUT_MEMORY && !s->nostdlib)
|
if (!s->nostdlib)
|
||||||
tccelf_add_crtbegin(s);
|
tccelf_add_crtbegin(s);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -564,9 +514,7 @@ int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* as GNU ld, consider it is an ld script if not recognized */
|
/* as GNU ld, consider it is an ld script if not recognized */
|
||||||
ret = tcc_load_ldscript(s1, fd);
|
tcc_error_noabort("%s: unrecognized file type", filename);
|
||||||
if (ret < 0)
|
|
||||||
tcc_error_noabort("%s: unrecognized file type", filename);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
|
@ -660,6 +608,7 @@ int tcc_add_library(TCCState *s, const char *libraryname)
|
||||||
static const char * const libs[] = { "%s/lib%s.a", NULL };
|
static const char * const libs[] = { "%s/lib%s.a", NULL };
|
||||||
const char * const *pp = libs;
|
const char * const *pp = libs;
|
||||||
int flags = s->filetype & AFF_WHOLE_ARCHIVE;
|
int flags = s->filetype & AFF_WHOLE_ARCHIVE;
|
||||||
|
|
||||||
while (*pp) {
|
while (*pp) {
|
||||||
int ret = tcc_add_library_internal(s, *pp,
|
int ret = tcc_add_library_internal(s, *pp,
|
||||||
libraryname, flags, s->library_paths, s->nb_library_paths);
|
libraryname, flags, s->library_paths, s->nb_library_paths);
|
||||||
|
@ -678,18 +627,6 @@ void tcc_add_pragma_libs(TCCState *s1)
|
||||||
tcc_add_library(s1, s1->pragma_libs[i]);
|
tcc_add_library(s1, s1->pragma_libs[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
int tcc_add_symbol(TCCState *s1, const char *name, const void *val)
|
|
||||||
{
|
|
||||||
char buf[256];
|
|
||||||
if (s1->leading_underscore) {
|
|
||||||
buf[0] = '_';
|
|
||||||
pstrcpy(buf + 1, sizeof(buf) - 1, name);
|
|
||||||
name = buf;
|
|
||||||
}
|
|
||||||
set_global_sym(s1, name, NULL, (addr_t)(uintptr_t)val); /* NULL: SHN_ABS */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void tcc_set_lib_path(TCCState *s, const char *path)
|
void tcc_set_lib_path(TCCState *s, const char *path)
|
||||||
{
|
{
|
||||||
tcc_free(s->tcc_lib_path);
|
tcc_free(s->tcc_lib_path);
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <tcc.h>
|
#include <tcc.h>
|
||||||
|
#include "cc/cc.h"
|
||||||
|
|
||||||
#ifdef TCC_MEMORY_DEBUG
|
#ifdef TCC_MEMORY_DEBUG
|
||||||
# undef tcc_free
|
# undef tcc_free
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
#include <tcc.h>
|
#include <string.h>
|
||||||
|
#include <tcc/state.h>
|
||||||
|
#include <tcc/memory.h>
|
||||||
#include <tcc/object.h>
|
#include <tcc/object.h>
|
||||||
#include <tcc/object/archive.h>
|
#include <tcc/object/archive.h>
|
||||||
#include <tcc/object/coff.h>
|
#include <tcc/object/coff.h>
|
||||||
|
@ -10,4 +12,4 @@ tcc_object_type(int fd, void *h)
|
||||||
|
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#include "utils/string.h"
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
# include "config.h"
|
# include "config.h"
|
||||||
|
@ -7,6 +10,8 @@
|
||||||
#include <tcc/object/coff.h>
|
#include <tcc/object/coff.h>
|
||||||
#include <tcc/state.h>
|
#include <tcc/state.h>
|
||||||
|
|
||||||
|
#define ALIGN_UP(val, alignment) ((val + alignment - 1) & -alignment)
|
||||||
|
|
||||||
#define COFF_DEFAULT_ENTRYNAME "_start"
|
#define COFF_DEFAULT_ENTRYNAME "_start"
|
||||||
|
|
||||||
void dynarray_add(void *ptab, int *nb_ptr, void *data);
|
void dynarray_add(void *ptab, int *nb_ptr, void *data);
|
||||||
|
@ -39,14 +44,6 @@ coff_free_section(TCCSection *s)
|
||||||
s->data_allocated = s->data_offset = 0;
|
s->data_allocated = s->data_offset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
coff_new_symtab(TCCState2 *s1)
|
|
||||||
{
|
|
||||||
TCCSymtab *symtab;
|
|
||||||
|
|
||||||
symtab = tcc_mallocz(sizeof(TCCSymtab));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
coff_new(TCCState2 *s1)
|
coff_new(TCCState2 *s1)
|
||||||
{
|
{
|
||||||
|
@ -55,9 +52,12 @@ coff_new(TCCState2 *s1)
|
||||||
s1->text_section = coff_new_section(s1, ".text", COFF_STYP_TEXT);
|
s1->text_section = coff_new_section(s1, ".text", COFF_STYP_TEXT);
|
||||||
s1->data_section = coff_new_section(s1, ".data", COFF_STYP_DATA);
|
s1->data_section = coff_new_section(s1, ".data", COFF_STYP_DATA);
|
||||||
s1->bss_section = coff_new_section(s1, ".bss", COFF_STYP_BSS);
|
s1->bss_section = coff_new_section(s1, ".bss", COFF_STYP_BSS);
|
||||||
s1->rodata_section = coff_new_section(s1, ".rodata", COFF_STYP_DATA);
|
s1->rodata_section = coff_new_section(s1, ".rodata", COFF_STYP_RODATA);
|
||||||
|
|
||||||
coff_new_symtab(s1);
|
s1->symtab = tcc_mallocz(sizeof(TCCSymtab)); /* create new symtab */
|
||||||
|
/* add dummy symbols */
|
||||||
|
s1->symtab->nsym++;
|
||||||
|
s1->symtab->syms = tcc_mallocz(sizeof(COFFSym));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -71,6 +71,218 @@ coff_delete(TCCState2 *s1)
|
||||||
}
|
}
|
||||||
|
|
||||||
dynarray_reset(&s1->sections, &s1->nb_sections);
|
dynarray_reset(&s1->sections, &s1->nb_sections);
|
||||||
|
|
||||||
|
if (s1->symtab != NULL)
|
||||||
|
{
|
||||||
|
tcc_free(s1->symtab->strtab.tab);
|
||||||
|
tcc_free(s1->symtab->syms);
|
||||||
|
tcc_free(s1->symtab);
|
||||||
|
s1->symtab = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
coff_begin_file(TCCState2 *s1)
|
||||||
|
{
|
||||||
|
TCCSection *sec;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 1; i < s1->nb_sections; i++)
|
||||||
|
{
|
||||||
|
sec = s1->sections[i];
|
||||||
|
sec->offset = sec->data_offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
coff_section_realloc(TCCSection *sec, size_t new_size)
|
||||||
|
{
|
||||||
|
size_t size;
|
||||||
|
uint8_t *data;
|
||||||
|
|
||||||
|
size = sec->data_allocated;
|
||||||
|
if (size == 0)
|
||||||
|
{
|
||||||
|
size = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (size < new_size)
|
||||||
|
{
|
||||||
|
size = size * 2;
|
||||||
|
}
|
||||||
|
data = tcc_realloc(sec->data, size);
|
||||||
|
memset(data + sec->data_allocated, 0, size - sec->data_allocated);
|
||||||
|
sec->data = data;
|
||||||
|
sec->data_allocated = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
coff_section_add(TCCSection *sec, size_t size, int align)
|
||||||
|
{
|
||||||
|
size_t offset;
|
||||||
|
size_t offset1;
|
||||||
|
|
||||||
|
offset = ALIGN_UP(sec->data_offset, align);
|
||||||
|
offset1 = offset + size;
|
||||||
|
if (sec->flags != COFF_STYP_BSS && offset1 > sec->data_allocated)
|
||||||
|
{
|
||||||
|
coff_section_realloc(sec, offset1);
|
||||||
|
}
|
||||||
|
sec->data_offset = offset1;
|
||||||
|
if (align > sec->addralign)
|
||||||
|
{
|
||||||
|
sec->addralign = align;
|
||||||
|
}
|
||||||
|
return (offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* reserve at least 'size' bytes in section 'sec' from
|
||||||
|
sec->data_offset. */
|
||||||
|
void *
|
||||||
|
coff_section_ptr_add(TCCSection *sec, size_t size)
|
||||||
|
{
|
||||||
|
return (sec->data + coff_section_add(sec, size, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
static TCCSection *
|
||||||
|
coff_have_section(TCCState2 *s1, const char *name)
|
||||||
|
{
|
||||||
|
TCCSection *sec;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 1; i < s1->nb_sections; i++)
|
||||||
|
{
|
||||||
|
sec = s1->sections[i];
|
||||||
|
if (strncmp(name, sec->name, 8) == 0)
|
||||||
|
{
|
||||||
|
return (sec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return a reference to a section, and create it if it does not
|
||||||
|
exists */
|
||||||
|
TCCSection *
|
||||||
|
coff_find_section(TCCState2 *s1, const char *name)
|
||||||
|
{
|
||||||
|
TCCSection *sec;
|
||||||
|
|
||||||
|
sec = coff_have_section(s1, name);
|
||||||
|
if (sec != NULL)
|
||||||
|
{
|
||||||
|
return (sec);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (coff_new_section(s1, name, COFF_STYP_TEXT));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ---------------------------------------------------------------------------
|
||||||
|
* Symbols
|
||||||
|
* ---------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
coff_add_sym(TCCState2 *s1, uint32_t value, const char *name, size_t size,
|
||||||
|
int16_t scnum, uint16_t type, int8_t sclass)
|
||||||
|
{
|
||||||
|
size_t symidx;
|
||||||
|
size_t strtaboffset;
|
||||||
|
COFFSym *sym;
|
||||||
|
char *ptr;
|
||||||
|
|
||||||
|
symidx = s1->symtab->nsym;
|
||||||
|
s1->symtab->nsym++;
|
||||||
|
|
||||||
|
s1->symtab->syms = tcc_realloc(s1->symtab->syms, sizeof(COFFSym) * s1->symtab->nsym);
|
||||||
|
sym = &(s1->symtab->syms[symidx]);
|
||||||
|
if (size > 8)
|
||||||
|
{
|
||||||
|
strtaboffset = ALIGN_UP(s1->symtab->strtab.len, 1);
|
||||||
|
s1->symtab->strtab.len += strtaboffset + size + 1;
|
||||||
|
ptr = s1->symtab->strtab.tab;
|
||||||
|
s1->symtab->strtab.tab = tcc_realloc(ptr, s1->symtab->strtab.len);
|
||||||
|
ptr += strtaboffset;
|
||||||
|
memcpy(ptr, name, size + 1);
|
||||||
|
|
||||||
|
sym->n.n.zeroes = 0x0;
|
||||||
|
sym->n.n.offset = strtaboffset;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memset(sym->n.name, 0, 8);
|
||||||
|
memcpy(sym->n.name, name, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (symidx);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
coff_find_sym(TCCState2 *s1, const char *name)
|
||||||
|
{
|
||||||
|
size_t symidx;
|
||||||
|
size_t len;
|
||||||
|
COFFSym *sym;
|
||||||
|
const char *str;
|
||||||
|
|
||||||
|
len = strlen(name);
|
||||||
|
|
||||||
|
for (symidx = 1; symidx < s1->symtab->nsym; symidx++)
|
||||||
|
{
|
||||||
|
sym = &(s1->symtab->syms[symidx]);
|
||||||
|
|
||||||
|
if ((len > 8 && sym->n.n.zeroes != 0)
|
||||||
|
|| (len <= 8 && sym->n.n.zeroes == 0))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (len > 8)
|
||||||
|
{
|
||||||
|
str = s1->symtab->strtab.tab + sym->n.n.offset;
|
||||||
|
if (strcmp(name, str) == 0)
|
||||||
|
{
|
||||||
|
return (symidx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (strncmp(name, sym->n.name, 8) == 0)
|
||||||
|
{
|
||||||
|
return (symidx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
coff_get_sym_addr(TCCState2 *s1, const char *name, int err, int forc)
|
||||||
|
{
|
||||||
|
COFFSym *sym;
|
||||||
|
int sym_idx;
|
||||||
|
char buf[256];
|
||||||
|
|
||||||
|
if (forc && s1->leading_underscore)
|
||||||
|
{
|
||||||
|
buf[0] = '_';
|
||||||
|
pstrcpy(buf + 1, sizeof(buf) - 1, name);
|
||||||
|
name = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
sym_idx = coff_find_sym(s1, name);
|
||||||
|
sym = &((COFFSym *)s1->symtab->syms)[sym_idx];
|
||||||
|
if (sym_idx == 0 || sym->scnum == COFF_N_UNDEF)
|
||||||
|
{
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
//_tcc_error_noabort("%s not defined", name);
|
||||||
|
}
|
||||||
|
return ((uint32_t)-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (sym->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
|
@ -54,7 +54,6 @@ enum {
|
||||||
OPTION_include,
|
OPTION_include,
|
||||||
OPTION_nostdinc,
|
OPTION_nostdinc,
|
||||||
OPTION_nostdlib,
|
OPTION_nostdlib,
|
||||||
OPTION_print_search_dirs,
|
|
||||||
OPTION_w,
|
OPTION_w,
|
||||||
OPTION_E,
|
OPTION_E,
|
||||||
OPTION_M,
|
OPTION_M,
|
||||||
|
@ -100,7 +99,6 @@ static const TCCOption options[] = {
|
||||||
{"include", OPTION_include, TCC_OPTION_HAS_ARG},
|
{"include", OPTION_include, TCC_OPTION_HAS_ARG},
|
||||||
{"nostdinc", OPTION_nostdinc, 0},
|
{"nostdinc", OPTION_nostdinc, 0},
|
||||||
{"nostdlib", OPTION_nostdlib, 0},
|
{"nostdlib", OPTION_nostdlib, 0},
|
||||||
{"print-search-dirs", OPTION_print_search_dirs, 0},
|
|
||||||
{"w", OPTION_w, 0},
|
{"w", OPTION_w, 0},
|
||||||
{"E", OPTION_E, 0},
|
{"E", OPTION_E, 0},
|
||||||
{"M", OPTION_M, 0},
|
{"M", OPTION_M, 0},
|
||||||
|
@ -141,13 +139,11 @@ static const Flag options_W[] = {
|
||||||
static const Flag options_f[] = {
|
static const Flag options_f[] = {
|
||||||
{offsetof(TCCState, char_is_unsigned), 0, "unsigned-char"},
|
{offsetof(TCCState, char_is_unsigned), 0, "unsigned-char"},
|
||||||
{offsetof(TCCState, char_is_unsigned), F_FD_INVERT, "signed-char"},
|
{offsetof(TCCState, char_is_unsigned), F_FD_INVERT, "signed-char"},
|
||||||
{offsetof(TCCState, nocommon), F_FD_INVERT, "common"},
|
|
||||||
{offsetof(TCCState, leading_underscore), 0, "leading-underscore"},
|
{offsetof(TCCState, leading_underscore), 0, "leading-underscore"},
|
||||||
{offsetof(TCCState, ms_extensions), 0, "ms-extensions"},
|
{offsetof(TCCState, ms_extensions), 0, "ms-extensions"},
|
||||||
{offsetof(TCCState, dollars_in_identifiers), 0, "dollars-in-identifiers"},
|
{offsetof(TCCState, dollars_in_identifiers), 0, "dollars-in-identifiers"},
|
||||||
{offsetof(TCCState, reverse_funcargs), 0, "reverse-funcargs"},
|
{offsetof(TCCState, reverse_funcargs), 0, "reverse-funcargs"},
|
||||||
{offsetof(TCCState, gnu89_inline), 0, "gnu89-inline"},
|
{offsetof(TCCState, gnu89_inline), 0, "gnu89-inline"},
|
||||||
{offsetof(TCCState, unwind_tables), 0, "asynchronous-unwind-tables"},
|
|
||||||
{0, 0, NULL}
|
{0, 0, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -333,25 +329,23 @@ set_linker(TCCState *s, const char *option)
|
||||||
s->text_addr = strtoull(p, &end, 16);
|
s->text_addr = strtoull(p, &end, 16);
|
||||||
s->has_text_addr = 1;
|
s->has_text_addr = 1;
|
||||||
} else if (link_option(option, "oformat=", &p)) {
|
} else if (link_option(option, "oformat=", &p)) {
|
||||||
if (strstart("elf32-", &p)) {
|
if (link_arg("binary", p))
|
||||||
s->output_format = TCC_OUTPUT_FORMAT_ELF;
|
{
|
||||||
} else if (link_arg("binary", p)) {
|
|
||||||
s->output_format = TCC_OUTPUT_FORMAT_BINARY;
|
s->output_format = TCC_OUTPUT_FORMAT_BINARY;
|
||||||
#ifdef TCC_TARGET_COFF
|
}
|
||||||
} else if (link_arg("coff", p)) {
|
else if (link_arg("coff", p))
|
||||||
|
{
|
||||||
s->output_format = TCC_OUTPUT_FORMAT_COFF;
|
s->output_format = TCC_OUTPUT_FORMAT_COFF;
|
||||||
#endif
|
}
|
||||||
} else
|
else
|
||||||
|
{
|
||||||
goto err;
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
} else if (link_option(option, "as-needed", &p)) {
|
} else if (link_option(option, "as-needed", &p)) {
|
||||||
ignoring = 1;
|
ignoring = 1;
|
||||||
} else if (link_option(option, "O", &p)) {
|
} else if (link_option(option, "O", &p)) {
|
||||||
ignoring = 1;
|
ignoring = 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)) {
|
} else if (link_option(option, "section-alignment=", &p)) {
|
||||||
s->section_align = strtoul(p, &end, 16);
|
s->section_align = strtoul(p, &end, 16);
|
||||||
} else if (ret = link_option(option, "?whole-archive", &p), ret) {
|
} else if (ret = link_option(option, "?whole-archive", &p), ret) {
|
||||||
|
@ -717,9 +711,6 @@ reparse:
|
||||||
case OPTION_O:
|
case OPTION_O:
|
||||||
s->optimize = atoi(optarg);
|
s->optimize = atoi(optarg);
|
||||||
break;
|
break;
|
||||||
case OPTION_print_search_dirs:
|
|
||||||
x = TCC_OPT_PRINT_DIRS;
|
|
||||||
goto extra_action;
|
|
||||||
case OPTION_ar:
|
case OPTION_ar:
|
||||||
x = TCC_OPT_ARCHIVE;
|
x = TCC_OPT_ARCHIVE;
|
||||||
extra_action:
|
extra_action:
|
||||||
|
@ -745,8 +736,6 @@ unsupported_option:
|
||||||
return (tool);
|
return (tool);
|
||||||
if (optind != noaction)
|
if (optind != noaction)
|
||||||
return (0);
|
return (0);
|
||||||
if (s->verbose == 2)
|
|
||||||
return (TCC_OPT_PRINT_DIRS);
|
|
||||||
if (s->verbose)
|
if (s->verbose)
|
||||||
return (TCC_OPT_VERSION);
|
return (TCC_OPT_VERSION);
|
||||||
return (TCC_OPT_HELP);
|
return (TCC_OPT_HELP);
|
||||||
|
|
1037
libtcc/tccelf.c
1037
libtcc/tccelf.c
File diff suppressed because it is too large
Load diff
32
tcc-doc.texi
32
tcc-doc.texi
|
@ -284,7 +284,7 @@ Specify an additional static library path for the @option{-l} option. The
|
||||||
default library paths are @file{/usr/local/lib}, @file{/usr/lib} and @file{/lib}.
|
default library paths are @file{/usr/local/lib}, @file{/usr/lib} and @file{/lib}.
|
||||||
|
|
||||||
@item -lxxx
|
@item -lxxx
|
||||||
Link your program with dynamic library libxxx.so or static library
|
Link your program with static library
|
||||||
libxxx.a. The library is searched in the paths specified by the
|
libxxx.a. The library is searched in the paths specified by the
|
||||||
@option{-L} option and @env{LIBRARY_PATH} variable.
|
@option{-L} option and @env{LIBRARY_PATH} variable.
|
||||||
|
|
||||||
|
@ -292,30 +292,14 @@ libxxx.a. The library is searched in the paths specified by the
|
||||||
Set the path where the tcc internal libraries (and include files) can be
|
Set the path where the tcc internal libraries (and include files) can be
|
||||||
found (default is @file{PREFIX/lib/tcc}).
|
found (default is @file{PREFIX/lib/tcc}).
|
||||||
|
|
||||||
@item -shared
|
|
||||||
Generate a shared library instead of an executable.
|
|
||||||
|
|
||||||
@item -soname name
|
|
||||||
set name for shared library to be used at runtime
|
|
||||||
|
|
||||||
@item -static
|
@item -static
|
||||||
Generate a statically linked executable (default is a shared linked
|
Generate a statically linked executable (default is a shared linked
|
||||||
executable).
|
executable).
|
||||||
|
|
||||||
@item -rdynamic
|
|
||||||
Export global symbols to the dynamic linker. It is useful when a library
|
|
||||||
opened with @code{dlopen()} needs to access executable symbols.
|
|
||||||
|
|
||||||
@item -r
|
@item -r
|
||||||
Generate an object file combining all input files.
|
Generate an object file combining all input files.
|
||||||
|
|
||||||
@item -Wl,-rpath=path
|
|
||||||
Put custom search path for dynamic libraries into executable.
|
|
||||||
|
|
||||||
@item -Wl,--enable-new-dtags
|
|
||||||
When putting a custom search path for dynamic libraries into the executable,
|
|
||||||
create the new ELF dynamic tag DT_RUNPATH instead of the old legacy DT_RPATH.
|
|
||||||
|
|
||||||
@item -Wl,--oformat=fmt
|
@item -Wl,--oformat=fmt
|
||||||
Use @var{fmt} as output format. The supported output formats are:
|
Use @var{fmt} as output format. The supported output formats are:
|
||||||
@table @code
|
@table @code
|
||||||
|
@ -327,11 +311,6 @@ Binary image (only for executable output)
|
||||||
COFF output format (only for executable output for TMS320C67xx target)
|
COFF output format (only for executable output for TMS320C67xx target)
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
@item -Wl,--export-all-symbols
|
|
||||||
@item -Wl,--export-dynamic
|
|
||||||
Export global symbols to the dynamic linker. It is useful when a library
|
|
||||||
opened with @code{dlopen()} needs to access executable symbols.
|
|
||||||
|
|
||||||
@item -Wl,-subsystem=console/gui/wince/...
|
@item -Wl,-subsystem=console/gui/wince/...
|
||||||
Set type for PE (Windows) executables.
|
Set type for PE (Windows) executables.
|
||||||
|
|
||||||
|
@ -827,13 +806,9 @@ Currently, MMX opcodes are supported but not SSE ones.
|
||||||
@cindex ELF
|
@cindex ELF
|
||||||
|
|
||||||
TCC can directly output relocatable ELF files (object files),
|
TCC can directly output relocatable ELF files (object files),
|
||||||
executable ELF files and dynamic ELF libraries without relying on an
|
executable ELF files without relying on an
|
||||||
external linker.
|
external linker.
|
||||||
|
|
||||||
Dynamic ELF libraries can be output but the C compiler does not generate
|
|
||||||
position independent code (PIC). It means that the dynamic library
|
|
||||||
code generated by TCC cannot be factorized among processes yet.
|
|
||||||
|
|
||||||
TCC linker eliminates unreferenced object code in libraries. A single pass is
|
TCC linker eliminates unreferenced object code in libraries. A single pass is
|
||||||
done on the object and library list, so the order in which object files and
|
done on the object and library list, so the order in which object files and
|
||||||
libraries are specified is important (same constraint as GNU ld). No grouping
|
libraries are specified is important (same constraint as GNU ld). No grouping
|
||||||
|
@ -841,8 +816,7 @@ options (@option{--start-group} and @option{--end-group}) are supported.
|
||||||
|
|
||||||
@section ELF file loader
|
@section ELF file loader
|
||||||
|
|
||||||
TCC can load ELF object files, archives (.a files) and dynamic
|
TCC can load ELF object files and archives (.a files).
|
||||||
libraries (.so).
|
|
||||||
|
|
||||||
@section PE-i386 file generation
|
@section PE-i386 file generation
|
||||||
@cindex PE-i386
|
@cindex PE-i386
|
||||||
|
|
23
tcc/tcc.c
23
tcc/tcc.c
|
@ -17,8 +17,9 @@
|
||||||
* License along with this library; if not, write to the Free Software
|
* License along with this library; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
# include "config.h"
|
||||||
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
@ -50,7 +51,7 @@ static const char help_str[] =
|
||||||
" -E preprocess only\n"
|
" -E preprocess only\n"
|
||||||
"Linker options:\n"
|
"Linker options:\n"
|
||||||
" -Ldir add library path 'dir'\n"
|
" -Ldir add library path 'dir'\n"
|
||||||
" -llib link with dynamic or static library 'lib'\n"
|
" -llib link with static library 'lib'\n"
|
||||||
" -r generate (relocatable) object file\n"
|
" -r generate (relocatable) object file\n"
|
||||||
" -Wl,-opt[=val] set linker option (see tcc -hh)\n"
|
" -Wl,-opt[=val] set linker option (see tcc -hh)\n"
|
||||||
"Misc. options:\n"
|
"Misc. options:\n"
|
||||||
|
@ -89,14 +90,11 @@ static const char help_more_str[] =
|
||||||
" discarded-qualifiers warn when const is dropped (*)\n"
|
" discarded-qualifiers warn when const is dropped (*)\n"
|
||||||
"-f[no-]... flags:\n"
|
"-f[no-]... flags:\n"
|
||||||
" unsigned-char default char is unsigned\n"
|
" unsigned-char default char is unsigned\n"
|
||||||
" signed-char default char is signed\n"
|
" signed-char default char is signed\n" " leading-underscore decorate extern symbols\n"
|
||||||
" common use common section instead of bss\n"
|
|
||||||
" leading-underscore decorate extern symbols\n"
|
|
||||||
" ms-extensions allow anonymous struct in struct\n"
|
" ms-extensions allow anonymous struct in struct\n"
|
||||||
" dollars-in-identifiers allow '$' in C symbols\n"
|
" dollars-in-identifiers allow '$' in C symbols\n"
|
||||||
" reverse-funcargs evaluate function arguments right to left\n"
|
" reverse-funcargs evaluate function arguments right to left\n"
|
||||||
" gnu89-inline 'extern inline' is like 'static inline'\n"
|
" gnu89-inline 'extern inline' is like 'static inline'\n"
|
||||||
" asynchronous-unwind-tables create eh_frame section [on]\n"
|
|
||||||
"-m... target specific options:\n"
|
"-m... target specific options:\n"
|
||||||
" ms-bitfields use MSVC bitfield layout\n"
|
" ms-bitfields use MSVC bitfield layout\n"
|
||||||
"-Wl,... linker options:\n"
|
"-Wl,... linker options:\n"
|
||||||
|
@ -104,7 +102,6 @@ static const char help_more_str[] =
|
||||||
" -[no-]whole-archive load lib(s) fully/only as needed\n"
|
" -[no-]whole-archive load lib(s) fully/only as needed\n"
|
||||||
" -image-base= -Ttext= set base address of executable\n"
|
" -image-base= -Ttext= set base address of executable\n"
|
||||||
" -section-alignment= set section alignment in executable\n"
|
" -section-alignment= set section alignment in executable\n"
|
||||||
" -enable-new-dtags set DT_RUNPATH instead of DT_RPATH\n"
|
|
||||||
" -oformat=[coff,binary] set executable output format\n"
|
" -oformat=[coff,binary] set executable output format\n"
|
||||||
" -init= -fini= -Map= -as-needed -O (ignored)\n"
|
" -init= -fini= -Map= -as-needed -O (ignored)\n"
|
||||||
"Predefined macros:\n"
|
"Predefined macros:\n"
|
||||||
|
@ -221,13 +218,6 @@ redo:
|
||||||
return tcc_tool_ar(s, argc, argv);
|
return tcc_tool_ar(s, argc, argv);
|
||||||
if (opt == TCC_OPT_VERSION)
|
if (opt == TCC_OPT_VERSION)
|
||||||
return 0;
|
return 0;
|
||||||
if (opt == TCC_OPT_PRINT_DIRS) {
|
|
||||||
/* initialize search dirs */
|
|
||||||
set_environment(s);
|
|
||||||
tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
|
|
||||||
print_search_dirs(s);
|
|
||||||
return (EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s->nb_files == 0) {
|
if (s->nb_files == 0) {
|
||||||
tcc_error_noabort("no input files");
|
tcc_error_noabort("no input files");
|
||||||
|
@ -279,15 +269,12 @@ redo:
|
||||||
if (s->output_type == TCC_OUTPUT_PREPROCESS) {
|
if (s->output_type == TCC_OUTPUT_PREPROCESS) {
|
||||||
;
|
;
|
||||||
} else if (0 == ret) {
|
} else if (0 == ret) {
|
||||||
if (s->output_type == TCC_OUTPUT_MEMORY) {
|
|
||||||
} else {
|
|
||||||
if (!s->outfile)
|
if (!s->outfile)
|
||||||
s->outfile = default_outputfile(s, first_file);
|
s->outfile = default_outputfile(s, first_file);
|
||||||
if (!s->just_deps)
|
if (!s->just_deps)
|
||||||
ret = tcc_output_file(s, s->outfile);
|
ret = tcc_output_file(s, s->outfile);
|
||||||
if (!ret && s->gen_deps)
|
if (!ret && s->gen_deps)
|
||||||
gen_makedeps(s, s->outfile, s->deps_outfile);
|
gen_makedeps(s, s->outfile, s->deps_outfile);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
done = 1;
|
done = 1;
|
||||||
|
|
|
@ -27,6 +27,9 @@
|
||||||
* License along with this library; if not, write to the Free Software
|
* License along with this library; if not, write to the Free Software
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include "config.h"
|
||||||
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
@ -361,6 +364,9 @@ const int _dowildcard = 1;
|
||||||
|
|
||||||
/* -------------------------------------------------------------- */
|
/* -------------------------------------------------------------- */
|
||||||
/* generate xxx.d file */
|
/* generate xxx.d file */
|
||||||
|
static inline int is_space(int ch) {
|
||||||
|
return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
|
||||||
|
}
|
||||||
|
|
||||||
static char *escape_target_dep(const char *s) {
|
static char *escape_target_dep(const char *s) {
|
||||||
char *res = tcc_malloc(strlen(s) * 2 + 1);
|
char *res = tcc_malloc(strlen(s) * 2 + 1);
|
||||||
|
|
Loading…
Reference in a new issue