WIP replace ELF part with COFF
This commit is contained in:
parent
c5d1e40ebe
commit
5a54c79520
22 changed files with 1799 additions and 1400 deletions
13
RELICENSING
13
RELICENSING
|
@ -28,26 +28,21 @@
|
||||||
Author (name) I agree (YES/NO) Files/Features (optional)
|
Author (name) I agree (YES/NO) Files/Features (optional)
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
Adam Sampson YES makefiles
|
Adam Sampson YES makefiles
|
||||||
Daniel Glöckner NO arm-gen.c
|
Daniel Glöckner YES
|
||||||
Daniel Glöckner YES not arm-gen.c
|
|
||||||
Danny Milosavljevic YES arm-asm.c riscv64-asm.c
|
|
||||||
Edmund Grimley Evans YES arm64
|
|
||||||
Fabrice Bellard YES original author
|
Fabrice Bellard YES original author
|
||||||
Frédéric Féret YES x86 64/16 bit asm
|
Frédéric Féret YES x86 64/16 bit asm
|
||||||
grischka YES tccpe.c
|
grischka YES tccpe.c
|
||||||
Henry Kroll YES
|
Henry Kroll YES
|
||||||
Herman ten Brugge YES
|
Herman ten Brugge YES
|
||||||
Joe Soroka YES
|
Joe Soroka YES
|
||||||
Kirill Smelkov YES
|
Kirill Smelkov YES
|
||||||
mingodad YES
|
mingodad YES
|
||||||
Pip Cet YES
|
Pip Cet YES
|
||||||
Shinichiro Hamaji YES x86_64-gen.c
|
|
||||||
Steffen Nurpmeso YES
|
Steffen Nurpmeso YES
|
||||||
Vincent Lefèvre YES
|
Vincent Lefèvre YES
|
||||||
Thomas Preud'homme YES arm-gen.c
|
|
||||||
Timo VJ Lähde (Timppa) ? tiny_libmaker.c
|
Timo VJ Lähde (Timppa) ? tiny_libmaker.c
|
||||||
TK ? tcccoff.c c67-gen.c
|
TK ? tcccoff.c
|
||||||
Tyge Løvset YES tgmath.h, Windows tcc_libm.h math.h
|
Tyge Løvset YES tgmath.h
|
||||||
Urs Janssen YES
|
Urs Janssen YES
|
||||||
waddlesplash YES
|
waddlesplash YES
|
||||||
Christian Jullien YES Windows Cygwin build and tests
|
Christian Jullien YES Windows Cygwin build and tests
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
noinst_LIBRARIES = libtcc.a
|
noinst_LIBRARIES = libtcc.a
|
||||||
libtcc_a_SOURCES = libtcc.c option.c path.c io.c memory.c \
|
libtcc_a_SOURCES = libtcc.c option.c path.c io.c memory.c \
|
||||||
cc/tccpp.c cc/tccgen.c \
|
cc/tccpp.c cc/tccgen.c \
|
||||||
cc/tccasm.c tccelf.c \
|
cc/tccasm.c \
|
||||||
cc/i386/gen.c cc/i386/link.c \
|
cc/i386/gen.c cc/i386/link.c \
|
||||||
cc/i386/asm.c tcccoff.c
|
cc/i386/asm.c object/coff.c object/archive.c object.c
|
||||||
libtcc_a_CPPFLAGS = -I$(top_srcdir) -I$(srcdir) -I$(srcdir)/include
|
libtcc_a_CPPFLAGS = -I$(top_srcdir) -I$(srcdir) -I$(srcdir)/include
|
|
@ -1,6 +1,7 @@
|
||||||
#ifndef TCC_CC_H
|
#ifndef TCC_CC_H
|
||||||
# define TCC_CC_H
|
# define TCC_CC_H
|
||||||
|
|
||||||
|
#include "tcc/state.h"
|
||||||
# include <tcc.h>
|
# include <tcc.h>
|
||||||
|
|
||||||
/* ------------ tccpp.c ------------ */
|
/* ------------ tccpp.c ------------ */
|
||||||
|
@ -122,14 +123,12 @@ int ieee_finite(double d);
|
||||||
int exact_log2p1(int i);
|
int exact_log2p1(int i);
|
||||||
void test_lvalue(void);
|
void test_lvalue(void);
|
||||||
|
|
||||||
ElfSym *elfsym(Sym *);
|
COFFSym *coffsym(Sym *);
|
||||||
void update_storage(Sym *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_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);
|
void put_extern_sym(Sym *sym, TCCSection *section, addr_t value, unsigned long size);
|
||||||
#if PTR_SIZE == 4
|
void greloc(TCCSection *s, Sym *sym, unsigned long offset, int type);
|
||||||
void greloc(Section *s, Sym *sym, unsigned long offset, int type);
|
void greloca(TCCSection *s, Sym *sym, unsigned long offset, int type, addr_t addend);
|
||||||
#endif
|
|
||||||
void greloca(Section *s, Sym *sym, unsigned long offset, int type, addr_t addend);
|
|
||||||
|
|
||||||
void sym_free(Sym *sym);
|
void sym_free(Sym *sym);
|
||||||
Sym *sym_push(int v, CType *type, int r, int c);
|
Sym *sym_push(int v, CType *type, int r, int c);
|
||||||
|
@ -156,9 +155,7 @@ void vrott(int n);
|
||||||
void vrotb(int n);
|
void vrotb(int n);
|
||||||
void vrev(int n);
|
void vrev(int n);
|
||||||
void vpop(void);
|
void vpop(void);
|
||||||
#if PTR_SIZE == 4
|
|
||||||
void lexpand(void);
|
void lexpand(void);
|
||||||
#endif
|
|
||||||
void save_reg(int r);
|
void save_reg(int r);
|
||||||
void save_reg_upstack(int r, int n);
|
void save_reg_upstack(int r, int n);
|
||||||
int get_reg(int rc);
|
int get_reg(int rc);
|
||||||
|
@ -181,13 +178,12 @@ int expr_const(void);
|
||||||
/* ------------ xxx-link.c ------------ */
|
/* ------------ xxx-link.c ------------ */
|
||||||
|
|
||||||
#if !defined ELF_OBJ_ONLY
|
#if !defined ELF_OBJ_ONLY
|
||||||
int code_reloc (int reloc_type);
|
|
||||||
#define NEED_RELOC_TYPE
|
#define NEED_RELOC_TYPE
|
||||||
|
|
||||||
#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);
|
||||||
|
*/
|
||||||
|
|
||||||
/* ------------ xxx-gen.c ------------ */
|
/* ------------ xxx-gen.c ------------ */
|
||||||
extern const char * const target_machine_defs;
|
extern const char * const target_machine_defs;
|
||||||
|
@ -269,7 +265,12 @@ 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_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);
|
void asm_clobber(uint8_t *clobber_regs, const char *str);
|
||||||
|
|
||||||
#define ST_ASM_SET 0x04
|
/** XXX: fixme */
|
||||||
|
/* Symbol visibility specification encoded in the st_other field. */
|
||||||
|
#define STV_DEFAULT 0 /* Default symbol visibility rules */
|
||||||
|
#define STV_INTERNAL 1 /* Processor specific hidden class */
|
||||||
|
#define STV_HIDDEN 2 /* Sym unavailable in other modules */
|
||||||
|
#define STV_PROTECTED 3 /* Not preemptible, not exported */
|
||||||
|
|
||||||
|
|
||||||
#endif /* !TCC_CC_H */
|
#endif /* !TCC_CC_H */
|
|
@ -19,6 +19,7 @@
|
||||||
* 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 "tcc/object/coff.h"
|
||||||
#ifndef HAVE_CONFIG_H
|
#ifndef HAVE_CONFIG_H
|
||||||
# include "config.h"
|
# include "config.h"
|
||||||
#endif /* HAVE_CONFIG_H */
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
@ -27,7 +28,7 @@
|
||||||
#include "tcc.h"
|
#include "tcc.h"
|
||||||
#define USING_GLOBALS
|
#define USING_GLOBALS
|
||||||
#include "cc/cc.h"
|
#include "cc/cc.h"
|
||||||
#include "cC/token.h"
|
#include "cc/token.h"
|
||||||
|
|
||||||
#define MAX_OPERANDS 3
|
#define MAX_OPERANDS 3
|
||||||
|
|
||||||
|
@ -403,15 +404,20 @@ void gen_expr32(ExprValue *pe)
|
||||||
static void gen_disp32(ExprValue *pe)
|
static void gen_disp32(ExprValue *pe)
|
||||||
{
|
{
|
||||||
Sym *sym = pe->sym;
|
Sym *sym = pe->sym;
|
||||||
ElfSym *esym = elfsym(sym);
|
COFFSym *csym = coffsym(sym);
|
||||||
if (esym && esym->st_shndx == tcc_state->cur_text_section->sh_num) {
|
|
||||||
|
if (csym && csym->scnum == tcc_state->cur_text_section->secnum)
|
||||||
|
{
|
||||||
/* same section: we can output an absolute value. Note
|
/* same section: we can output an absolute value. Note
|
||||||
that the TCC compiler behaves differently here because
|
that the TCC compiler behaves differently here because
|
||||||
it always outputs a relocation to ease (future) code
|
it always outputs a relocation to ease (future) code
|
||||||
elimination in the linker */
|
elimination in the linker */
|
||||||
gen_le32(pe->v + esym->st_value - ind - 4);
|
gen_le32(pe->v + csym->value - ind - 4);
|
||||||
} else {
|
}
|
||||||
if (sym && sym->type.t == VT_VOID) {
|
else
|
||||||
|
{
|
||||||
|
if (sym && sym->type.t == VT_VOID)
|
||||||
|
{
|
||||||
sym->type.t = VT_FUNC;
|
sym->type.t = VT_FUNC;
|
||||||
sym->type.ref = NULL;
|
sym->type.ref = NULL;
|
||||||
}
|
}
|
||||||
|
@ -809,30 +815,42 @@ again:
|
||||||
}
|
}
|
||||||
if (pa->instr_type & OPC_B)
|
if (pa->instr_type & OPC_B)
|
||||||
v += s >= 1;
|
v += s >= 1;
|
||||||
if (nb_ops == 1 && pa->op_type[0] == OPT_DISP8) {
|
if (nb_ops == 1 && pa->op_type[0] == OPT_DISP8)
|
||||||
ElfSym *esym;
|
{
|
||||||
|
COFFSym *csym;
|
||||||
int jmp_disp;
|
int jmp_disp;
|
||||||
|
|
||||||
/* see if we can really generate the jump with a byte offset */
|
/* see if we can really generate the jump with a byte offset */
|
||||||
esym = elfsym(ops[0].e.sym);
|
csym = coffsym(ops[0].e.sym);
|
||||||
if (!esym || esym->st_shndx != tcc_state->cur_text_section->sh_num)
|
if (!csym || csym->scnum != tcc_state->cur_text_section->secnum)
|
||||||
|
{
|
||||||
goto no_short_jump;
|
goto no_short_jump;
|
||||||
jmp_disp = ops[0].e.v + esym->st_value - ind - 2 - (v >= 0xff);
|
}
|
||||||
if (jmp_disp == (int8_t)jmp_disp) {
|
jmp_disp = ops[0].e.v + csym->value - ind - 2 - (v >= 0xff);
|
||||||
|
if (jmp_disp == (int8_t)jmp_disp)
|
||||||
|
{
|
||||||
/* OK to generate jump */
|
/* OK to generate jump */
|
||||||
ops[0].e.sym = 0;
|
ops[0].e.sym = 0;
|
||||||
ops[0].e.v = jmp_disp;
|
ops[0].e.v = jmp_disp;
|
||||||
op_type[0] = OP_IM8S;
|
op_type[0] = OP_IM8S;
|
||||||
} else {
|
}
|
||||||
no_short_jump:
|
else
|
||||||
/* long jump will be allowed. need to modify the
|
{
|
||||||
opcode slightly */
|
no_short_jump:
|
||||||
if (v == 0xeb) /* jmp */
|
/* long jump will be allowed. need to modify the
|
||||||
v = 0xe9;
|
opcode slightly */
|
||||||
else if (v == 0x70) /* jcc */
|
if (v == 0xeb) /* jmp */
|
||||||
v += 0x0f10;
|
{
|
||||||
else
|
v = 0xe9;
|
||||||
tcc_error("invalid displacement");
|
}
|
||||||
|
else if (v == 0x70) /* jcc */
|
||||||
|
{
|
||||||
|
v += 0x0f10;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tcc_error("invalid displacement");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (OPCT_IS(pa->instr_type, OPC_TEST))
|
if (OPCT_IS(pa->instr_type, OPC_TEST))
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
* 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 "tcc/object/coff.h"
|
||||||
#define USING_GLOBALS
|
#define USING_GLOBALS
|
||||||
#include <tcc.h>
|
#include <tcc.h>
|
||||||
#include "cc/token.h"
|
#include "cc/token.h"
|
||||||
|
@ -44,16 +45,23 @@ static unsigned long func_sub_sp_offset;
|
||||||
static int func_ret_sub;
|
static int func_ret_sub;
|
||||||
|
|
||||||
/* XXX: make it faster ? */
|
/* XXX: make it faster ? */
|
||||||
void g(int c)
|
void
|
||||||
|
g(int c)
|
||||||
{
|
{
|
||||||
int ind1;
|
int ind1;
|
||||||
if (nocode_wanted)
|
|
||||||
return;
|
if (nocode_wanted)
|
||||||
ind1 = ind + 1;
|
{
|
||||||
if (ind1 > tcc_state->cur_text_section->data_allocated)
|
return;
|
||||||
section_realloc(tcc_state->cur_text_section, ind1);
|
}
|
||||||
tcc_state->cur_text_section->data[ind] = c;
|
|
||||||
ind = ind1;
|
ind1 = ind + 1;
|
||||||
|
if (ind1 > tcc_state->cur_text_section->data_allocated)
|
||||||
|
{
|
||||||
|
coff_section_realloc(tcc_state->cur_text_section, ind1);
|
||||||
|
}
|
||||||
|
tcc_state->cur_text_section->data[ind] = c;
|
||||||
|
ind = ind1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void o(unsigned int c)
|
void o(unsigned int c)
|
||||||
|
@ -111,18 +119,23 @@ void gen_fill_nops(int bytes)
|
||||||
#define gjmp2(instr,lbl) oad(instr,lbl)
|
#define gjmp2(instr,lbl) oad(instr,lbl)
|
||||||
|
|
||||||
/* output constant with relocation if 'r & VT_SYM' is true */
|
/* output constant with relocation if 'r & VT_SYM' is true */
|
||||||
void gen_addr32(int r, Sym *sym, int c)
|
void
|
||||||
|
gen_addr32(int r, Sym *sym, int c)
|
||||||
{
|
{
|
||||||
if (r & VT_SYM)
|
if (r & VT_SYM)
|
||||||
greloc(tcc_state->cur_text_section, sym, ind, R_386_32);
|
{
|
||||||
gen_le32(c);
|
greloc(tcc_state->cur_text_section, sym, ind, COFF_R_DIR32);
|
||||||
|
}
|
||||||
|
gen_le32(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gen_addrpc32(int r, Sym *sym, int c)
|
void gen_addrpc32(int r, Sym *sym, int c)
|
||||||
{
|
{
|
||||||
if (r & VT_SYM)
|
if (r & VT_SYM)
|
||||||
greloc(tcc_state->cur_text_section, sym, ind, R_386_PC32);
|
{
|
||||||
gen_le32(c - 4);
|
greloc(tcc_state->cur_text_section, sym, ind, COFF_R_PCRLONG);
|
||||||
|
}
|
||||||
|
gen_le32(c - 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* generate a modrm reference. 'op_reg' contains the additional 3
|
/* generate a modrm reference. 'op_reg' contains the additional 3
|
||||||
|
@ -272,18 +285,22 @@ static void gadd_sp(int val)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 'is_jmp' is '1' if it is a jump */
|
/* 'is_jmp' is '1' if it is a jump */
|
||||||
static void gcall_or_jmp(int is_jmp)
|
static void
|
||||||
|
gcall_or_jmp(int is_jmp)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST && (vtop->r & VT_SYM)) {
|
if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST && (vtop->r & VT_SYM))
|
||||||
/* constant and relocation case */
|
{
|
||||||
greloc(tcc_state->cur_text_section, vtop->sym, ind + 1, R_386_PC32);
|
/* constant and relocation case */
|
||||||
oad(0xe8 + is_jmp, vtop->c.i - 4); /* call/jmp im */
|
greloc(tcc_state->cur_text_section, vtop->sym, ind + 1, COFF_R_PCRLONG);
|
||||||
} else {
|
oad(0xe8 + is_jmp, vtop->c.i - 4); /* call/jmp im */
|
||||||
/* otherwise, indirect call */
|
}
|
||||||
r = gv(RC_INT);
|
else
|
||||||
o(0xff); /* call/jmp *r */
|
{
|
||||||
o(0xd0 + r + (is_jmp << 4));
|
/* otherwise, indirect call */
|
||||||
|
r = gv(RC_INT);
|
||||||
|
o(0xff); /* call/jmp *r */
|
||||||
|
o(0xd0 + r + (is_jmp << 4));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -938,19 +955,6 @@ void gen_cvt_csti(int t)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* increment tcov counter */
|
|
||||||
void gen_increment_tcov (SValue *sv)
|
|
||||||
{
|
|
||||||
o(0x0583); /* addl $1, xxx */
|
|
||||||
greloc(tcc_state->cur_text_section, sv->sym, ind, R_386_32);
|
|
||||||
gen_le32(0);
|
|
||||||
o(1);
|
|
||||||
o(0x1583); /* addcl $0, xxx */
|
|
||||||
greloc(tcc_state->cur_text_section, sv->sym, ind, R_386_32);
|
|
||||||
gen_le32(4);
|
|
||||||
g(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* computed goto support */
|
/* computed goto support */
|
||||||
void ggoto(void)
|
void ggoto(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,33 +1,7 @@
|
||||||
#include <tcc.h>
|
#include <tcc.h>
|
||||||
#include "cc/cc.h"
|
#include "cc/cc.h"
|
||||||
|
|
||||||
#ifdef NEED_RELOC_TYPE
|
#if 0
|
||||||
/* Returns 1 for a code relocation, 0 for a data relocation. For unknown
|
|
||||||
relocations, returns -1. */
|
|
||||||
int code_reloc (int reloc_type)
|
|
||||||
{
|
|
||||||
switch (reloc_type) {
|
|
||||||
case R_386_RELATIVE:
|
|
||||||
case R_386_16:
|
|
||||||
case R_386_32:
|
|
||||||
case R_386_GLOB_DAT:
|
|
||||||
case R_386_COPY:
|
|
||||||
case R_386_TLS_GD:
|
|
||||||
case R_386_TLS_LDM:
|
|
||||||
case R_386_TLS_LDO_32:
|
|
||||||
case R_386_TLS_LE:
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
case R_386_PC16:
|
|
||||||
case R_386_PC32:
|
|
||||||
case R_386_JMP_SLOT:
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#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)
|
||||||
{
|
{
|
||||||
int sym_index;
|
int sym_index;
|
||||||
|
@ -142,3 +116,4 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
1861
libtcc/cc/tccasm.c
1861
libtcc/cc/tccasm.c
File diff suppressed because it is too large
Load diff
|
@ -18,6 +18,8 @@
|
||||||
* 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 "tcc/object/coff.h"
|
||||||
|
#include "tcc/state.h"
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
# include "config.h"
|
# include "config.h"
|
||||||
#endif /* HAVE_CONFIG_H */
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
@ -128,7 +130,7 @@ static struct scope {
|
||||||
} *cur_scope, *loop_scope, *root_scope;
|
} *cur_scope, *loop_scope, *root_scope;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Section *sec;
|
TCCSection *sec;
|
||||||
int local_offset;
|
int local_offset;
|
||||||
Sym *flex_array_ref;
|
Sym *flex_array_ref;
|
||||||
} init_params;
|
} init_params;
|
||||||
|
@ -406,117 +408,153 @@ void tccgen_finish(TCCState *s1)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
ElfSym *elfsym(Sym *s)
|
COFFSym *
|
||||||
|
coffsym(Sym *s)
|
||||||
{
|
{
|
||||||
if (!s || !s->c)
|
if (!s || !s->c)
|
||||||
return NULL;
|
{
|
||||||
return &((ElfSym *)tcc_state->symtab_section->data)[s->c];
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (&((COFFSym *)tcc_state->symtab->syms)[s->c]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* apply storage attributes to Elf symbol */
|
/* apply storage attributes to COFF symbol */
|
||||||
void update_storage(Sym *sym)
|
void
|
||||||
|
update_storage(Sym *sym)
|
||||||
{
|
{
|
||||||
ElfSym *esym;
|
COFFSym *csym;
|
||||||
int sym_bind, old_sym_bind;
|
int sym_bind;
|
||||||
|
|
||||||
esym = elfsym(sym);
|
csym = coffsym(sym);
|
||||||
if (!esym)
|
if (!csym) return;
|
||||||
return;
|
|
||||||
|
if (sym->a.visibility)
|
||||||
if (sym->a.visibility)
|
{
|
||||||
esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1))
|
/** XXX: visibility */
|
||||||
| sym->a.visibility;
|
if (sym->a.visibility == STV_HIDDEN)
|
||||||
|
{
|
||||||
if (sym->type.t & (VT_STATIC | VT_INLINE))
|
csym->sclass = COFF_C_HIDDEN;
|
||||||
sym_bind = STB_LOCAL;
|
}
|
||||||
else if (sym->a.weak)
|
else if (sym->a.visibility == STV_DEFAULT)
|
||||||
sym_bind = STB_WEAK;
|
{
|
||||||
else
|
csym->sclass = COFF_C_EXT;
|
||||||
sym_bind = STB_GLOBAL;
|
}
|
||||||
old_sym_bind = ELFW(ST_BIND)(esym->st_info);
|
/*esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1))
|
||||||
if (sym_bind != old_sym_bind) {
|
| sym->a.visibility;*/
|
||||||
esym->st_info = ELFW(ST_INFO)(sym_bind, ELFW(ST_TYPE)(esym->st_info));
|
}
|
||||||
}
|
/** XXX: sym type */
|
||||||
|
if (sym->type.t & (VT_STATIC | VT_INLINE))
|
||||||
|
{
|
||||||
|
sym_bind = COFF_C_STAT;
|
||||||
|
/*sym_bind = STB_LOCAL;*/
|
||||||
|
}
|
||||||
|
else if (sym->a.weak)
|
||||||
|
{
|
||||||
|
sym_bind = COFF_C_ALIAS;
|
||||||
|
/* sym_bind = STB_WEAK;*/
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*sym_bind = STB_GLOBAL;*/
|
||||||
|
sym_bind = COFF_C_EXT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (csym->sclass != sym_bind)
|
||||||
|
{
|
||||||
|
csym->sclass = sym_bind;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
/* update sym->c so that it points to an external symbol in section
|
/* update sym->c so that it points to an external symbol in section
|
||||||
'section' with value 'value' */
|
'section' with value 'value' */
|
||||||
|
|
||||||
void put_extern_sym2(Sym *sym, int sh_num,
|
void
|
||||||
|
put_extern_sym2(Sym *sym, int sh_num,
|
||||||
addr_t value, unsigned long size,
|
addr_t value, unsigned long size,
|
||||||
int can_add_underscore)
|
int can_add_underscore)
|
||||||
{
|
{
|
||||||
int sym_type, sym_bind, info, other, t;
|
int sym_type, sym_bind, info, other, t;
|
||||||
ElfSym *esym;
|
COFFSym *csym;
|
||||||
const char *name;
|
const char *name;
|
||||||
char buf1[256];
|
char buf1[256];
|
||||||
|
|
||||||
if (!sym->c) {
|
if (!sym->c)
|
||||||
|
{
|
||||||
name = get_tok_str(sym->v, NULL);
|
name = get_tok_str(sym->v, NULL);
|
||||||
t = sym->type.t;
|
t = sym->type.t;
|
||||||
if ((t & VT_BTYPE) == VT_FUNC) {
|
if ((t & VT_BTYPE) == VT_FUNC)
|
||||||
sym_type = STT_FUNC;
|
{
|
||||||
} else if ((t & VT_BTYPE) == VT_VOID) {
|
/* sym_type = STT_FUNC;*/
|
||||||
sym_type = STT_NOTYPE;
|
sym_type = COFF_DT_FCN;
|
||||||
if ((t & (VT_BTYPE|VT_ASM_FUNC)) == VT_ASM_FUNC)
|
|
||||||
sym_type = STT_FUNC;
|
|
||||||
} else {
|
|
||||||
sym_type = STT_OBJECT;
|
|
||||||
}
|
}
|
||||||
|
else if ((t & VT_BTYPE) == VT_VOID)
|
||||||
|
{
|
||||||
|
sym_type = COFF_DT_NON; /* notype*/
|
||||||
|
if ((t & (VT_BTYPE|VT_ASM_FUNC)) == VT_ASM_FUNC)
|
||||||
|
{
|
||||||
|
/*sym_type = STT_FUNC;*/
|
||||||
|
sym_type = COFF_DT_FCN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/** XXX: sym_type = STT_OBJECT; */
|
||||||
|
}
|
||||||
|
|
||||||
if (t & (VT_STATIC | VT_INLINE))
|
if (t & (VT_STATIC | VT_INLINE))
|
||||||
sym_bind = STB_LOCAL;
|
{
|
||||||
|
sym_bind = COFF_C_STAT;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
sym_bind = STB_GLOBAL;
|
{
|
||||||
|
sym_bind = COFF_C_EXT;
|
||||||
|
}
|
||||||
other = 0;
|
other = 0;
|
||||||
|
|
||||||
#ifdef TCC_TARGET_PE
|
if (sym->asm_label)
|
||||||
if (sym_type == STT_FUNC && sym->type.ref) {
|
{
|
||||||
Sym *ref = sym->type.ref;
|
|
||||||
if (ref->a.nodecorate) {
|
|
||||||
can_add_underscore = 0;
|
|
||||||
}
|
|
||||||
if (ref->f.func_call == FUNC_STDCALL && can_add_underscore) {
|
|
||||||
sprintf(buf1, "_%s@%d", name, ref->f.func_args * PTR_SIZE);
|
|
||||||
name = buf1;
|
|
||||||
other |= ST_PE_STDCALL;
|
|
||||||
can_add_underscore = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (sym->asm_label) {
|
|
||||||
name = get_tok_str(sym->asm_label, NULL);
|
name = get_tok_str(sym->asm_label, NULL);
|
||||||
can_add_underscore = 0;
|
can_add_underscore = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tcc_state->leading_underscore && can_add_underscore) {
|
if (tcc_state->leading_underscore && can_add_underscore)
|
||||||
|
{
|
||||||
buf1[0] = '_';
|
buf1[0] = '_';
|
||||||
pstrcpy(buf1 + 1, sizeof(buf1) - 1, name);
|
pstrcpy(buf1 + 1, sizeof(buf1) - 1, name);
|
||||||
name = buf1;
|
name = buf1;
|
||||||
}
|
}
|
||||||
|
|
||||||
info = ELFW(ST_INFO)(sym_bind, sym_type);
|
sym->c = coff_add_sym(tcc_state, value, name, size, sh_num, sym_type, sym_bind);
|
||||||
sym->c = put_elf_sym(tcc_state->symtab_section, value, size, info, other, sh_num, name);
|
|
||||||
|
|
||||||
} else {
|
/** XXX: info = ELFW(ST_INFO)(sym_bind, sym_type);
|
||||||
esym = elfsym(sym);
|
sym->c = put_elf_sym(tcc_state->symtab_section, value, size, info, other, sh_num, name);*/
|
||||||
esym->st_value = value;
|
|
||||||
esym->st_size = size;
|
}
|
||||||
esym->st_shndx = sh_num;
|
else
|
||||||
|
{
|
||||||
|
csym = coffsym(sym);
|
||||||
|
csym->value = value;
|
||||||
|
csym->scnum = sh_num;
|
||||||
|
/** XXX: esym->st_size = size; */
|
||||||
}
|
}
|
||||||
update_storage(sym);
|
update_storage(sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
void put_extern_sym(Sym *sym, Section *s, addr_t value, unsigned long size)
|
void
|
||||||
|
put_extern_sym(Sym *sym, TCCSection *s, addr_t value, unsigned long size)
|
||||||
{
|
{
|
||||||
if (nocode_wanted && (NODATA_WANTED || (s && s == tcc_state->cur_text_section)))
|
if (nocode_wanted && (NODATA_WANTED || (s && s == tcc_state->cur_text_section)))
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
put_extern_sym2(sym, s ? s->sh_num : SHN_UNDEF, value, size, 1);
|
}
|
||||||
|
put_extern_sym2(sym, s ? s->secnum : COFF_N_UNDEF, value, size, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add a new relocation entry to symbol 'sym' in section 's' */
|
/* add a new relocation entry to symbol 'sym' in section 's' */
|
||||||
void greloca(Section *s, Sym *sym, unsigned long offset, int type,
|
void
|
||||||
|
greloca(TCCSection *s, Sym *sym, unsigned long offset, int type,
|
||||||
addr_t addend)
|
addr_t addend)
|
||||||
{
|
{
|
||||||
int c = 0;
|
int c = 0;
|
||||||
|
@ -531,15 +569,14 @@ 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(tcc_state->symtab_section, s, offset, type, c, addend);
|
coff_add_reloca(tcc_state, s, offset, type, c, addend);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if PTR_SIZE == 4
|
void
|
||||||
void greloc(Section *s, Sym *sym, unsigned long offset, int type)
|
greloc(TCCSection *s, Sym *sym, unsigned long offset, int type)
|
||||||
{
|
{
|
||||||
greloca(s, sym, offset, type, 0);
|
greloca(s, sym, offset, type, 0);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
/* symbol allocator */
|
/* symbol allocator */
|
||||||
|
@ -1040,7 +1077,8 @@ void vpushsym(CType *type, Sym *sym)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return a static symbol pointing to a section */
|
/* Return a static symbol pointing to a section */
|
||||||
Sym *get_sym_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
|
Sym *
|
||||||
|
get_sym_ref(CType *type, TCCSection *sec, unsigned long offset, unsigned long size)
|
||||||
{
|
{
|
||||||
int v;
|
int v;
|
||||||
Sym *sym;
|
Sym *sym;
|
||||||
|
@ -1053,7 +1091,8 @@ Sym *get_sym_ref(CType *type, Section *sec, unsigned long offset, unsigned long
|
||||||
}
|
}
|
||||||
|
|
||||||
/* push a reference to a section offset by adding a dummy symbol */
|
/* push a reference to a section offset by adding a dummy symbol */
|
||||||
static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
|
static void
|
||||||
|
vpush_ref(CType *type, TCCSection *sec, unsigned long offset, unsigned long size)
|
||||||
{
|
{
|
||||||
vpushsym(type, get_sym_ref(type, sec, offset, size));
|
vpushsym(type, get_sym_ref(type, sec, offset, size));
|
||||||
}
|
}
|
||||||
|
@ -1614,7 +1653,7 @@ int gv(int rc)
|
||||||
size = type_size(&vtop->type, &align);
|
size = type_size(&vtop->type, &align);
|
||||||
if (NODATA_WANTED)
|
if (NODATA_WANTED)
|
||||||
size = 0, align = 1;
|
size = 0, align = 1;
|
||||||
offset = section_add(p.sec, size, align);
|
offset = coff_section_add(p.sec, size, align);
|
||||||
vpush_ref(&vtop->type, p.sec, offset, size);
|
vpush_ref(&vtop->type, p.sec, offset, size);
|
||||||
vswap();
|
vswap();
|
||||||
init_putv(&p, &vtop->type, offset);
|
init_putv(&p, &vtop->type, offset);
|
||||||
|
@ -3547,7 +3586,7 @@ redo:
|
||||||
case TOK_SECTION2:
|
case TOK_SECTION2:
|
||||||
skip('(');
|
skip('(');
|
||||||
astr = parse_mult_str("section name")->data;
|
astr = parse_mult_str("section name")->data;
|
||||||
ad->section = find_section(tcc_state, astr);
|
ad->section = coff_find_section(tcc_state, astr);
|
||||||
skip(')');
|
skip(')');
|
||||||
break;
|
break;
|
||||||
case TOK_ALIAS1:
|
case TOK_ALIAS1:
|
||||||
|
@ -6974,8 +7013,10 @@ static void init_putz(init_params *p, unsigned long c, int size)
|
||||||
|
|
||||||
/* delete relocations for specified range c ... c + size. Unfortunatly
|
/* delete relocations for specified range c ... c + size. Unfortunatly
|
||||||
in very special cases, relocations may occur unordered */
|
in very special cases, relocations may occur unordered */
|
||||||
static void decl_design_delrels(Section *sec, int c, int size)
|
static void
|
||||||
|
decl_design_delrels(TCCSection *sec, int c, int size)
|
||||||
{
|
{
|
||||||
|
/** XXX: TODO
|
||||||
ElfW_Rel *rel, *rel2, *rel_end;
|
ElfW_Rel *rel, *rel2, *rel_end;
|
||||||
if (!sec || !sec->reloc)
|
if (!sec || !sec->reloc)
|
||||||
return;
|
return;
|
||||||
|
@ -6990,7 +7031,7 @@ static void decl_design_delrels(Section *sec, int c, int size)
|
||||||
++rel2;
|
++rel2;
|
||||||
}
|
}
|
||||||
++rel;
|
++rel;
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
static void decl_design_flex(init_params *p, Sym *ref, int index)
|
static void decl_design_flex(init_params *p, Sym *ref, int index)
|
||||||
|
@ -7135,92 +7176,104 @@ static int decl_designator(init_params *p, CType *type, unsigned long c,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* store a value or an expression directly in global data or in local array */
|
/* store a value or an expression directly in global data or in local array */
|
||||||
static void init_putv(init_params *p, CType *type, unsigned long c)
|
static void
|
||||||
|
init_putv(init_params *p, CType *type, unsigned long c)
|
||||||
{
|
{
|
||||||
int bt;
|
int bt;
|
||||||
void *ptr;
|
void *ptr;
|
||||||
CType dtype;
|
CType dtype;
|
||||||
int size, align;
|
int size, align;
|
||||||
Section *sec = p->sec;
|
TCCSection *sec = p->sec;
|
||||||
uint64_t val;
|
uint64_t val;
|
||||||
|
|
||||||
dtype = *type;
|
dtype = *type;
|
||||||
dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
|
dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
|
||||||
|
|
||||||
size = type_size(type, &align);
|
size = type_size(type, &align);
|
||||||
if (type->t & VT_BITFIELD)
|
if (type->t & VT_BITFIELD)
|
||||||
size = (BIT_POS(type->t) + BIT_SIZE(type->t) + 7) / 8;
|
{
|
||||||
init_assert(p, c + size);
|
size = (BIT_POS(type->t) + BIT_SIZE(type->t) + 7) / 8;
|
||||||
|
}
|
||||||
if (sec) {
|
init_assert(p, c + size);
|
||||||
/* XXX: not portable */
|
|
||||||
/* XXX: generate error if incorrect relocation */
|
if (sec)
|
||||||
gen_assign_cast(&dtype);
|
{
|
||||||
bt = type->t & VT_BTYPE;
|
/* XXX: not portable */
|
||||||
|
/* XXX: generate error if incorrect relocation */
|
||||||
if ((vtop->r & VT_SYM)
|
gen_assign_cast(&dtype);
|
||||||
&& bt != VT_PTR
|
bt = type->t & VT_BTYPE;
|
||||||
&& (bt != (PTR_SIZE == 8 ? VT_LLONG : VT_INT)
|
|
||||||
|| (type->t & VT_BITFIELD))
|
if ((vtop->r & VT_SYM)
|
||||||
&& !((vtop->r & VT_CONST) && vtop->sym->v >= SYM_FIRST_ANOM)
|
&& bt != VT_PTR
|
||||||
)
|
&& (bt != (PTR_SIZE == 8 ? VT_LLONG : VT_INT)
|
||||||
tcc_error("initializer element is not computable at load time");
|
|| (type->t & VT_BITFIELD))
|
||||||
|
&& !((vtop->r & VT_CONST) && vtop->sym->v >= SYM_FIRST_ANOM))
|
||||||
if (NODATA_WANTED) {
|
{
|
||||||
vtop--;
|
tcc_error("initializer element is not computable at load time");
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ptr = sec->data + c;
|
|
||||||
val = vtop->c.i;
|
|
||||||
|
|
||||||
/* XXX: make code faster ? */
|
|
||||||
if ((vtop->r & (VT_SYM|VT_CONST)) == (VT_SYM|VT_CONST) &&
|
|
||||||
vtop->sym->v >= SYM_FIRST_ANOM &&
|
|
||||||
/* XXX This rejects compound literals like
|
|
||||||
'(void *){ptr}'. The problem is that '&sym' is
|
|
||||||
represented the same way, which would be ruled out
|
|
||||||
by the SYM_FIRST_ANOM check above, but also '"string"'
|
|
||||||
in 'char *p = "string"' is represented the same
|
|
||||||
with the type being VT_PTR and the symbol being an
|
|
||||||
anonymous one. That is, there's no difference in vtop
|
|
||||||
between '(void *){x}' and '&(void *){x}'. Ignore
|
|
||||||
pointer typed entities here. Hopefully no real code
|
|
||||||
will ever use compound literals with scalar type. */
|
|
||||||
(vtop->type.t & VT_BTYPE) != VT_PTR) {
|
|
||||||
/* These come from compound literals, memcpy stuff over. */
|
|
||||||
Section *ssec;
|
|
||||||
ElfSym *esym;
|
|
||||||
ElfW_Rel *rel;
|
|
||||||
esym = elfsym(vtop->sym);
|
|
||||||
ssec = tcc_state->sections[esym->st_shndx];
|
|
||||||
memmove (ptr, ssec->data + esym->st_value + (int)vtop->c.i, size);
|
|
||||||
if (ssec->reloc) {
|
|
||||||
/* We need to copy over all memory contents, and that
|
|
||||||
includes relocations. Use the fact that relocs are
|
|
||||||
created it order, so look from the end of relocs
|
|
||||||
until we hit one before the copied region. */
|
|
||||||
unsigned long relofs = ssec->reloc->data_offset;
|
|
||||||
while (relofs >= sizeof(*rel)) {
|
|
||||||
relofs -= sizeof(*rel);
|
|
||||||
rel = (ElfW_Rel*)(ssec->reloc->data + relofs);
|
|
||||||
if (rel->r_offset >= esym->st_value + size)
|
|
||||||
continue;
|
|
||||||
if (rel->r_offset < esym->st_value)
|
|
||||||
break;
|
|
||||||
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),
|
|
||||||
#if PTR_SIZE == 8
|
|
||||||
rel->r_addend
|
|
||||||
#else
|
|
||||||
0
|
|
||||||
#endif
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
if (NODATA_WANTED)
|
||||||
|
{
|
||||||
|
vtop--;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr = sec->data + c;
|
||||||
|
val = vtop->c.i;
|
||||||
|
|
||||||
|
/* XXX: make code faster ? */
|
||||||
|
if ((vtop->r & (VT_SYM|VT_CONST)) == (VT_SYM|VT_CONST)
|
||||||
|
&& vtop->sym->v >= SYM_FIRST_ANOM
|
||||||
|
/* XXX This rejects compound literals like
|
||||||
|
'(void *){ptr}'. The problem is that '&sym' is
|
||||||
|
represented the same way, which would be ruled out
|
||||||
|
by the SYM_FIRST_ANOM check above, but also '"string"'
|
||||||
|
in 'char *p = "string"' is represented the same
|
||||||
|
with the type being VT_PTR and the symbol being an
|
||||||
|
anonymous one. That is, there's no difference in vtop
|
||||||
|
between '(void *){x}' and '&(void *){x}'. Ignore
|
||||||
|
pointer typed entities here. Hopefully no real code
|
||||||
|
will ever use compound literals with scalar type. */
|
||||||
|
&& (vtop->type.t & VT_BTYPE) != VT_PTR)
|
||||||
|
{
|
||||||
|
/* These come from compound literals, memcpy stuff over. */
|
||||||
|
TCCSection *ssec;
|
||||||
|
COFFSym *csym;
|
||||||
|
COFFReloc *rel;
|
||||||
|
|
||||||
|
csym = coffsym(vtop->sym);
|
||||||
|
ssec = tcc_state->sections[csym->scnum];
|
||||||
|
memmove(ptr, ssec->data + csym->value + (int)vtop->c.i, size);
|
||||||
|
if (ssec->reloc)
|
||||||
|
{
|
||||||
|
/* We need to copy over all memory contents, and that
|
||||||
|
includes relocations. Use the fact that relocs are
|
||||||
|
created it order, so look from the end of relocs
|
||||||
|
until we hit one before the copied region. */
|
||||||
|
size_t reloc_idx = ssec->nreloc;
|
||||||
|
while (reloc_idx > 0)
|
||||||
|
{
|
||||||
|
reloc_idx--;
|
||||||
|
|
||||||
|
rel = &ssec->reloc[reloc_idx];
|
||||||
|
if (rel->vaddr >= csym->value + size)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rel->vaddr < csym->value)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
coff_add_reloca(tcc_state, sec,
|
||||||
|
c + rel->vaddr - csym->value,
|
||||||
|
rel->type, rel->symndx, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
if (type->t & VT_BITFIELD) {
|
if (type->t & VT_BITFIELD) {
|
||||||
int bit_pos, bit_size, bits, n;
|
int bit_pos, bit_size, bits, n;
|
||||||
unsigned char *p, v, m;
|
unsigned char *p, v, m;
|
||||||
|
@ -7285,29 +7338,15 @@ static void init_putv(init_params *p, CType *type, unsigned long c)
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#if PTR_SIZE == 8
|
|
||||||
/* intptr_t may need a reloc too, see tcctest.c:relocation_test() */
|
|
||||||
case VT_LLONG:
|
|
||||||
case VT_PTR:
|
|
||||||
if (vtop->r & VT_SYM)
|
|
||||||
greloca(sec, vtop->sym, c, R_DATA_PTR, val);
|
|
||||||
else
|
|
||||||
write64le(ptr, val);
|
|
||||||
break;
|
|
||||||
case VT_INT:
|
|
||||||
write32le(ptr, val);
|
|
||||||
break;
|
|
||||||
#else
|
|
||||||
case VT_LLONG:
|
case VT_LLONG:
|
||||||
write64le(ptr, val);
|
write64le(ptr, val);
|
||||||
break;
|
break;
|
||||||
case VT_PTR:
|
case VT_PTR:
|
||||||
case VT_INT:
|
case VT_INT:
|
||||||
if (vtop->r & VT_SYM)
|
if (vtop->r & VT_SYM)
|
||||||
greloc(sec, vtop->sym, c, R_DATA_PTR);
|
greloc(sec, vtop->sym, c, COFF_R_DIR32);
|
||||||
write32le(ptr, val);
|
write32le(ptr, val);
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
default:
|
default:
|
||||||
//tcc_internal_error("unexpected type");
|
//tcc_internal_error("unexpected type");
|
||||||
break;
|
break;
|
||||||
|
@ -7547,13 +7586,14 @@ static void decl_initializer(init_params *p, CType *type, unsigned long c, int f
|
||||||
are parsed. If 'v' is zero, then a reference to the new object
|
are parsed. If 'v' is zero, then a reference to the new object
|
||||||
is put in the value stack. If 'has_init' is 2, a special parsing
|
is put in the value stack. If 'has_init' is 2, a special parsing
|
||||||
is done to handle string constants. */
|
is done to handle string constants. */
|
||||||
static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
|
static void
|
||||||
|
decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
|
||||||
int has_init, int v, int global)
|
int has_init, int v, int global)
|
||||||
{
|
{
|
||||||
int size, align, addr;
|
int size, align, addr;
|
||||||
TokenString *init_str = NULL;
|
TokenString *init_str = NULL;
|
||||||
|
|
||||||
Section *sec;
|
TCCSection *sec;
|
||||||
Sym *flexible_array;
|
Sym *flexible_array;
|
||||||
Sym *sym;
|
Sym *sym;
|
||||||
int saved_nocode_wanted = nocode_wanted;
|
int saved_nocode_wanted = nocode_wanted;
|
||||||
|
@ -7687,7 +7727,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
|
||||||
}
|
}
|
||||||
patch_storage(sym, ad, type);
|
patch_storage(sym, ad, type);
|
||||||
/* we accept several definitions of the same global variable. */
|
/* we accept several definitions of the same global variable. */
|
||||||
if (!has_init && sym->c && elfsym(sym)->st_shndx != SHN_UNDEF)
|
if (!has_init && sym->c && coffsym(sym)->scnum != COFF_N_UNDEF)
|
||||||
goto no_alloc;
|
goto no_alloc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7706,7 +7746,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
|
||||||
sec = tcc_state->bss_section;
|
sec = tcc_state->bss_section;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
addr = section_add(sec, size, align);
|
addr = coff_section_add(sec, size, align);
|
||||||
|
|
||||||
if (v) {
|
if (v) {
|
||||||
if (!sym) {
|
if (!sym) {
|
||||||
|
@ -7814,7 +7854,7 @@ static void gen_function(Sym *sym)
|
||||||
|
|
||||||
ind = tcc_state->cur_text_section->data_offset;
|
ind = tcc_state->cur_text_section->data_offset;
|
||||||
if (sym->a.aligned) {
|
if (sym->a.aligned) {
|
||||||
size_t newoff = section_add(tcc_state->cur_text_section, 0,
|
size_t newoff = coff_section_add(tcc_state->cur_text_section, 0,
|
||||||
1 << (sym->a.aligned - 1));
|
1 << (sym->a.aligned - 1));
|
||||||
gen_fill_nops(newoff - ind);
|
gen_fill_nops(newoff - ind);
|
||||||
}
|
}
|
||||||
|
@ -7827,11 +7867,12 @@ static void gen_function(Sym *sym)
|
||||||
/* NOTE: we patch the symbol size later */
|
/* NOTE: we patch the symbol size later */
|
||||||
put_extern_sym(sym, tcc_state->cur_text_section, ind, 0);
|
put_extern_sym(sym, tcc_state->cur_text_section, ind, 0);
|
||||||
|
|
||||||
|
/** XXX: ???
|
||||||
if (sym->type.ref->f.func_ctor)
|
if (sym->type.ref->f.func_ctor)
|
||||||
add_array (tcc_state, ".init_array", sym->c);
|
add_array (tcc_state, ".init_array", sym->c);
|
||||||
if (sym->type.ref->f.func_dtor)
|
if (sym->type.ref->f.func_dtor)
|
||||||
add_array (tcc_state, ".fini_array", sym->c);
|
add_array (tcc_state, ".fini_array", sym->c);
|
||||||
|
*/
|
||||||
|
|
||||||
/* push a dummy symbol to enable local sym storage */
|
/* push a dummy symbol to enable local sym storage */
|
||||||
sym_push2(&local_stack, SYM_FIELD, 0, 0);
|
sym_push2(&local_stack, SYM_FIELD, 0, 0);
|
||||||
|
@ -7851,8 +7892,9 @@ static void gen_function(Sym *sym)
|
||||||
gfunc_epilog();
|
gfunc_epilog();
|
||||||
|
|
||||||
|
|
||||||
|
/** XXX: ??? */
|
||||||
/* patch symbol size */
|
/* patch symbol size */
|
||||||
elfsym(sym)->st_size = ind - func_ind;
|
/*coffsym(sym)->st_size = ind - func_ind;*/
|
||||||
|
|
||||||
tcc_state->cur_text_section->data_offset = ind;
|
tcc_state->cur_text_section->data_offset = ind;
|
||||||
local_scope = 0;
|
local_scope = 0;
|
||||||
|
@ -7944,7 +7986,7 @@ static int decl(int l)
|
||||||
CType type, btype;
|
CType type, btype;
|
||||||
Sym *sym;
|
Sym *sym;
|
||||||
AttributeDef ad, adbase;
|
AttributeDef ad, adbase;
|
||||||
ElfSym *esym;
|
COFFSym *csym;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
|
||||||
|
@ -8076,8 +8118,8 @@ static int decl(int l)
|
||||||
tcc_state->cur_text_section = ad.section;
|
tcc_state->cur_text_section = ad.section;
|
||||||
if (!tcc_state->cur_text_section)
|
if (!tcc_state->cur_text_section)
|
||||||
tcc_state->cur_text_section = tcc_state->text_section;
|
tcc_state->cur_text_section = tcc_state->text_section;
|
||||||
else if (tcc_state->cur_text_section->sh_num > tcc_state->bss_section->sh_num)
|
else if (tcc_state->cur_text_section->secnum > tcc_state->bss_section->secnum)
|
||||||
tcc_state->cur_text_section->sh_flags = tcc_state->text_section->sh_flags;
|
tcc_state->cur_text_section->flags = tcc_state->text_section->flags;
|
||||||
gen_function(sym);
|
gen_function(sym);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -8160,11 +8202,13 @@ static int decl(int l)
|
||||||
We only support the case where the base is already
|
We only support the case where the base is already
|
||||||
defined, otherwise we would need deferring to emit
|
defined, otherwise we would need deferring to emit
|
||||||
the aliases until the end of the compile unit. */
|
the aliases until the end of the compile unit. */
|
||||||
esym = elfsym(sym_find(ad.alias_target));
|
csym = coffsym(sym_find(ad.alias_target));
|
||||||
if (!esym)
|
if (!csym)
|
||||||
tcc_error("unsupported forward __alias__ attribute");
|
{
|
||||||
put_extern_sym2(sym_find(v), esym->st_shndx,
|
tcc_error("unsupported forward __alias__ attribute");
|
||||||
esym->st_value, esym->st_size, 1);
|
}
|
||||||
|
put_extern_sym2(sym_find(v), csym->scnum,
|
||||||
|
csym->value, /** XXX: esym->st_size */0, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (tok != ',') {
|
if (tok != ',') {
|
||||||
|
|
|
@ -118,7 +118,7 @@ extern long double strtold (const char *__nptr, char **__endptr);
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
#include <libtcc.h>
|
#include <libtcc.h>
|
||||||
#include <tcc/elf.h>
|
/*#include <tcc/elf.h>*/
|
||||||
#include <tcc/object/coff.h>
|
#include <tcc/object/coff.h>
|
||||||
#include <tcc/utils/cstring.h>
|
#include <tcc/utils/cstring.h>
|
||||||
|
|
||||||
|
@ -131,7 +131,6 @@ extern long double strtold (const char *__nptr, char **__endptr);
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
/* include the target specific definitions */
|
/* include the target specific definitions */
|
||||||
# include "tcc/i386/gen.h"
|
# include "tcc/i386/gen.h"
|
||||||
# include "tcc/i386/link.h"
|
|
||||||
|
|
||||||
# define ELFCLASSW ELFCLASS32
|
# define ELFCLASSW ELFCLASS32
|
||||||
# define ElfW(type) Elf##32##_##type
|
# define ElfW(type) Elf##32##_##type
|
||||||
|
@ -270,6 +269,7 @@ typedef struct Sym {
|
||||||
struct Sym *prev_tok; /* previous symbol for this token */
|
struct Sym *prev_tok; /* previous symbol for this token */
|
||||||
} Sym;
|
} Sym;
|
||||||
|
|
||||||
|
#if 0
|
||||||
/* section definition */
|
/* section definition */
|
||||||
typedef struct Section {
|
typedef struct Section {
|
||||||
unsigned long data_offset; /* current data offset */
|
unsigned long data_offset; /* current data offset */
|
||||||
|
@ -304,6 +304,8 @@ typedef struct Section {
|
||||||
char old_name[1]; /* section name */
|
char old_name[1]; /* section name */
|
||||||
} Section;
|
} Section;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/* -------------------------------------------------- */
|
/* -------------------------------------------------- */
|
||||||
|
|
||||||
#define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
|
#define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
|
||||||
|
@ -344,6 +346,8 @@ typedef struct Section {
|
||||||
|
|
||||||
#include <tcc/io.h>
|
#include <tcc/io.h>
|
||||||
|
|
||||||
|
#define WARN_ON 1
|
||||||
|
|
||||||
/* used to record tokens */
|
/* used to record tokens */
|
||||||
typedef struct TokenString {
|
typedef struct TokenString {
|
||||||
int *str;
|
int *str;
|
||||||
|
@ -362,7 +366,7 @@ typedef struct TokenString {
|
||||||
typedef struct AttributeDef {
|
typedef struct AttributeDef {
|
||||||
struct SymAttr a;
|
struct SymAttr a;
|
||||||
struct FuncAttr f;
|
struct FuncAttr f;
|
||||||
struct Section *section;
|
struct TCCSection *section;
|
||||||
Sym *cleanup_func;
|
Sym *cleanup_func;
|
||||||
int alias_target; /* token */
|
int alias_target; /* token */
|
||||||
int asm_label; /* associated asm label */
|
int asm_label; /* associated asm label */
|
||||||
|
@ -409,6 +413,7 @@ typedef struct ASMOperand {
|
||||||
int is_label; /* for asm goto */
|
int is_label; /* for asm goto */
|
||||||
} ASMOperand;
|
} ASMOperand;
|
||||||
|
|
||||||
|
#if 0
|
||||||
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 */
|
||||||
|
@ -562,6 +567,9 @@ struct TCCState {
|
||||||
char **argv;
|
char **argv;
|
||||||
CString linker_arg; /* collect -Wl options */
|
CString linker_arg; /* collect -Wl options */
|
||||||
};
|
};
|
||||||
|
#else
|
||||||
|
# include <tcc/state.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
struct filespec {
|
struct filespec {
|
||||||
char type;
|
char type;
|
||||||
|
@ -686,11 +694,7 @@ int tcc_add_file_internal(TCCState *s1, const char *filename, int flags);
|
||||||
#define AFF_TYPE_ASMPP 4
|
#define AFF_TYPE_ASMPP 4
|
||||||
#define AFF_TYPE_LIB 8
|
#define AFF_TYPE_LIB 8
|
||||||
#define AFF_TYPE_MASK (15 | AFF_TYPE_BIN)
|
#define AFF_TYPE_MASK (15 | AFF_TYPE_BIN)
|
||||||
/* values from tcc_object_type(...) */
|
|
||||||
#define AFF_BINTYPE_REL 1
|
|
||||||
#define AFF_BINTYPE_DYN 2
|
|
||||||
#define AFF_BINTYPE_AR 3
|
|
||||||
#define AFF_BINTYPE_COFF 4
|
|
||||||
|
|
||||||
/* return value of tcc_add_file_internal(): 0, -1, or FILE_NOT_FOUND */
|
/* return value of tcc_add_file_internal(): 0, -1, or FILE_NOT_FOUND */
|
||||||
#define FILE_NOT_FOUND -2
|
#define FILE_NOT_FOUND -2
|
||||||
|
@ -707,62 +711,36 @@ 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);
|
||||||
|
|
||||||
/* ------------ tccelf.c ------------ */
|
/* ------------- coff.c ------------- */
|
||||||
|
void coff_delete(TCCState *s1);
|
||||||
|
void coff_new(TCCState *s1);
|
||||||
|
void coff_section_realloc(TCCSection *sec, size_t new_size);
|
||||||
|
TCCSection *coff_find_section(TCCState *s1, const char *name);
|
||||||
|
void *coff_section_ptr_add(TCCSection *sec, size_t size);
|
||||||
|
int coff_add_sym(TCCState *s1, uint32_t value, const char *name, size_t size,
|
||||||
|
int16_t scnum, uint16_t type, int8_t sclass);
|
||||||
|
void coff_add_reloca(TCCState *s1, TCCSection *s, uint32_t offset,
|
||||||
|
int type, int symbol, uint32_t addend);
|
||||||
|
size_t coff_section_add(TCCSection *sec, size_t size, int align);
|
||||||
|
void coff_begin_file(TCCState *s1);
|
||||||
|
void coff_end_file(TCCState *s1);
|
||||||
|
int coff_load_file(TCCState *s1, int fd, unsigned long file_offset);
|
||||||
|
void coff_add_crtbegin(TCCState *s1);
|
||||||
|
void coff_add_crtend(TCCState *s1);
|
||||||
|
/* ------------- archive.c ---------- */
|
||||||
|
int archive_load(TCCState *s1, int fd, int alacarte);
|
||||||
|
|
||||||
|
|
||||||
#define TCC_OUTPUT_FORMAT_ELF 0 /* default output format: ELF */
|
|
||||||
#define TCC_OUTPUT_FORMAT_BINARY 1 /* binary image output */
|
#define TCC_OUTPUT_FORMAT_BINARY 1 /* binary image output */
|
||||||
#define TCC_OUTPUT_FORMAT_COFF 2 /* COFF */
|
#define TCC_OUTPUT_FORMAT_COFF 2 /* COFF */
|
||||||
|
|
||||||
#define ARMAG "!<arch>\n" /* For COFF and a.out archives */
|
|
||||||
|
|
||||||
void tccelf_new(TCCState *s);
|
|
||||||
void tccelf_delete(TCCState *s);
|
|
||||||
void tccelf_begin_file(TCCState *s1);
|
|
||||||
void tccelf_end_file(TCCState *s1);
|
|
||||||
Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags);
|
|
||||||
void section_realloc(Section *sec, unsigned long new_size);
|
|
||||||
size_t section_add(Section *sec, addr_t size, int align);
|
|
||||||
void *section_ptr_add(Section *sec, addr_t size);
|
|
||||||
Section *find_section(TCCState *s1, const char *name);
|
|
||||||
void free_section(Section *s);
|
|
||||||
Section *new_symtab(TCCState *s1, const char *symtab_name, int sh_type, int sh_flags, const char *strtab_name, const char *hash_name, int hash_sh_flags);
|
|
||||||
void init_symtab(Section *s);
|
|
||||||
|
|
||||||
int put_elf_str(Section *s, const char *sym);
|
|
||||||
int put_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name);
|
|
||||||
int set_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name);
|
|
||||||
int find_elf_sym(Section *s, const char *name);
|
|
||||||
void put_elf_reloc(Section *symtab, Section *s, unsigned long offset, int type, int symbol);
|
|
||||||
void put_elf_reloca(Section *symtab, Section *s, unsigned long offset, int type, int symbol, addr_t addend);
|
|
||||||
|
|
||||||
void resolve_common_syms(TCCState *s1);
|
|
||||||
void relocate_syms(TCCState *s1, Section *symtab, int do_resolve);
|
|
||||||
void relocate_sections(TCCState *s1);
|
|
||||||
|
|
||||||
ssize_t full_read(int fd, void *buf, size_t count);
|
|
||||||
void *load_data(int fd, unsigned long file_offset, unsigned long size);
|
|
||||||
int tcc_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);
|
|
||||||
|
|
||||||
addr_t get_sym_addr(TCCState *s, const char *name, int err, int forc);
|
|
||||||
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>
|
||||||
using variable <elem> */
|
using variable <elem> */
|
||||||
#define for_each_elem(sec, startoff, elem, type) \
|
#define for_each_elem(sec, startoff, elem, type) \
|
||||||
for (elem = (type *) sec->data + startoff; \
|
for (elem = (type *) sec->data + startoff; \
|
||||||
elem < (type *) (sec->data + sec->data_offset); elem++)
|
elem < (type *) (sec->data + sec->data_offset); elem++)
|
||||||
|
|
||||||
#ifndef ELF_OBJ_ONLY
|
|
||||||
void tccelf_add_crtbegin(TCCState *s1);
|
|
||||||
void tccelf_add_crtend(TCCState *s1);
|
|
||||||
#endif
|
|
||||||
#ifndef TCC_TARGET_PE
|
|
||||||
void tcc_add_runtime(TCCState *s1);
|
void tcc_add_runtime(TCCState *s1);
|
||||||
#endif
|
|
||||||
|
|
||||||
int coff_load_file(TCCState *s1, int fd, const char *fname);
|
|
||||||
|
|
||||||
/* ------------ tccdbg.c ------------ */
|
/* ------------ tccdbg.c ------------ */
|
||||||
#define tcc_error_noabort TCC_SET_STATE(_tcc_error_noabort)
|
#define tcc_error_noabort TCC_SET_STATE(_tcc_error_noabort)
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
#ifndef TCC_I386_LINK_H
|
|
||||||
# define TCC_I386_LINK_H 1
|
|
||||||
|
|
||||||
/* relocation type for 32 bit data relocation */
|
|
||||||
# define R_DATA_32 R_386_32
|
|
||||||
# define R_DATA_PTR R_386_32
|
|
||||||
# define R_JMP_SLOT R_386_JMP_SLOT
|
|
||||||
# define R_GLOB_DAT R_386_GLOB_DAT
|
|
||||||
# define R_COPY R_386_COPY
|
|
||||||
# define R_RELATIVE R_386_RELATIVE
|
|
||||||
|
|
||||||
# define R_NUM R_386_NUM
|
|
||||||
|
|
||||||
# define ELF_START_ADDR 0x08048000
|
|
||||||
# define ELF_PAGE_SIZE 0x1000
|
|
||||||
|
|
||||||
#endif /* !TCC_I386_LINK_H */
|
|
|
@ -26,4 +26,7 @@ typedef struct BufferedFile {
|
||||||
# define CH_EOB '\\' /** end of buffer or '\0' char in file */
|
# define CH_EOB '\\' /** end of buffer or '\0' char in file */
|
||||||
# define CH_EOF (-1) /** end of file */
|
# define CH_EOF (-1) /** end of file */
|
||||||
|
|
||||||
|
ssize_t full_read(int fd, void *buf, size_t count);
|
||||||
|
void *load_data(int fd, unsigned long file_offset, unsigned long size);
|
||||||
|
|
||||||
#endif /* !TCC_IO_H */
|
#endif /* !TCC_IO_H */
|
|
@ -1,10 +1,12 @@
|
||||||
#ifndef TCC_OBJECT_H
|
#ifndef TCC_OBJECT_H
|
||||||
# define TCC_OBJECT_H 1
|
# define TCC_OBJECT_H 1
|
||||||
|
|
||||||
|
# include <tcc/object/coff.h>
|
||||||
|
|
||||||
# define TCC_BINTYPE_NONE 0
|
# define TCC_BINTYPE_NONE 0
|
||||||
# define TCC_BINTYPE_COFF 1
|
# define TCC_BINTYPE_COFF 1
|
||||||
# define TCC_BINTYPE_ARCHIVE 2
|
# define TCC_BINTYPE_ARCHIVE 2
|
||||||
|
|
||||||
int tcc_object_type(int fd, void *h);
|
int tcc_object_type(int fd, COFFFileHeader *h);
|
||||||
|
|
||||||
#endif /* !TCC_OBJECT_H */
|
#endif /* !TCC_OBJECT_H */
|
|
@ -107,6 +107,40 @@ typedef struct COFFSym {
|
||||||
# define COFF_N_UNDEF 0
|
# define COFF_N_UNDEF 0
|
||||||
# define COFF_N_ABS -1
|
# define COFF_N_ABS -1
|
||||||
|
|
||||||
|
# define COFF_C_EFCN -1 /* physical end of a function */
|
||||||
|
# define COFF_C_NULL 0
|
||||||
|
# define COFF_C_AUTO 1
|
||||||
|
# define COFF_C_EXT 2 /* external symbol */
|
||||||
|
# define COFF_C_STAT 3 /* static */
|
||||||
|
# define COFF_C_REG 4 /* register var */
|
||||||
|
# define COFF_C_EXTDEF 5 /* external definition */
|
||||||
|
# define COFF_C_LABEL 6
|
||||||
|
# define COFF_C_ULABEL 7 /* undefined label */
|
||||||
|
# define COFF_C_MOS 8 /* member of struct */
|
||||||
|
# define COFF_C_ARG 9
|
||||||
|
# define COFF_C_STRTAG 10 /* struct tag */
|
||||||
|
# define COFF_C_MOU 11 /* member of union */
|
||||||
|
# define COFF_C_UNTAG 12 /* union tag */
|
||||||
|
# define COFF_C_TPDEF 13 /* typedef */
|
||||||
|
# define COFF_C_USTATIC 14
|
||||||
|
# define COFF_C_ENTAG 15
|
||||||
|
# define COFF_C_MOE 16
|
||||||
|
# define COFF_C_REGPARM 17
|
||||||
|
# define COFF_C_FIELD 18
|
||||||
|
# define COFF_C_BLOCK 100
|
||||||
|
# define COFF_C_FCN 101
|
||||||
|
# define COFF_C_EOS 102
|
||||||
|
# define COFF_C_FILE 103
|
||||||
|
# define COFF_C_LINE 104
|
||||||
|
# define COFF_C_ALIAS 105
|
||||||
|
# define COFF_C_HIDDEN 106
|
||||||
|
|
||||||
|
# define COFF_DT_FUNC (2 << 2)
|
||||||
|
# define COFF_DT_NON (0 << 2)
|
||||||
|
# define COFF_DT_PTR (1 << 2)
|
||||||
|
# define COFF_DT_FCN (2 << 2)
|
||||||
|
# define COFF_DT_ARY (3 << 2)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -15,8 +15,9 @@
|
||||||
# define TCC_CACHED_INCLUDES_HASH_SIZE 32
|
# define TCC_CACHED_INCLUDES_HASH_SIZE 32
|
||||||
# define TCC_PACK_STACK_SIZE 8
|
# define TCC_PACK_STACK_SIZE 8
|
||||||
|
|
||||||
typedef struct TCCState2 TCCState2;
|
typedef struct TCCState TCCState;
|
||||||
typedef struct COFFSym COFFSym;
|
typedef struct COFFSym COFFSym;
|
||||||
|
typedef struct COFFReloc COFFReloc;
|
||||||
typedef struct CachedInclude CachedInclude;
|
typedef struct CachedInclude CachedInclude;
|
||||||
typedef struct InlineFunc InlineFunc;
|
typedef struct InlineFunc InlineFunc;
|
||||||
|
|
||||||
|
@ -27,6 +28,7 @@ typedef struct TCCStrtab {
|
||||||
|
|
||||||
typedef struct TCCSymtab {
|
typedef struct TCCSymtab {
|
||||||
size_t nsym;
|
size_t nsym;
|
||||||
|
size_t start;
|
||||||
COFFSym *syms;
|
COFFSym *syms;
|
||||||
TCCStrtab strtab;
|
TCCStrtab strtab;
|
||||||
} TCCSymtab;
|
} TCCSymtab;
|
||||||
|
@ -36,16 +38,21 @@ typedef struct TCCSection {
|
||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
uint32_t data_allocated;
|
uint32_t data_allocated;
|
||||||
|
|
||||||
TCCState2 *state;
|
TCCState *state;
|
||||||
|
|
||||||
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;
|
int16_t addralign;
|
||||||
|
uint16_t type;
|
||||||
size_t offset;
|
size_t offset;
|
||||||
|
|
||||||
|
size_t nreloc;
|
||||||
|
COFFReloc *reloc;
|
||||||
|
struct TCCSection *prev;
|
||||||
} TCCSection;
|
} TCCSection;
|
||||||
|
|
||||||
struct TCCState2 {
|
struct TCCState {
|
||||||
uint8_t verbose; /** if 1, display some information during compilation */
|
uint8_t verbose; /** if 1, display some information during compilation */
|
||||||
uint8_t nostdinc; /** if 1, no standard headers are added */
|
uint8_t nostdinc; /** if 1, no standard headers are added */
|
||||||
uint8_t nostdlib; /** if 1, no standard libraries are added */
|
uint8_t nostdlib; /** if 1, no standard libraries are added */
|
||||||
|
@ -84,7 +91,7 @@ struct TCCState2 {
|
||||||
uint8_t gnu_ext; /** use GNU C extensions */
|
uint8_t gnu_ext; /** use GNU C extensions */
|
||||||
uint8_t tcc_ext; /** use TinyCC extensions */
|
uint8_t tcc_ext; /** use TinyCC extensions */
|
||||||
|
|
||||||
uint8_t dflags; /** -dX value */
|
uint8_t dflag; /** -dX value */
|
||||||
uint8_t Pflag; /** -P switch (LINE_MACRO_OUTPUT_FORMAT) */
|
uint8_t Pflag; /** -P switch (LINE_MACRO_OUTPUT_FORMAT) */
|
||||||
|
|
||||||
uint8_t has_text_addr;
|
uint8_t has_text_addr;
|
||||||
|
@ -151,7 +158,7 @@ struct TCCState2 {
|
||||||
|
|
||||||
/* sections */
|
/* sections */
|
||||||
TCCSection **sections;
|
TCCSection **sections;
|
||||||
int nb_sections; /* number of sections, including first dummy section */
|
int nb_sections; /** number of sections, including first dummy section */
|
||||||
|
|
||||||
/* predefined sections */
|
/* predefined sections */
|
||||||
TCCSection *text_section;
|
TCCSection *text_section;
|
||||||
|
@ -171,6 +178,16 @@ struct TCCState2 {
|
||||||
|
|
||||||
/* for warnings/errors for object files */
|
/* for warnings/errors for object files */
|
||||||
const char *current_filename;
|
const char *current_filename;
|
||||||
|
|
||||||
|
/* used by main and tcc_parse_args only */
|
||||||
|
void **files; /** files seen on command line */
|
||||||
|
int nb_files; /** number thereof */
|
||||||
|
int nb_libraries; /** number of libs thereof */
|
||||||
|
char *outfile; /** output filename */
|
||||||
|
char *deps_outfile; /** option -MF */
|
||||||
|
int argc;
|
||||||
|
char **argv;
|
||||||
|
CString linker_arg; /** collect -Wl options */
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* !TCC_STATE_H */
|
#endif /* !TCC_STATE_H */
|
36
libtcc/io.c
36
libtcc/io.c
|
@ -51,3 +51,39 @@ void tcc_close(void)
|
||||||
tok_flags = bf->prev_tok_flags;
|
tok_flags = bf->prev_tok_flags;
|
||||||
tcc_free(bf);
|
tcc_free(bf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
full_read(int fd, void *buf, size_t count)
|
||||||
|
{
|
||||||
|
char *cbuf;
|
||||||
|
size_t rnum;
|
||||||
|
ssize_t num;
|
||||||
|
|
||||||
|
cbuf = buf;
|
||||||
|
rnum = 0;
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
num = read(fd, cbuf, count-rnum);
|
||||||
|
if (num < 0)
|
||||||
|
{
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
if (num == 0)
|
||||||
|
{
|
||||||
|
return rnum;
|
||||||
|
}
|
||||||
|
rnum += num;
|
||||||
|
cbuf += num;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
load_data(int fd, unsigned long file_offset, unsigned long size)
|
||||||
|
{
|
||||||
|
void *data;
|
||||||
|
|
||||||
|
data = tcc_malloc(size);
|
||||||
|
lseek(fd, file_offset, SEEK_SET);
|
||||||
|
full_read(fd, data, size);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
240
libtcc/libtcc.c
240
libtcc/libtcc.c
|
@ -28,7 +28,6 @@
|
||||||
#include <tcc/path.h>
|
#include <tcc/path.h>
|
||||||
#include <tcc/memory.h>
|
#include <tcc/memory.h>
|
||||||
#include <tcc/object.h>
|
#include <tcc/object.h>
|
||||||
#include "utils/string.h"
|
|
||||||
#include "cc/cc.h"
|
#include "cc/cc.h"
|
||||||
|
|
||||||
/********************************************************/
|
/********************************************************/
|
||||||
|
@ -56,13 +55,20 @@ PUB_FUNC void tcc_exit_state(TCCState *s1)
|
||||||
tcc_state = NULL;
|
tcc_state = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *tcc_load_text(int fd)
|
char *
|
||||||
|
tcc_load_text(int fd)
|
||||||
{
|
{
|
||||||
int len = lseek(fd, 0, SEEK_END);
|
int len;
|
||||||
char *buf = load_data(fd, 0, len + 1);
|
char *buf;
|
||||||
|
|
||||||
|
len = lseek(fd, 0, SEEK_END);
|
||||||
|
buf = load_data(fd, 0, len + 1); /** XXX: rename func */
|
||||||
if (buf)
|
if (buf)
|
||||||
buf[len] = 0;
|
{
|
||||||
return buf;
|
buf[len] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
@ -300,50 +306,62 @@ int tcc_open(TCCState *s1, const char *filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* compile the file opened in 'file'. Return non zero if errors. */
|
/* compile the file opened in 'file'. Return non zero if errors. */
|
||||||
static int tcc_compile(TCCState *s1, int filetype, const char *str, int fd)
|
static int
|
||||||
|
tcc_compile(TCCState *s1, int filetype, const char *str, int fd)
|
||||||
{
|
{
|
||||||
/* Here we enter the code section where we use the global variables for
|
/* Here we enter the code section where we use the global variables for
|
||||||
parsing and code generation (tccpp.c, tccgen.c, <target>-gen.c).
|
parsing and code generation (tccpp.c, tccgen.c, <target>-gen.c).
|
||||||
Other threads need to wait until we're done.
|
Other threads need to wait until we're done.
|
||||||
|
|
||||||
Alternatively we could use thread local storage for those global
|
Alternatively we could use thread local storage for those global
|
||||||
variables, which may or may not have advantages */
|
variables, which may or may not have advantages */
|
||||||
|
int len;
|
||||||
tcc_enter_state(s1);
|
|
||||||
s1->error_set_jmp_enabled = 1;
|
tcc_enter_state(s1);
|
||||||
|
s1->error_set_jmp_enabled = 1;
|
||||||
if (setjmp(s1->error_jmp_buf) == 0) {
|
|
||||||
s1->nb_errors = 0;
|
if (setjmp(s1->error_jmp_buf) == 0)
|
||||||
|
{
|
||||||
if (fd == -1) {
|
s1->nb_errors = 0;
|
||||||
int len = strlen(str);
|
|
||||||
tcc_open_bf(s1, "<string>", len);
|
if (fd == -1)
|
||||||
memcpy(file->buffer, str, len);
|
{
|
||||||
} else {
|
len = strlen(str);
|
||||||
tcc_open_bf(s1, str, 0);
|
tcc_open_bf(s1, "<string>", len);
|
||||||
file->fd = fd;
|
memcpy(file->buffer, str, len);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
preprocess_start(s1, filetype);
|
{
|
||||||
tccgen_init(s1);
|
tcc_open_bf(s1, str, 0);
|
||||||
|
file->fd = fd;
|
||||||
if (s1->output_type == TCC_OUTPUT_PREPROCESS) {
|
}
|
||||||
tcc_preprocess(s1);
|
|
||||||
} else {
|
preprocess_start(s1, filetype);
|
||||||
tccelf_begin_file(s1);
|
tccgen_init(s1);
|
||||||
if (filetype & (AFF_TYPE_ASM | AFF_TYPE_ASMPP)) {
|
|
||||||
tcc_assemble(s1, !!(filetype & AFF_TYPE_ASMPP));
|
if (s1->output_type == TCC_OUTPUT_PREPROCESS)
|
||||||
} else {
|
{
|
||||||
tccgen_compile(s1);
|
tcc_preprocess(s1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
coff_begin_file(s1);
|
||||||
|
if (filetype & (AFF_TYPE_ASM | AFF_TYPE_ASMPP))
|
||||||
|
{
|
||||||
|
tcc_assemble(s1, !!(filetype & AFF_TYPE_ASMPP));
|
||||||
}
|
}
|
||||||
tccelf_end_file(s1);
|
else
|
||||||
}
|
{
|
||||||
}
|
tccgen_compile(s1);
|
||||||
tccgen_finish(s1);
|
}
|
||||||
preprocess_end(s1);
|
coff_end_file(s1);
|
||||||
s1->error_set_jmp_enabled = 0;
|
}
|
||||||
tcc_exit_state(s1);
|
}
|
||||||
return s1->nb_errors != 0 ? -1 : 0;
|
tccgen_finish(s1);
|
||||||
|
preprocess_end(s1);
|
||||||
|
s1->error_set_jmp_enabled = 0;
|
||||||
|
tcc_exit_state(s1);
|
||||||
|
return (s1->nb_errors != 0 ? -1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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" */
|
||||||
|
@ -394,10 +412,11 @@ TCCState *tcc_new(void)
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void tcc_delete(TCCState *s1)
|
void
|
||||||
|
tcc_delete(TCCState *s1)
|
||||||
{
|
{
|
||||||
/* free sections */
|
/* free sections */
|
||||||
tccelf_delete(s1);
|
coff_delete(s1);
|
||||||
|
|
||||||
/* free library paths */
|
/* free library paths */
|
||||||
dynarray_reset(&s1->library_paths, &s1->nb_library_paths);
|
dynarray_reset(&s1->library_paths, &s1->nb_library_paths);
|
||||||
|
@ -424,7 +443,8 @@ void tcc_delete(TCCState *s1)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int tcc_set_output_type(TCCState *s, int output_type)
|
int
|
||||||
|
tcc_set_output_type(TCCState *s, int output_type)
|
||||||
{
|
{
|
||||||
s->output_type = output_type;
|
s->output_type = output_type;
|
||||||
|
|
||||||
|
@ -439,11 +459,11 @@ int tcc_set_output_type(TCCState *s, int output_type)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add sections */
|
/* add sections */
|
||||||
tccelf_new(s);
|
coff_new(s);
|
||||||
|
|
||||||
if (output_type == TCC_OUTPUT_OBJ) {
|
if (output_type == TCC_OUTPUT_OBJ) {
|
||||||
/* always elf for objects */
|
/* always elf for objects */
|
||||||
s->output_format = TCC_OUTPUT_FORMAT_ELF;
|
s->output_format = TCC_OUTPUT_FORMAT_COFF;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -452,7 +472,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 (!s->nostdlib)
|
if (!s->nostdlib)
|
||||||
tccelf_add_crtbegin(s);
|
coff_add_crtbegin(s);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -470,64 +490,70 @@ int tcc_add_sysinclude_path(TCCState *s, const char *pathname)
|
||||||
|
|
||||||
static int guess_filetype(const char *filename);
|
static int guess_filetype(const char *filename);
|
||||||
|
|
||||||
int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
|
int
|
||||||
|
tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
|
||||||
{
|
{
|
||||||
int fd, ret = -1;
|
COFFFileHeader fhdr;
|
||||||
|
int obj_type;
|
||||||
if (0 == (flags & AFF_TYPE_MASK))
|
int fd, ret = -1;
|
||||||
flags |= guess_filetype(filename);
|
|
||||||
|
if (0 == (flags & AFF_TYPE_MASK))
|
||||||
/* ignore binary files with -E */
|
{
|
||||||
if (s1->output_type == TCC_OUTPUT_PREPROCESS
|
flags |= guess_filetype(filename);
|
||||||
&& (flags & AFF_TYPE_BIN))
|
}
|
||||||
return 0;
|
|
||||||
|
/* ignore binary files with -E */
|
||||||
/* open the file */
|
if (s1->output_type == TCC_OUTPUT_PREPROCESS
|
||||||
fd = _tcc_open(s1, filename);
|
&& (flags & AFF_TYPE_BIN))
|
||||||
if (fd < 0) {
|
{
|
||||||
if (flags & AFF_PRINT_ERROR)
|
return (0);
|
||||||
tcc_error_noabort("file '%s' not found", filename);
|
}
|
||||||
return FILE_NOT_FOUND;
|
|
||||||
|
/* open the file */
|
||||||
|
fd = _tcc_open(s1, filename);
|
||||||
|
if (fd < 0)
|
||||||
|
{
|
||||||
|
if (flags & AFF_PRINT_ERROR)
|
||||||
|
{
|
||||||
|
tcc_error_noabort("file '%s' not found", filename);
|
||||||
|
}
|
||||||
|
return (FILE_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
s1->current_filename = filename;
|
||||||
|
if (flags & AFF_TYPE_BIN)
|
||||||
|
{
|
||||||
|
obj_type = tcc_object_type(fd, &fhdr);
|
||||||
|
lseek(fd, 0, SEEK_SET);
|
||||||
|
|
||||||
|
switch (obj_type)
|
||||||
|
{
|
||||||
|
case TCC_BINTYPE_COFF:
|
||||||
|
ret = coff_load_file(s1, fd, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TCC_BINTYPE_ARCHIVE:
|
||||||
|
ret = archive_load(s1, fd, !(flags & AFF_WHOLE_ARCHIVE));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
tcc_error_noabort("%s: unrecognized file type", filename);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
s1->current_filename = filename;
|
{
|
||||||
if (flags & AFF_TYPE_BIN) {
|
/* update target deps */
|
||||||
ElfW(Ehdr) ehdr;
|
dynarray_add(&s1->target_deps, &s1->nb_target_deps, tcc_strdup(filename));
|
||||||
int obj_type;
|
ret = tcc_compile(s1, flags, filename, fd);
|
||||||
|
}
|
||||||
obj_type = tcc_object_type(fd, &ehdr);
|
s1->current_filename = NULL;
|
||||||
lseek(fd, 0, SEEK_SET);
|
return (ret);
|
||||||
|
|
||||||
switch (obj_type) {
|
|
||||||
|
|
||||||
case AFF_BINTYPE_REL:
|
|
||||||
ret = tcc_load_object_file(s1, fd, 0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AFF_BINTYPE_AR:
|
|
||||||
ret = tcc_load_archive(s1, fd, !(flags & AFF_WHOLE_ARCHIVE));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AFF_BINTYPE_COFF:
|
|
||||||
ret = coff_load_file(s1, fd, filename);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
/* as GNU ld, consider it is an ld script if not recognized */
|
|
||||||
tcc_error_noabort("%s: unrecognized file type", filename);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
close(fd);
|
|
||||||
} else {
|
|
||||||
/* update target deps */
|
|
||||||
dynarray_add(&s1->target_deps, &s1->nb_target_deps, tcc_strdup(filename));
|
|
||||||
ret = tcc_compile(s1, flags, filename, fd);
|
|
||||||
}
|
|
||||||
s1->current_filename = NULL;
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int guess_filetype(const char *filename)
|
static int
|
||||||
|
guess_filetype(const char *filename)
|
||||||
{
|
{
|
||||||
int filetype = 0;
|
int filetype = 0;
|
||||||
if (1) {
|
if (1) {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include "tcc/io.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <tcc/state.h>
|
#include <tcc/state.h>
|
||||||
#include <tcc/memory.h>
|
#include <tcc/memory.h>
|
||||||
|
@ -6,10 +7,22 @@
|
||||||
#include <tcc/object/coff.h>
|
#include <tcc/object/coff.h>
|
||||||
|
|
||||||
int
|
int
|
||||||
tcc_object_type(int fd, void *h)
|
tcc_object_type(int fd, COFFFileHeader *h)
|
||||||
{
|
{
|
||||||
size_t size;
|
ssize_t size;
|
||||||
|
|
||||||
|
size = full_read(fd, h, sizeof(COFFFileHeader));
|
||||||
return (0);
|
if (size == sizeof(COFFFileHeader)
|
||||||
|
&& h->magic == COFF_MAGIC
|
||||||
|
&& (h->flags & COFF_F_EXEC) == 0)
|
||||||
|
{
|
||||||
|
return (TCC_BINTYPE_COFF);
|
||||||
|
}
|
||||||
|
else if (size >= 8
|
||||||
|
&& memcmp(h, ARCHIVE_MAGIC, ARCHIVE_MAGSZ) == 0)
|
||||||
|
{
|
||||||
|
return (TCC_BINTYPE_ARCHIVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (TCC_BINTYPE_NONE);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,4 +10,9 @@ tcc_load_archive(TCCState *s1, int fd, int alacarte)
|
||||||
size_t file_offset;
|
size_t file_offset;
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int archive_load(TCCState *s1, int fd, int alacarte)
|
||||||
|
{
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include "tcc.h"
|
||||||
#include "utils/string.h"
|
#include "utils/string.h"
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
@ -18,7 +19,7 @@ void dynarray_add(void *ptab, int *nb_ptr, void *data);
|
||||||
void dynarray_reset(void *pp, int *n);
|
void dynarray_reset(void *pp, int *n);
|
||||||
|
|
||||||
static TCCSection *
|
static TCCSection *
|
||||||
coff_new_section(TCCState2 *s1, const char *name, int flags)
|
coff_new_section(TCCState *s1, const char *name, int flags)
|
||||||
{
|
{
|
||||||
TCCSection *sec;
|
TCCSection *sec;
|
||||||
|
|
||||||
|
@ -42,10 +43,12 @@ coff_free_section(TCCSection *s)
|
||||||
tcc_free(s->data);
|
tcc_free(s->data);
|
||||||
s->data = NULL;
|
s->data = NULL;
|
||||||
s->data_allocated = s->data_offset = 0;
|
s->data_allocated = s->data_offset = 0;
|
||||||
|
tcc_free(s->reloc);
|
||||||
|
s->reloc = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
coff_new(TCCState2 *s1)
|
coff_new(TCCState *s1)
|
||||||
{
|
{
|
||||||
dynarray_add(&s1->sections, &s1->nb_sections, NULL);
|
dynarray_add(&s1->sections, &s1->nb_sections, NULL);
|
||||||
|
|
||||||
|
@ -61,7 +64,7 @@ coff_new(TCCState2 *s1)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
coff_delete(TCCState2 *s1)
|
coff_delete(TCCState *s1)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -82,7 +85,7 @@ coff_delete(TCCState2 *s1)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
coff_begin_file(TCCState2 *s1)
|
coff_begin_file(TCCState *s1)
|
||||||
{
|
{
|
||||||
TCCSection *sec;
|
TCCSection *sec;
|
||||||
int i;
|
int i;
|
||||||
|
@ -92,6 +95,26 @@ coff_begin_file(TCCState2 *s1)
|
||||||
sec = s1->sections[i];
|
sec = s1->sections[i];
|
||||||
sec->offset = sec->data_offset;
|
sec->offset = sec->data_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s1->symtab->start = s1->symtab->nsym;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
coff_end_file(TCCState *s1)
|
||||||
|
{
|
||||||
|
int nb_syms;
|
||||||
|
int *tr;
|
||||||
|
int i;
|
||||||
|
COFFSym *sym;
|
||||||
|
|
||||||
|
nb_syms = s1->symtab->nsym - s1->symtab->start;
|
||||||
|
|
||||||
|
tr = tcc_mallocz(nb_syms * sizeof(int));
|
||||||
|
|
||||||
|
for (i = s1->symtab->start; i < nb_syms; i++)
|
||||||
|
{
|
||||||
|
sym = &s1->symtab->syms[i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -145,7 +168,7 @@ coff_section_ptr_add(TCCSection *sec, size_t size)
|
||||||
}
|
}
|
||||||
|
|
||||||
static TCCSection *
|
static TCCSection *
|
||||||
coff_have_section(TCCState2 *s1, const char *name)
|
coff_have_section(TCCState *s1, const char *name)
|
||||||
{
|
{
|
||||||
TCCSection *sec;
|
TCCSection *sec;
|
||||||
int i;
|
int i;
|
||||||
|
@ -164,7 +187,7 @@ coff_have_section(TCCState2 *s1, const char *name)
|
||||||
/* return a reference to a section, and create it if it does not
|
/* return a reference to a section, and create it if it does not
|
||||||
exists */
|
exists */
|
||||||
TCCSection *
|
TCCSection *
|
||||||
coff_find_section(TCCState2 *s1, const char *name)
|
coff_find_section(TCCState *s1, const char *name)
|
||||||
{
|
{
|
||||||
TCCSection *sec;
|
TCCSection *sec;
|
||||||
|
|
||||||
|
@ -184,7 +207,7 @@ coff_find_section(TCCState2 *s1, const char *name)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
coff_add_sym(TCCState2 *s1, uint32_t value, const char *name, size_t size,
|
coff_add_sym(TCCState *s1, uint32_t value, const char *name, size_t size,
|
||||||
int16_t scnum, uint16_t type, int8_t sclass)
|
int16_t scnum, uint16_t type, int8_t sclass)
|
||||||
{
|
{
|
||||||
size_t symidx;
|
size_t symidx;
|
||||||
|
@ -197,6 +220,7 @@ coff_add_sym(TCCState2 *s1, uint32_t value, const char *name, size_t size,
|
||||||
|
|
||||||
s1->symtab->syms = tcc_realloc(s1->symtab->syms, sizeof(COFFSym) * s1->symtab->nsym);
|
s1->symtab->syms = tcc_realloc(s1->symtab->syms, sizeof(COFFSym) * s1->symtab->nsym);
|
||||||
sym = &(s1->symtab->syms[symidx]);
|
sym = &(s1->symtab->syms[symidx]);
|
||||||
|
size = strlen(name); /** XXX: fixme */
|
||||||
if (size > 8)
|
if (size > 8)
|
||||||
{
|
{
|
||||||
strtaboffset = ALIGN_UP(s1->symtab->strtab.len, 1);
|
strtaboffset = ALIGN_UP(s1->symtab->strtab.len, 1);
|
||||||
|
@ -219,7 +243,7 @@ coff_add_sym(TCCState2 *s1, uint32_t value, const char *name, size_t size,
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
coff_find_sym(TCCState2 *s1, const char *name)
|
coff_find_sym(TCCState *s1, const char *name)
|
||||||
{
|
{
|
||||||
size_t symidx;
|
size_t symidx;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
@ -258,7 +282,7 @@ coff_find_sym(TCCState2 *s1, const char *name)
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
coff_get_sym_addr(TCCState2 *s1, const char *name, int err, int forc)
|
coff_get_sym_addr(TCCState *s1, const char *name, int err, int forc)
|
||||||
{
|
{
|
||||||
COFFSym *sym;
|
COFFSym *sym;
|
||||||
int sym_idx;
|
int sym_idx;
|
||||||
|
@ -285,8 +309,34 @@ coff_get_sym_addr(TCCState2 *s1, const char *name, int err, int forc)
|
||||||
return (sym->value);
|
return (sym->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ---------------------------------------------------------------------------
|
||||||
|
* Relocs
|
||||||
|
* ---------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
coff_add_reloca(TCCState *s1, TCCSection *s, uint32_t offset,
|
||||||
|
int type, int symbol, uint32_t addend)
|
||||||
|
{
|
||||||
|
char buf[256];
|
||||||
|
COFFReloc *rel;
|
||||||
|
|
||||||
|
if (s->reloc == NULL)
|
||||||
|
{
|
||||||
|
s->reloc = tcc_mallocz(sizeof(COFFReloc) * UINT16_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
rel = &s->reloc[s->nreloc];
|
||||||
|
s->nreloc++;
|
||||||
|
|
||||||
|
rel->symndx = symbol;
|
||||||
|
rel->type = type;
|
||||||
|
rel->vaddr = offset;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
tcc_output_coff(TCCState2 *s1, FILE *f)
|
tcc_output_coff(TCCState *s1, FILE *f)
|
||||||
{
|
{
|
||||||
COFFFileHeader coffhdr;
|
COFFFileHeader coffhdr;
|
||||||
AOutHeader aouthdr;
|
AOutHeader aouthdr;
|
||||||
|
@ -325,23 +375,35 @@ tcc_output_coff(TCCState2 *s1, FILE *f)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
coff_output_object(TCCState2 *s, const char *filename)
|
coff_output_object(TCCState *s, const char *filename)
|
||||||
{
|
{
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
coff_output_exe(TCCState2 *s, const char *filename)
|
coff_output_exe(TCCState *s, const char *filename)
|
||||||
{
|
{
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
coff_load_object(TCCState2 *s, int fd, size_t file_offset)
|
coff_load_object(TCCState *s, int fd, size_t file_offset)
|
||||||
{
|
{
|
||||||
COFFFileHeader chdr;
|
COFFFileHeader chdr;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
coff_add_crtbegin(TCCState *s1)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
coff_add_crtend(TCCState *s1)
|
||||||
|
{
|
||||||
|
|
||||||
}
|
}
|
113
libtcc/tcccoff.c
113
libtcc/tcccoff.c
|
@ -1,113 +0,0 @@
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
# include "config.h"
|
|
||||||
#endif /* HAVE_CONFIG_H */
|
|
||||||
|
|
||||||
#include <tcc.h>
|
|
||||||
#include <tcc/path.h>
|
|
||||||
#include <tcc/memory.h>
|
|
||||||
#include <tcc/coff.h>
|
|
||||||
|
|
||||||
static int
|
|
||||||
read_mem(int fd, unsigned offset, void *buffer, unsigned len)
|
|
||||||
{
|
|
||||||
lseek(fd, offset, SEEK_SET);
|
|
||||||
return len == read(fd, buffer, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
coff_load_lib(TCCState *s1, int fd)
|
|
||||||
{
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
coff_merge_or_create(void)
|
|
||||||
{
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
coff_resolve_symbols(void)
|
|
||||||
{
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
coff_load_obj(TCCState *s1, int fd)
|
|
||||||
{
|
|
||||||
FILHDR hdr;
|
|
||||||
SCNHDR *scns;
|
|
||||||
SYMENT *syments;
|
|
||||||
RELOC *relocs;
|
|
||||||
Section *s;
|
|
||||||
uint16_t i;
|
|
||||||
int32_t j;
|
|
||||||
int k;
|
|
||||||
char buff[9];
|
|
||||||
|
|
||||||
if (!read_mem(fd, 0, &hdr, FILHSZ))
|
|
||||||
return (tcc_error_noabort("not a coff object file"));
|
|
||||||
|
|
||||||
if (hdr.f_magic != F_MACH_I386 || hdr.f_flags & F_EXEC)
|
|
||||||
return (tcc_error_noabort("invalid coff object file"));
|
|
||||||
|
|
||||||
/* read sections */
|
|
||||||
scns = tcc_malloc(SCNHSZ * hdr.f_nscns);
|
|
||||||
if (!read_mem(fd, FILHSZ, scns, SCNHSZ * hdr.f_nscns))
|
|
||||||
{
|
|
||||||
tcc_free(scns);
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < hdr.f_nscns; i++)
|
|
||||||
{
|
|
||||||
memset(buff, 0, 9);
|
|
||||||
memcpy(buff, scns[i].s_name, 8);
|
|
||||||
printf("sec: %s\n", buff);
|
|
||||||
|
|
||||||
for (k = 1; k < s1->nb_sections; k++)
|
|
||||||
{
|
|
||||||
if (strcmp(s1->sections[k]->old_name, buff) != 0)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* load symtab */
|
|
||||||
syments = tcc_malloc(SYMESZ * hdr.f_nsyms);
|
|
||||||
read_mem(fd, hdr.f_symptr, syments, SYMESZ * hdr.f_nsyms);
|
|
||||||
for (j = 0; j < hdr.f_nsyms; j++)
|
|
||||||
{
|
|
||||||
memset(buff, 0, 9);
|
|
||||||
memcpy(buff, syments[j].n_name, 8);
|
|
||||||
printf("sym: %s\n", buff);
|
|
||||||
}
|
|
||||||
|
|
||||||
tcc_free(syments);
|
|
||||||
tcc_free(scns);
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
coff_load_file(TCCState *s1, int fd, const char *fname)
|
|
||||||
{
|
|
||||||
if (strcmp(tcc_fileextension(fname), ".a") == 0)
|
|
||||||
{
|
|
||||||
return (coff_load_lib(s1, fd));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return (coff_load_obj(s1, fd));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
coff_output_file(TCCState *s1, const char *filename)
|
|
||||||
{
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
|
|
@ -34,7 +34,8 @@
|
||||||
|
|
||||||
/* Define this to get some debug output during relocation processing. */
|
/* Define this to get some debug output during relocation processing. */
|
||||||
#undef DEBUG_RELOC
|
#undef DEBUG_RELOC
|
||||||
|
# define ELF_START_ADDR 0x08048000
|
||||||
|
# define ELF_PAGE_SIZE 0x1000
|
||||||
/********************************************************/
|
/********************************************************/
|
||||||
/* global variables */
|
/* global variables */
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,7 @@ static int ar_usage(int ret) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int tcc_tool_ar(TCCState *s1, int argc, char **argv)
|
int tcc_tool_ar(TCCState *s1, int argc, char **argv)
|
||||||
{
|
{/*
|
||||||
static const ArchiveFileHeader arhdr_init = {
|
static const ArchiveFileHeader arhdr_init = {
|
||||||
"/ ",
|
"/ ",
|
||||||
"0 ",
|
"0 ",
|
||||||
|
@ -141,7 +141,7 @@ no_ar:
|
||||||
if (strcmp(arhdr.name,"/") && strcmp(arhdr.name,"/SYM64/")) {
|
if (strcmp(arhdr.name,"/") && strcmp(arhdr.name,"/SYM64/")) {
|
||||||
if (e > p && e[-1] == '/')
|
if (e > p && e[-1] == '/')
|
||||||
e[-1] = '\0';
|
e[-1] = '\0';
|
||||||
/* tv not implemented */
|
// tv not implemented
|
||||||
if (table || verbose)
|
if (table || verbose)
|
||||||
printf("%s%s\n", extract ? "x - " : "", arhdr.name);
|
printf("%s%s\n", extract ? "x - " : "", arhdr.name);
|
||||||
if (extract) {
|
if (extract) {
|
||||||
|
@ -154,7 +154,7 @@ no_ar:
|
||||||
}
|
}
|
||||||
fwrite(buf, fsize, 1, fo);
|
fwrite(buf, fsize, 1, fo);
|
||||||
fclose(fo);
|
fclose(fo);
|
||||||
/* ignore date/uid/gid/mode */
|
// ignore date/uid/gid/mode
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fsize & 1)
|
if (fsize & 1)
|
||||||
|
@ -328,7 +328,9 @@ the_end:
|
||||||
remove(created_file);
|
remove(created_file);
|
||||||
if (fo)
|
if (fo)
|
||||||
fclose(fo), remove(tfile);
|
fclose(fo), remove(tfile);
|
||||||
return ret;
|
return ret;*/
|
||||||
|
|
||||||
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------------------------- */
|
/* -------------------------------------------------------------- */
|
||||||
|
|
Loading…
Reference in a new issue