Further strip down tcc

This commit is contained in:
d0p1 🏳️‍⚧️ 2025-02-14 17:47:45 +01:00
parent 94b74d446f
commit c5d1e40ebe
30 changed files with 723 additions and 1881 deletions

View file

@ -1,6 +1,7 @@
noinst_LIBRARIES = libtcc.a
libtcc_a_SOURCES = libtcc.c option.c path.c memory.c tccpp.c tccgen.c \
tccasm.c tccelf.c \
i386/gen.c i386/link.c \
i386/asm.c tcccoff.c
libtcc_a_SOURCES = libtcc.c option.c path.c io.c memory.c \
cc/tccpp.c cc/tccgen.c \
cc/tccasm.c tccelf.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

275
libtcc/cc/cc.h Normal file
View 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 */

View file

@ -25,7 +25,9 @@
#define USING_GLOBALS
#include "tcc.h"
#include "token.h"
#define USING_GLOBALS
#include "cc/cc.h"
#include "cC/token.h"
#define MAX_OPERANDS 3
@ -1268,7 +1270,7 @@ void subst_asm_operand(CString *add_str,
in the C symbol table when later looking up
this name. So enter them now into the asm label
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)
cstr_ccat(add_str, '_');

View file

@ -20,7 +20,9 @@
#define USING_GLOBALS
#include <tcc.h>
#include "token.h"
#include "cc/token.h"
#define USING_GLOBALS
#include "cc/cc.h"
const char * const target_machine_defs =
"__i386__\0"

View file

@ -1,4 +1,5 @@
#include <tcc.h>
#include "cc/cc.h"
#ifdef NEED_RELOC_TYPE
/* 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_16:
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_COPY:
case R_386_TLS_GD:
@ -23,126 +20,12 @@ int code_reloc (int reloc_type)
case R_386_PC16:
case R_386_PC32:
case R_386_PLT32:
case R_386_JMP_SLOT:
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
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:
add32le(ptr, val - addr);
return;
case R_386_PLT32:
add32le(ptr, val - addr);
return;
case R_386_GLOB_DAT:
case R_386_JMP_SLOT:
write32le(ptr, val);
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:
if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY) {
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));
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];
x = sym->st_value - sec->sh_addr - sec->data_offset;
add32le(ptr + 5, -x);
@ -259,7 +128,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
Section *sec;
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];
x = val - sec->sh_addr - sec->data_offset;
add32le(ptr, x);

View file

@ -17,16 +17,23 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "libtcc.h"
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif /* HAVE_CONFIG_H */
#include <stdlib.h>
#define USING_GLOBALS
#include "tcc.h"
#include "utils/string.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 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
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. */
static int asm2cname(int v, int *addeddot)
static int asm2cname(TCCState *s1, int v, int *addeddot)
{
const char *name;
*addeddot = 0;
if (!tcc_state->leading_underscore)
if (!s1->leading_underscore)
return v;
name = get_tok_str(v, NULL);
if (!name)
@ -73,20 +80,20 @@ static int asm2cname(int v, int *addeddot)
return v;
}
static Sym *asm_label_find(int v)
static Sym *asm_label_find(TCCState *s1, int v)
{
Sym *sym;
int addeddot;
v = asm2cname(v, &addeddot);
v = asm2cname(s1, v, &addeddot);
sym = sym_find(v);
while (sym && sym->sym_scope && !(sym->type.t & VT_STATIC))
sym = sym->prev_tok;
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
(for .set, removed for real defs), for mere references it's correct
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
all information from that symbol to the (possibly newly created)
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) {
sym = asm_label_push(name);
sym = asm_label_push(s1, name);
if (csym)
sym->c = csym->c;
}
@ -122,7 +129,7 @@ static Sym* asm_section_sym(TCCState *s1, Section *sec)
char buf[100]; int label; Sym *sym;
snprintf(buf, sizeof buf, "L.%s", sec->old_name);
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);
}
@ -143,7 +150,7 @@ static void asm_expr_unary(TCCState *s1, ExprValue *pe)
if (*p == 'b' || *p == 'f') {
/* backward or forward label */
label = asm_get_local_label_name(s1, n);
sym = asm_label_find(label);
sym = asm_label_find(s1, label);
if (*p == 'b') {
/* backward : find the last corresponding defined label */
if (sym && (!sym->c || elfsym(sym)->st_shndx == SHN_UNDEF))
@ -154,7 +161,7 @@ static void asm_expr_unary(TCCState *s1, ExprValue *pe)
/* forward */
if (!sym || (sym->c && elfsym(sym)->st_shndx != SHN_UNDEF)) {
/* 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;
@ -199,7 +206,7 @@ static void asm_expr_unary(TCCState *s1, ExprValue *pe)
break;
case '.':
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;
next();
break;
@ -207,7 +214,7 @@ static void asm_expr_unary(TCCState *s1, ExprValue *pe)
if (tok >= TOK_IDENT) {
ElfSym *esym;
/* 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);
if (esym && esym->st_shndx == SHN_ABS) {
/* 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 */
pe->v += esym1->st_value - esym2->st_value;
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
this actually makes the value PC-relative. */
pe->v += 0 - esym2->st_value;
@ -413,7 +420,7 @@ static Sym* asm_new_label1(TCCState *s1, int label, int is_local,
Sym *sym;
ElfSym *esym;
sym = asm_label_find(label);
sym = asm_label_find(s1, label);
if (sym) {
esym = elfsym(sym);
/* 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 {
new_label:
sym = asm_label_push(label);
sym = asm_label_push(s1, label);
}
if (!sym->c)
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)
{
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
@ -468,9 +475,9 @@ static Sym* set_symbol(TCCState *s1, int label)
static void use_section1(TCCState *s1, Section *sec)
{
tcc_state->cur_text_section->data_offset = ind;
tcc_state->cur_text_section = sec;
ind = tcc_state->cur_text_section->data_offset;
s1->cur_text_section->data_offset = ind;
s1->cur_text_section = sec;
ind = s1->cur_text_section->data_offset;
}
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)
{
Section *sec = find_section(s1, name);
sec->prev = tcc_state->cur_text_section;
sec->prev = s1->cur_text_section;
use_section1(s1, sec);
}
static void pop_section(TCCState *s1)
{
Section *prev = tcc_state->cur_text_section->prev;
Section *prev = s1->cur_text_section->prev;
if (!prev)
tcc_error(".popsection without .pushsection");
tcc_state->cur_text_section->prev = NULL;
s1->cur_text_section->prev = NULL;
use_section1(s1, prev);
}
@ -503,7 +510,7 @@ static void asm_parse_directive(TCCState *s1, int global)
uint8_t *ptr;
/* assembler directive */
sec = tcc_state->cur_text_section;
sec = s1->cur_text_section;
switch(tok) {
case TOK_ASMDIR_align:
case TOK_ASMDIR_balign:
@ -682,7 +689,7 @@ static void asm_parse_directive(TCCState *s1, int global)
n = e.v;
esym = elfsym(e.sym);
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");
n += esym->st_value;
}
@ -710,7 +717,7 @@ static void asm_parse_directive(TCCState *s1, int global)
do {
Sym *sym;
next();
sym = get_asm_sym(tok, NULL);
sym = get_asm_sym(s1, tok, NULL);
if (tok1 != TOK_ASMDIR_hidden)
sym->type.t &= ~VT_STATIC;
if (tok1 == TOK_ASMDIR_weak)
@ -806,7 +813,7 @@ static void asm_parse_directive(TCCState *s1, int global)
Sym *sym;
next();
sym = asm_label_find(tok);
sym = asm_label_find(s1, tok);
if (!sym) {
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;
next();
sym = get_asm_sym(tok, NULL);
sym = get_asm_sym(s1, tok, NULL);
next();
skip(',');
if (tok == TOK_STR) {
@ -894,7 +901,7 @@ static void asm_parse_directive(TCCState *s1, int global)
next();
}
}
last_text_section = tcc_state->cur_text_section;
last_text_section = s1->cur_text_section;
if (tok1 == TOK_ASMDIR_section)
use_section(s1, sname);
else
@ -903,8 +910,8 @@ static void asm_parse_directive(TCCState *s1, int global)
1. new_section normally acts for GCC compatibility and
sets alignment to PTR_SIZE. The assembler behaves different. */
if (old_nb_section != s1->nb_sections) {
tcc_state->cur_text_section->sh_addralign = 1;
tcc_state->cur_text_section->sh_flags = flags;
s1->cur_text_section->sh_addralign = 1;
s1->cur_text_section->sh_flags = flags;
}
}
break;
@ -914,7 +921,7 @@ static void asm_parse_directive(TCCState *s1, int global)
next();
if (!last_text_section)
tcc_error("no previous section referenced");
sec = tcc_state->cur_text_section;
sec = s1->cur_text_section;
use_section1(s1, last_text_section);
last_text_section = sec;
}
@ -926,13 +933,11 @@ static void asm_parse_directive(TCCState *s1, int global)
case TOK_ASMDIR_code16:
{
next();
s1->seg_size = 16;
}
break;
case TOK_ASMDIR_code32:
{
next();
s1->seg_size = 32;
}
break;
/* TODO: Implement symvar support. FreeBSD >= 14 needs this */
@ -1015,11 +1020,11 @@ int tcc_assemble(TCCState *s1, int do_preprocess)
{
int ret;
/* default section is text */
tcc_state->cur_text_section = tcc_state->text_section;
ind = tcc_state->cur_text_section->data_offset;
s1->cur_text_section = s1->text_section;
ind = s1->cur_text_section->data_offset;
nocode_wanted = 0;
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;
}
@ -1187,7 +1192,7 @@ static void parse_asm_operands(ASMOperand *operands, int *nb_operands_ptr,
}
/* parse the GCC asm() instruction */
void asm_instr(void)
void asm_instr(TCCState *s1)
{
CString astr, *astr1;
@ -1262,11 +1267,11 @@ void asm_instr(void)
csym->r = LABEL_FORWARD;
}
next();
asmname = asm_get_prefix_name(tcc_state, "LG.",
asmname = asm_get_prefix_name(s1, "LG.",
++asmgoto_n);
if (!csym->c)
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;
if (tok != ',')
@ -1312,13 +1317,13 @@ void asm_instr(void)
/* We don't allow switching section within inline asm to
bleed out to surrounding code. */
sec = tcc_state->cur_text_section;
sec = s1->cur_text_section;
/* 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);
if (sec != tcc_state->cur_text_section) {
if (sec != s1->cur_text_section) {
tcc_warning("inline asm tries to change current section");
use_section1(tcc_state, sec);
use_section1(s1, sec);
}
/* 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;
int saved_nocode_wanted = nocode_wanted;
@ -1353,13 +1358,13 @@ void asm_global_instr(void)
#ifdef ASM_DEBUG
printf("asm_global: \"%s\"\n", (char *)astr->data);
#endif
tcc_state->cur_text_section = tcc_state->text_section;
ind = tcc_state->cur_text_section->data_offset;
s1->cur_text_section = s1->text_section;
ind = s1->cur_text_section->data_offset;
/* 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 */
next();

View file

@ -26,6 +26,8 @@
#define USING_GLOBALS
#include <tcc.h>
#define USING_GLOBALS
#include "cc/cc.h"
#include <tcc/memory.h>
#include "utils/string.h"
#include "token.h"
@ -408,7 +410,7 @@ ElfSym *elfsym(Sym *s)
{
if (!s || !s->c)
return NULL;
return &((ElfSym *)symtab_section->data)[s->c];
return &((ElfSym *)tcc_state->symtab_section->data)[s->c];
}
/* apply storage attributes to Elf symbol */
@ -435,23 +437,6 @@ void update_storage(Sym *sym)
if (sym_bind != old_sym_bind) {
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);
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 {
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 */
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
@ -5186,7 +5171,7 @@ void unary(void)
t = (LONG_SIZE == 8 ? VT_LLONG : VT_INT) | VT_LONG | VT_UNSIGNED;
goto push_tokc;
case TOK___FUNCTION__:
if (!gnu_ext)
if (!tcc_state->gnu_ext)
goto tok_identifier;
/* fall thru */
case TOK___FUNC__:
@ -5462,7 +5447,7 @@ void unary(void)
}
break;
case TOK_LAND:
if (!gnu_ext)
if (!tcc_state->gnu_ext)
goto tok_identifier;
next();
/* allow to take the address of a label */
@ -5598,13 +5583,6 @@ special_math_val:
if (r & VT_SYM) {
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)) {
vtop->c.i = s->enum_val;
}
@ -6035,7 +6013,7 @@ static void expr_cond(void)
if (tok == '?') {
next();
c = condition_3way();
g = (tok == ':' && gnu_ext);
g = (tok == ':' && tcc_state->gnu_ext);
tt = 0;
if (!g) {
if (c < 0) {
@ -6776,7 +6754,7 @@ again:
dynarray_add(&cur_switch->p, &cur_switch->n, cr);
t = cur_switch->sv.type.t;
cr->v1 = cr->v2 = value64(expr_const64(), t);
if (tok == TOK_DOTS && gnu_ext) {
if (tok == TOK_DOTS && tcc_state->gnu_ext) {
next();
cr->v2 = value64(expr_const64(), t);
if (case_cmp(cr->v2, cr->v1) < 0)
@ -6800,7 +6778,7 @@ again:
} else if (t == TOK_GOTO) {
vla_restore(cur_scope->vla.locorig);
if (tok == '*' && gnu_ext) {
if (tok == '*' && tcc_state->gnu_ext) {
/* computed goto */
next();
gexpr();
@ -6837,7 +6815,7 @@ again:
skip(';');
} else if (t == TOK_ASM1 || t == TOK_ASM2 || t == TOK_ASM3) {
asm_instr();
asm_instr(tcc_state);
} else {
if (tok == ':' && t >= TOK_UIDENT) {
@ -6954,11 +6932,7 @@ static void parse_init_elem(int expr_type)
(compound literals). */
if (((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST
&& ((vtop->r & (VT_SYM|VT_LVAL)) != (VT_SYM|VT_LVAL)
|| vtop->sym->v < SYM_FIRST_ANOM))
#ifdef TCC_TARGET_PE
|| ((vtop->r & VT_SYM) && vtop->sym->a.dllimport)
#endif
)
|| vtop->sym->v < SYM_FIRST_ANOM)))
tcc_error("initializer element is not constant");
break;
case EXPR_ANY:
@ -7047,7 +7021,7 @@ static int decl_designator(init_params *p, CType *type, unsigned long c,
if (flags & DIF_HAVE_ELEM)
goto no_designator;
if (gnu_ext && tok >= TOK_UIDENT) {
if (tcc_state->gnu_ext && tok >= TOK_UIDENT) {
l = tok, next();
if (tok == ':')
goto struct_field;
@ -7061,7 +7035,7 @@ static int decl_designator(init_params *p, CType *type, unsigned long c,
expect("array type");
next();
index = index_last = expr_const();
if (tok == TOK_DOTS && gnu_ext) {
if (tok == TOK_DOTS && tcc_state->gnu_ext) {
next();
index_last = expr_const();
}
@ -7093,7 +7067,7 @@ static int decl_designator(init_params *p, CType *type, unsigned long c,
if (!cur_field) {
if (tok == '=') {
next();
} else if (!gnu_ext) {
} else if (!tcc_state->gnu_ext) {
expect("=");
}
} else {
@ -7234,7 +7208,7 @@ static void init_putv(init_params *p, CType *type, unsigned long c)
continue;
if (rel->r_offset < esym->st_value)
break;
put_elf_reloca(symtab_section, sec,
put_elf_reloca(tcc_state->symtab_section, sec,
c + rel->r_offset - esym->st_value,
ELFW(R_TYPE)(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;
} else if (has_init) {
sec = tcc_state->data_section;
} else if (tcc_state->nocommon)
} else {
sec = tcc_state->bss_section;
}
if (sec) {
addr = section_add(sec, size, align);
} else {
addr = align; /* SHN_COMMON is special, symbol value is align */
sec = common_section;
}
addr = section_add(sec, size, align);
if (v) {
if (!sym) {
@ -7997,7 +7965,7 @@ static int decl(int l)
break;
if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
/* global asm block */
asm_global_instr();
asm_global_instr(tcc_state);
continue;
}
if (tok >= TOK_UIDENT) {
@ -8063,34 +8031,12 @@ static int decl(int l)
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();
/* parse one last attribute list, after asm label */
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 (l != VT_CONST)
tcc_error("cannot use local functions");

View file

@ -23,9 +23,12 @@
#endif /* HAVE_CONFIG_H */
#include <stdlib.h>
#include <ctype.h>
#define USING_GLOBALS
#include <tcc.h>
#define USING_GLOBALS
#include "cc/cc.h"
#include <tcc/path.h>
#include <tcc/memory.h>
#include "utils/string.h"
@ -1555,7 +1558,7 @@ void parse_define(void)
if (varg == TOK_DOTS) {
varg = TOK___VA_ARGS__;
is_vaargs = 1;
} else if (tok == TOK_DOTS && gnu_ext) {
} else if (tok == TOK_DOTS && tcc_state->gnu_ext) {
is_vaargs = 1;
next_nomacro();
}
@ -2066,7 +2069,7 @@ static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long
c = '\v';
break;
case 'e':
if (!gnu_ext)
if (!tcc_state->gnu_ext)
goto invalid_escape;
c = 27;
break;
@ -2357,7 +2360,7 @@ static void parse_number(const char *p)
/* XXX: should patch directly float number */
d = (double)bn[1] * 4294967296.0 + (double)bn[0];
d = ldexp(d, exp_val - frac_bits);
t = toup(ch);
t = toupper(ch);
if (t == 'F') {
ch = *p++;
tok = TOK_CFLOAT;
@ -2412,7 +2415,7 @@ static void parse_number(const char *p)
}
}
*q = '\0';
t = toup(ch);
t = toupper(ch);
errno = 0;
if (t == 'F') {
ch = *p++;
@ -2469,7 +2472,7 @@ static void parse_number(const char *p)
lcount = ucount = 0;
p1 = p;
for(;;) {
t = toup(ch);
t = toupper(ch);
if (t == 'L') {
if (lcount >= 2)
tcc_error("three 'l's in integer constant");
@ -2737,7 +2740,7 @@ maybe_newline:
&& !(parse_flags & PARSE_FLAG_ASM_FILE
/* 0xe+1 is 3 tokens in asm */
&& ((char*)tokcstr.data)[0] == '0'
&& toup(((char*)tokcstr.data)[1]) == 'X'))
&& toupper(((char*)tokcstr.data)[1]) == 'X'))
|| t == 'p' || t == 'P'))))
break;
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) {
/* special case for var arg macros : ## eats the ','
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];
while (str.str[--str.len] != ',')
;
@ -3305,7 +3308,7 @@ static int macro_subst_tok(
break;
/* special case for gcc var args: add an empty
var arg argument if it is omitted */
if (sa->type.t && gnu_ext)
if (sa->type.t && tcc_state->gnu_ext)
goto empty_arg;
tcc_error("macro '%s' used with too few args",
get_tok_str(v, 0));
@ -3554,8 +3557,6 @@ static void tcc_predefs(TCCState *s1, CString *cs, int is_asm)
putdef(cs, "__ASSEMBLER__");
if (s1->output_type == TCC_OUTPUT_PREPROCESS)
putdef(cs, "__TCC_PP__");
if (s1->output_type == TCC_OUTPUT_MEMORY)
putdef(cs, "__TCC_RUN__");
if (s1->char_is_unsigned)
putdef(cs, "__CHAR_UNSIGNED__");
if (s1->optimize > 0)
@ -3832,7 +3833,7 @@ static int pp_need_space(int a, int b)
/* maybe hex like 0x1e */
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 t;
}

View file

@ -81,14 +81,6 @@ void tcc_undefine_symbol(TCCState *s, const char *sym);
*/
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
* @{
*/
# define TCC_OUTPUT_MEMORY 1 /** output will be run in memory */
# define TCC_OUTPUT_EXE 2 /** executable file */
# define TCC_OUTPUT_OBJ 3 /** object file */
# define TCC_OUTPUT_PREPROCESS 5 /** only preprocess */
@ -117,35 +108,11 @@ int tcc_add_library_path(TCCState *s, const char *pathname);
*/
int tcc_add_library(TCCState *s, const char *libraryname);
/**
* @brief add a symbol to the compiled program.
*/
int tcc_add_symbol(TCCState *s, const char *name, const void *val);
/**
* @brief output an executable, library or object file.
*
* DO NOT call tcc_relocate() before.
*/
int tcc_output_file(TCCState *s, const char *filename);
/**
* @brief do all relocations (needed before using tcc_get_symbol()).
*/
int tcc_relocate(TCCState *s1);
/**
* @brief return symbol value or NULL if not found.
*/
void *tcc_get_symbol(TCCState *s, const char *name);
typedef void (TCCSymbolFunc)(void *ctx, const char *name, const void *val);
/**
* @brief list all (global) symbols and their values via 'symbol_cb()'.
*/
void tcc_list_symbols(TCCState *s, void *ctx, TCCSymbolFunc *symbol_cb);
/**
* @}
*/

View file

@ -57,12 +57,6 @@ extern long double strtold (const char *__nptr, char **__endptr);
#define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
#endif
/* -------------------------------------------- */
#ifdef CONFIG_TCC_PIE
# define CONFIG_TCC_PIC 1
#endif
/* ------------ path configuration ------------ */
#ifndef CONFIG_SYSROOT
@ -348,28 +342,7 @@ typedef struct Section {
#define TYPE_PARAM 4 /* type declares function parameter */
#define TYPE_NEST 8 /* nested call to post_type */
#define IO_BUF_SIZE 8192
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 */
#include <tcc/io.h>
/* used to record tokens */
typedef struct TokenString {
@ -436,24 +409,14 @@ typedef struct ASMOperand {
int is_label; /* for asm goto */
} 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 {
unsigned char verbose; /* if true, display some information during compilation */
unsigned char nostdinc; /* if true, no standard headers are added */
unsigned char nostdlib; /* if true, no standard libraries are added */
unsigned char nocommon; /* if true, do not use common symbols for .bss data */
unsigned char symbolic; /* if true, resolve symbols in the current module first */
unsigned char filetype; /* file type for compilation (NONE,C,ASM) */
unsigned char optimize; /* only to #define __OPTIMIZE__ */
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, ... */
/* C language options */
@ -464,7 +427,6 @@ struct TCCState {
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 gnu89_inline; /* treat 'extern inline' like 'static inline' */
unsigned char unwind_tables; /* create eh_frame section */
/* warning switches */
unsigned char warn_none;
@ -496,10 +458,7 @@ struct TCCState {
addr_t text_addr; /* address of text section */
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 *rpath; /* as specified on the command line (-Wl,-rpath=) */
char *entryname; /* "_start" unless set */
/* output type, see TCC_OUTPUT_XXX */
@ -573,47 +532,23 @@ struct TCCState {
/* predefined sections */
Section *text_section, *data_section, *rodata_section, *bss_section;
Section *common_section;
Section *cur_text_section; /* current section where function code is generated */
/* symbol section */
union { Section *symtab_section, *symtab; }; /* historical alias */
/* 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;
Section *symtab_section;
/* Is there a new undefined sym since last 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 */
ElfW_Rel *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 */
int total_idents;
int total_lines;
unsigned int total_bytes;
unsigned int total_output[4];
/* used by tcc_load_ldscript */
int fd, cc;
/* for warnings/errors for object files */
const char *current_filename;
@ -772,184 +707,6 @@ char *tcc_load_text(int fd);
/* for #pragma once */
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 ------------ */
#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);
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);
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);
/* 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++)
#ifndef ELF_OBJ_ONLY
int tcc_load_ldscript(TCCState *s1, int fd);
void tccelf_add_crtbegin(TCCState *s1);
void tccelf_add_crtend(TCCState *s1);
#endif
@ -1011,120 +764,7 @@ void tcc_add_runtime(TCCState *s1);
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 ------------ */
#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 TCC_SET_STATE(_tcc_error)
#define tcc_warning TCC_SET_STATE(_tcc_warning)

View file

@ -371,7 +371,6 @@ typedef struct
#define PT_TLS 7 /* Thread-local storage segment */
#define PT_NUM 8 /* Number of defined types */
#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_RELRO 0x6474e552 /* Read-only after relocation */
#define PT_LOSUNW 0x6ffffffa
@ -432,19 +431,6 @@ typedef struct
#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). */
#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_FINI 13 /* Address of termination function */
#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_REL 17 /* Address 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_32 1 /* Direct 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_GLOB_DAT 6 /* Create GOT entry */
#define R_386_JMP_SLOT 7 /* Create PLT entry */
#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_TLS_TPOFF 14 /* Offset in static TLS block */
#define R_386_TLS_IE 15 /* Address of GOT entry for static TLS
@ -896,17 +877,5 @@ typedef struct
/* Keep this the last entry. */
#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 */

View file

@ -14,7 +14,4 @@
# define ELF_START_ADDR 0x08048000
# define ELF_PAGE_SIZE 0x1000
# define PCRELATIVE_DLLPLT 0
# define RELOCATE_DLLPLT 1
#endif /* !TCC_I386_LINK_H */

View file

@ -17,7 +17,7 @@ typedef struct BufferedFile {
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 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 */

View file

@ -71,6 +71,7 @@ typedef struct COFFSectionHeader {
# define COFF_STYP_TEXT 0x020
# define COFF_STYP_DATA 0x040
# define COFF_STYP_BSS 0x080
# define COFF_STYP_RODATA 0x100 /** stupidos extension */
# define COFF_STYP_INFO 0x200
# define COFF_STYP_OVER 0x400
# define COFF_STYP_LIB 0x800
@ -103,6 +104,9 @@ typedef struct COFFSym {
int8_t numaux;
} COFFSym;
# define COFF_N_UNDEF 0
# define COFF_N_ABS -1
/**
* @}
*/

View file

@ -10,7 +10,6 @@
# define TCC_OPT_HELP_MORE 'm'
# define TCC_OPT_ARCHIVE 'a'
# define TCC_OPT_VERSION 'V'
# define TCC_OPT_PRINT_DIRS 'P'
typedef struct TCCOption {
const char *name;

View file

@ -22,7 +22,7 @@ typedef struct InlineFunc InlineFunc;
typedef struct TCCStrtab {
size_t len;
uint8_t *tab;
char *tab;
} TCCStrtab;
typedef struct TCCSymtab {
@ -41,6 +41,8 @@ typedef struct TCCSection {
char name[8]; /** section name */
int32_t flags;
int16_t secnum;
int16_t addralign;
size_t offset;
} TCCSection;
struct TCCState2 {
@ -89,8 +91,6 @@ struct TCCState2 {
uint32_t text_addr; /** address of text section */
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 *entryname; /** "_start" unless set */
@ -161,12 +161,7 @@ struct TCCState2 {
TCCSection *cur_text_section; /** current section where function code is generated */
/* symbol data */
TCCSymtab symtab;
/* exception handling */
TCCSection *eh_frame_section;
TCCSection *eh_frame_hdr_section;
uint32_t eh_start;
TCCSymtab *symtab;
/* benchmark info */
int total_idents;
@ -174,10 +169,6 @@ struct TCCState2 {
uint32_t total_bytes;
uint32_t total_output[4];
/* used by tcc_load_ldscript */
int fd;
int cc;
/* for warnings/errors for object files */
const char *current_filename;
};

53
libtcc/io.c Normal file
View 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);
}

View file

@ -29,6 +29,7 @@
#include <tcc/memory.h>
#include <tcc/object.h>
#include "utils/string.h"
#include "cc/cc.h"
/********************************************************/
/* global variables */
@ -64,9 +65,6 @@ char *tcc_load_text(int fd)
return buf;
}
/********************************************************/
/* memory management */
#ifdef _WIN32
# define realpath(file, buf) _fullpath(buf, file, 260)
#endif
@ -278,42 +276,6 @@ PUB_FUNC void _tcc_warning(const char *fmt, ...)
/********************************************************/
/* 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)
{
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;
}
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" */
void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
{
@ -419,22 +376,16 @@ TCCState *tcc_new(void)
#undef gnu_ext
s->gnu_ext = 1;
s->tcc_ext = 1;
s->nocommon = 1;
s->dollars_in_identifiers = 1; /*on by default like in gcc/clang*/
s->cversion = 199901; /* default unless -std=c11 is supplied */
s->warn_implicit_function_declaration = 1;
s->warn_discarded_qualifiers = 1;
s->ms_extensions = 1;
s->unwind_tables = 1;
#ifdef __CHAR_UNSIGNED__
s->char_is_unsigned = 1;
#endif
s->seg_size = 32;
#ifdef CONFIG_NEW_DTAGS
s->enable_new_dtags = 1;
#endif
s->ppfp = stdout;
/* might be used in error() before preprocess_start() */
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);
tcc_free(s1->tcc_lib_path);;
tcc_free(s1->rpath);
tcc_free(s1->entryname);
tcc_free(s1->outfile);
tcc_free(s1->deps_outfile);
@ -501,7 +451,7 @@ int tcc_set_output_type(TCCState *s, int output_type)
/* paths for crt objects */
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);
return 0;
}
@ -564,8 +514,6 @@ int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
default:
/* as GNU ld, consider it is an ld script if not recognized */
ret = tcc_load_ldscript(s1, fd);
if (ret < 0)
tcc_error_noabort("%s: unrecognized file type", filename);
break;
}
@ -660,6 +608,7 @@ int tcc_add_library(TCCState *s, const char *libraryname)
static const char * const libs[] = { "%s/lib%s.a", NULL };
const char * const *pp = libs;
int flags = s->filetype & AFF_WHOLE_ARCHIVE;
while (*pp) {
int ret = tcc_add_library_internal(s, *pp,
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]);
}
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)
{
tcc_free(s->tcc_lib_path);

View file

@ -8,6 +8,7 @@
#include <string.h>
#include <tcc.h>
#include "cc/cc.h"
#ifdef TCC_MEMORY_DEBUG
# undef tcc_free

View file

@ -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/archive.h>
#include <tcc/object/coff.h>

View file

@ -1,3 +1,6 @@
#include "utils/string.h"
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#ifdef HAVE_CONFIG_H
# include "config.h"
@ -7,6 +10,8 @@
#include <tcc/object/coff.h>
#include <tcc/state.h>
#define ALIGN_UP(val, alignment) ((val + alignment - 1) & -alignment)
#define COFF_DEFAULT_ENTRYNAME "_start"
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;
}
static void
coff_new_symtab(TCCState2 *s1)
{
TCCSymtab *symtab;
symtab = tcc_mallocz(sizeof(TCCSymtab));
}
void
coff_new(TCCState2 *s1)
{
@ -55,9 +52,12 @@ coff_new(TCCState2 *s1)
s1->text_section = coff_new_section(s1, ".text", COFF_STYP_TEXT);
s1->data_section = coff_new_section(s1, ".data", COFF_STYP_DATA);
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
@ -71,6 +71,218 @@ coff_delete(TCCState2 *s1)
}
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

View file

@ -54,7 +54,6 @@ enum {
OPTION_include,
OPTION_nostdinc,
OPTION_nostdlib,
OPTION_print_search_dirs,
OPTION_w,
OPTION_E,
OPTION_M,
@ -100,7 +99,6 @@ static const TCCOption options[] = {
{"include", OPTION_include, TCC_OPTION_HAS_ARG},
{"nostdinc", OPTION_nostdinc, 0},
{"nostdlib", OPTION_nostdlib, 0},
{"print-search-dirs", OPTION_print_search_dirs, 0},
{"w", OPTION_w, 0},
{"E", OPTION_E, 0},
{"M", OPTION_M, 0},
@ -141,13 +139,11 @@ static const Flag options_W[] = {
static const Flag options_f[] = {
{offsetof(TCCState, char_is_unsigned), 0, "unsigned-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, ms_extensions), 0, "ms-extensions"},
{offsetof(TCCState, dollars_in_identifiers), 0, "dollars-in-identifiers"},
{offsetof(TCCState, reverse_funcargs), 0, "reverse-funcargs"},
{offsetof(TCCState, gnu89_inline), 0, "gnu89-inline"},
{offsetof(TCCState, unwind_tables), 0, "asynchronous-unwind-tables"},
{0, 0, NULL}
};
@ -333,25 +329,23 @@ set_linker(TCCState *s, const char *option)
s->text_addr = strtoull(p, &end, 16);
s->has_text_addr = 1;
} else if (link_option(option, "oformat=", &p)) {
if (strstart("elf32-", &p)) {
s->output_format = TCC_OUTPUT_FORMAT_ELF;
} else if (link_arg("binary", p)) {
if (link_arg("binary", p))
{
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;
#endif
} else
}
else
{
goto err;
}
} else if (link_option(option, "as-needed", &p)) {
ignoring = 1;
} else if (link_option(option, "O", &p)) {
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)) {
s->section_align = strtoul(p, &end, 16);
} else if (ret = link_option(option, "?whole-archive", &p), ret) {
@ -717,9 +711,6 @@ reparse:
case OPTION_O:
s->optimize = atoi(optarg);
break;
case OPTION_print_search_dirs:
x = TCC_OPT_PRINT_DIRS;
goto extra_action;
case OPTION_ar:
x = TCC_OPT_ARCHIVE;
extra_action:
@ -745,8 +736,6 @@ unsupported_option:
return (tool);
if (optind != noaction)
return (0);
if (s->verbose == 2)
return (TCC_OPT_PRINT_DIRS);
if (s->verbose)
return (TCC_OPT_VERSION);
return (TCC_OPT_HELP);

File diff suppressed because it is too large Load diff

View file

@ -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}.
@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
@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
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
Generate a statically linked executable (default is a shared linked
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
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
Use @var{fmt} as output format. The supported output formats are:
@table @code
@ -327,11 +311,6 @@ Binary image (only for executable output)
COFF output format (only for executable output for TMS320C67xx target)
@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/...
Set type for PE (Windows) executables.
@ -827,13 +806,9 @@ Currently, MMX opcodes are supported but not SSE ones.
@cindex ELF
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.
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
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
@ -841,8 +816,7 @@ options (@option{--start-group} and @option{--end-group}) are supported.
@section ELF file loader
TCC can load ELF object files, archives (.a files) and dynamic
libraries (.so).
TCC can load ELF object files and archives (.a files).
@section PE-i386 file generation
@cindex PE-i386

View file

@ -17,8 +17,9 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif /* HAVE_CONFIG_H */
#include <stdlib.h>
@ -50,7 +51,7 @@ static const char help_str[] =
" -E preprocess only\n"
"Linker options:\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"
" -Wl,-opt[=val] set linker option (see tcc -hh)\n"
"Misc. options:\n"
@ -89,14 +90,11 @@ static const char help_more_str[] =
" discarded-qualifiers warn when const is dropped (*)\n"
"-f[no-]... flags:\n"
" unsigned-char default char is unsigned\n"
" signed-char default char is signed\n"
" common use common section instead of bss\n"
" leading-underscore decorate extern symbols\n"
" signed-char default char is signed\n" " leading-underscore decorate extern symbols\n"
" ms-extensions allow anonymous struct in struct\n"
" dollars-in-identifiers allow '$' in C symbols\n"
" reverse-funcargs evaluate function arguments right to left\n"
" gnu89-inline 'extern inline' is like 'static inline'\n"
" asynchronous-unwind-tables create eh_frame section [on]\n"
"-m... target specific options:\n"
" ms-bitfields use MSVC bitfield layout\n"
"-Wl,... linker options:\n"
@ -104,7 +102,6 @@ static const char help_more_str[] =
" -[no-]whole-archive load lib(s) fully/only as needed\n"
" -image-base= -Ttext= set base address of 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"
" -init= -fini= -Map= -as-needed -O (ignored)\n"
"Predefined macros:\n"
@ -221,13 +218,6 @@ redo:
return tcc_tool_ar(s, argc, argv);
if (opt == TCC_OPT_VERSION)
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) {
tcc_error_noabort("no input files");
@ -279,8 +269,6 @@ redo:
if (s->output_type == TCC_OUTPUT_PREPROCESS) {
;
} else if (0 == ret) {
if (s->output_type == TCC_OUTPUT_MEMORY) {
} else {
if (!s->outfile)
s->outfile = default_outputfile(s, first_file);
if (!s->just_deps)
@ -288,7 +276,6 @@ redo:
if (!ret && s->gen_deps)
gen_makedeps(s, s->outfile, s->deps_outfile);
}
}
done = 1;
if (ret) {

View file

@ -27,6 +27,9 @@
* License along with this library; if not, write to the Free Software
* 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>
@ -361,6 +364,9 @@ const int _dowildcard = 1;
/* -------------------------------------------------------------- */
/* 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) {
char *res = tcc_malloc(strlen(s) * 2 + 1);