mirror of
https://github.com/mirror/tinycc.git
synced 2025-02-04 06:30:10 +08:00
Add constructor/destructor support
This commit is contained in:
parent
c4c5ea4381
commit
800c3a5e0b
7
tcc.h
7
tcc.h
@ -468,7 +468,9 @@ struct SymAttr {
|
|||||||
dllexport : 1,
|
dllexport : 1,
|
||||||
nodecorate : 1,
|
nodecorate : 1,
|
||||||
dllimport : 1,
|
dllimport : 1,
|
||||||
unused : 4;
|
constructor : 1,
|
||||||
|
destructor : 1,
|
||||||
|
unused : 2;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* function attributes or temporary attributes for parsing */
|
/* function attributes or temporary attributes for parsing */
|
||||||
@ -1443,6 +1445,9 @@ ST_FUNC void greloc(Section *s, Sym *sym, unsigned long offset, int type);
|
|||||||
#endif
|
#endif
|
||||||
ST_FUNC void greloca(Section *s, Sym *sym, unsigned long offset, int type, addr_t addend);
|
ST_FUNC void greloca(Section *s, Sym *sym, unsigned long offset, int type, addr_t addend);
|
||||||
|
|
||||||
|
ST_FUNC void add_init_array (TCCState *s1, Sym *sym);
|
||||||
|
ST_FUNC void add_fini_array (TCCState *s1, Sym *sym);
|
||||||
|
|
||||||
ST_FUNC int put_elf_str(Section *s, const char *sym);
|
ST_FUNC int put_elf_str(Section *s, const char *sym);
|
||||||
ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name);
|
ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name);
|
||||||
ST_FUNC int set_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name);
|
ST_FUNC int set_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name);
|
||||||
|
61
tccelf.c
61
tccelf.c
@ -339,9 +339,7 @@ ST_FUNC void section_reserve(Section *sec, unsigned long size)
|
|||||||
sec->data_offset = size;
|
sec->data_offset = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return a reference to a section, and create it if it does not
|
static Section *find_section_create (TCCState *s1, const char *name, int create)
|
||||||
exists */
|
|
||||||
ST_FUNC Section *find_section(TCCState *s1, const char *name)
|
|
||||||
{
|
{
|
||||||
Section *sec;
|
Section *sec;
|
||||||
int i;
|
int i;
|
||||||
@ -351,7 +349,14 @@ ST_FUNC Section *find_section(TCCState *s1, const char *name)
|
|||||||
return sec;
|
return sec;
|
||||||
}
|
}
|
||||||
/* sections are created as PROGBITS */
|
/* sections are created as PROGBITS */
|
||||||
return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
|
return create ? new_section(s1, name, SHT_PROGBITS, SHF_ALLOC) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return a reference to a section, and create it if it does not
|
||||||
|
exists */
|
||||||
|
ST_FUNC Section *find_section(TCCState *s1, const char *name)
|
||||||
|
{
|
||||||
|
return find_section_create (s1, name, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
@ -1436,6 +1441,30 @@ static int tcc_add_support(TCCState *s1, const char *filename)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static void add_array (const char *section, TCCState *s1, Sym *sym)
|
||||||
|
{
|
||||||
|
Section *s;
|
||||||
|
unsigned char *ptr;
|
||||||
|
|
||||||
|
s = find_section(s1, section);
|
||||||
|
if (s) {
|
||||||
|
s->sh_flags |= SHF_WRITE;
|
||||||
|
ptr = section_ptr_add(s, PTR_SIZE);
|
||||||
|
memset (ptr, 0, PTR_SIZE);
|
||||||
|
put_elf_reloc (s1->symtab, s, ptr - s->data, R_DATA_PTR, sym->c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ST_FUNC void add_init_array (TCCState *s1, Sym *sym)
|
||||||
|
{
|
||||||
|
add_array (".init_array", s1, sym);
|
||||||
|
}
|
||||||
|
|
||||||
|
ST_FUNC void add_fini_array (TCCState *s1, Sym *sym)
|
||||||
|
{
|
||||||
|
add_array (".fini_array", s1, sym);
|
||||||
|
}
|
||||||
|
|
||||||
ST_FUNC void tcc_add_bcheck(TCCState *s1)
|
ST_FUNC void tcc_add_bcheck(TCCState *s1)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
@ -2081,6 +2110,7 @@ static void fill_unloadable_phdr(ElfW(Phdr) *phdr, int phnum, Section *interp,
|
|||||||
static void fill_dynamic(TCCState *s1, struct dyn_inf *dyninf)
|
static void fill_dynamic(TCCState *s1, struct dyn_inf *dyninf)
|
||||||
{
|
{
|
||||||
Section *dynamic = dyninf->dynamic;
|
Section *dynamic = dyninf->dynamic;
|
||||||
|
Section *s;
|
||||||
|
|
||||||
/* put dynamic section entries */
|
/* put dynamic section entries */
|
||||||
put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
|
put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
|
||||||
@ -2109,6 +2139,29 @@ static void fill_dynamic(TCCState *s1, struct dyn_inf *dyninf)
|
|||||||
put_dt(dynamic, DT_VERNEED, verneed_section->sh_addr);
|
put_dt(dynamic, DT_VERNEED, verneed_section->sh_addr);
|
||||||
put_dt(dynamic, DT_VERNEEDNUM, dt_verneednum);
|
put_dt(dynamic, DT_VERNEEDNUM, dt_verneednum);
|
||||||
put_dt(dynamic, DT_VERSYM, versym_section->sh_addr);
|
put_dt(dynamic, DT_VERSYM, versym_section->sh_addr);
|
||||||
|
s = find_section_create (s1, ".preinit_array", 0);
|
||||||
|
if (s && s->data_offset) {
|
||||||
|
put_dt(dynamic, DT_PREINIT_ARRAY, s->sh_addr);
|
||||||
|
put_dt(dynamic, DT_PREINIT_ARRAYSZ, s->data_offset);
|
||||||
|
}
|
||||||
|
s = find_section_create (s1, ".init_array", 0);
|
||||||
|
if (s && s->data_offset) {
|
||||||
|
put_dt(dynamic, DT_INIT_ARRAY, s->sh_addr);
|
||||||
|
put_dt(dynamic, DT_INIT_ARRAYSZ, s->data_offset);
|
||||||
|
}
|
||||||
|
s = find_section_create (s1, ".fini_array", 0);
|
||||||
|
if (s && s->data_offset) {
|
||||||
|
put_dt(dynamic, DT_FINI_ARRAY, s->sh_addr);
|
||||||
|
put_dt(dynamic, DT_FINI_ARRAYSZ, s->data_offset);
|
||||||
|
}
|
||||||
|
s = find_section_create (s1, ".init", 0);
|
||||||
|
if (s && s->data_offset) {
|
||||||
|
put_dt(dynamic, DT_INIT, s->sh_addr);
|
||||||
|
}
|
||||||
|
s = find_section_create (s1, ".fini", 0);
|
||||||
|
if (s && s->data_offset) {
|
||||||
|
put_dt(dynamic, DT_FINI, s->sh_addr);
|
||||||
|
}
|
||||||
if (s1->do_debug)
|
if (s1->do_debug)
|
||||||
put_dt(dynamic, DT_DEBUG, 0);
|
put_dt(dynamic, DT_DEBUG, 0);
|
||||||
put_dt(dynamic, DT_NULL, 0);
|
put_dt(dynamic, DT_NULL, 0);
|
||||||
|
21
tccgen.c
21
tccgen.c
@ -3578,6 +3578,14 @@ redo:
|
|||||||
skip(')');
|
skip(')');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case TOK_CONSTRUCTOR1:
|
||||||
|
case TOK_CONSTRUCTOR2:
|
||||||
|
ad->a.constructor = 1;
|
||||||
|
break;
|
||||||
|
case TOK_DESTRUCTOR1:
|
||||||
|
case TOK_DESTRUCTOR2:
|
||||||
|
ad->a.destructor = 1;
|
||||||
|
break;
|
||||||
case TOK_SECTION1:
|
case TOK_SECTION1:
|
||||||
case TOK_SECTION2:
|
case TOK_SECTION2:
|
||||||
skip('(');
|
skip('(');
|
||||||
@ -7560,7 +7568,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
|
|||||||
|
|
||||||
/* parse a function defined by symbol 'sym' and generate its code in
|
/* parse a function defined by symbol 'sym' and generate its code in
|
||||||
'cur_text_section' */
|
'cur_text_section' */
|
||||||
static void gen_function(Sym *sym)
|
static void gen_function(Sym *sym, AttributeDef *ad)
|
||||||
{
|
{
|
||||||
/* Initialize VLA state */
|
/* Initialize VLA state */
|
||||||
struct scope f = { 0 };
|
struct scope f = { 0 };
|
||||||
@ -7576,6 +7584,13 @@ static void gen_function(Sym *sym)
|
|||||||
/* NOTE: we patch the symbol size later */
|
/* NOTE: we patch the symbol size later */
|
||||||
put_extern_sym(sym, cur_text_section, ind, 0);
|
put_extern_sym(sym, cur_text_section, ind, 0);
|
||||||
|
|
||||||
|
if (ad && ad->a.constructor) {
|
||||||
|
add_init_array (tcc_state, sym);
|
||||||
|
}
|
||||||
|
if (ad && ad->a.destructor) {
|
||||||
|
add_fini_array (tcc_state, sym);
|
||||||
|
}
|
||||||
|
|
||||||
funcname = get_tok_str(sym->v, NULL);
|
funcname = get_tok_str(sym->v, NULL);
|
||||||
func_ind = ind;
|
func_ind = ind;
|
||||||
|
|
||||||
@ -7634,7 +7649,7 @@ static void gen_inline_functions(TCCState *s)
|
|||||||
begin_macro(fn->func_str, 1);
|
begin_macro(fn->func_str, 1);
|
||||||
next();
|
next();
|
||||||
cur_text_section = text_section;
|
cur_text_section = text_section;
|
||||||
gen_function(sym);
|
gen_function(sym, NULL);
|
||||||
end_macro();
|
end_macro();
|
||||||
|
|
||||||
inline_generated = 1;
|
inline_generated = 1;
|
||||||
@ -7814,7 +7829,7 @@ static int decl0(int l, int is_for_loop_init, Sym *func_sym)
|
|||||||
cur_text_section = ad.section;
|
cur_text_section = ad.section;
|
||||||
if (!cur_text_section)
|
if (!cur_text_section)
|
||||||
cur_text_section = text_section;
|
cur_text_section = text_section;
|
||||||
gen_function(sym);
|
gen_function(sym, &ad);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
|
4
tcctok.h
4
tcctok.h
@ -127,6 +127,10 @@
|
|||||||
DEF(TOK_REGPARM2, "__regparm__")
|
DEF(TOK_REGPARM2, "__regparm__")
|
||||||
DEF(TOK_CLEANUP1, "cleanup")
|
DEF(TOK_CLEANUP1, "cleanup")
|
||||||
DEF(TOK_CLEANUP2, "__cleanup__")
|
DEF(TOK_CLEANUP2, "__cleanup__")
|
||||||
|
DEF(TOK_CONSTRUCTOR1, "constructor")
|
||||||
|
DEF(TOK_CONSTRUCTOR2, "__constructor__")
|
||||||
|
DEF(TOK_DESTRUCTOR1, "destructor")
|
||||||
|
DEF(TOK_DESTRUCTOR2, "__destructor__")
|
||||||
|
|
||||||
DEF(TOK_MODE, "__mode__")
|
DEF(TOK_MODE, "__mode__")
|
||||||
DEF(TOK_MODE_QI, "__QI__")
|
DEF(TOK_MODE_QI, "__QI__")
|
||||||
|
20
tests/tests2/108_constructor.c
Normal file
20
tests/tests2/108_constructor.c
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
extern int write (int fd, void *buf, int len);
|
||||||
|
|
||||||
|
static void __attribute__ ((constructor))
|
||||||
|
testc (void)
|
||||||
|
{
|
||||||
|
write (1, "constructor\n", 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __attribute__ ((destructor))
|
||||||
|
testd (void)
|
||||||
|
{
|
||||||
|
write (1, "destructor\n", 11);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (void)
|
||||||
|
{
|
||||||
|
write (1, "main\n", 5);
|
||||||
|
return 0;
|
||||||
|
}
|
3
tests/tests2/108_constructor.expect
Normal file
3
tests/tests2/108_constructor.expect
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
constructor
|
||||||
|
main
|
||||||
|
destructor
|
@ -33,6 +33,7 @@ ifeq (-$(CONFIG_WIN32)-$(CONFIG_i386)$(CONFIG_arm)-,--yes-)
|
|||||||
endif
|
endif
|
||||||
ifneq (-$(CONFIG_WIN32)$(CONFIG_WIN64)-,--)
|
ifneq (-$(CONFIG_WIN32)$(CONFIG_WIN64)-,--)
|
||||||
SKIP += 106_pthread.test # No pthread support
|
SKIP += 106_pthread.test # No pthread support
|
||||||
|
SKIP += 108_constructor.test # No contructor/destructor support
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Some tests might need arguments
|
# Some tests might need arguments
|
||||||
@ -67,6 +68,9 @@ GEN-ALWAYS =
|
|||||||
106_pthread.test: FLAGS += -pthread
|
106_pthread.test: FLAGS += -pthread
|
||||||
106_pthread.test: NORUN = true
|
106_pthread.test: NORUN = true
|
||||||
|
|
||||||
|
# constructor/destructor
|
||||||
|
108_constructor.test: NORUN = true
|
||||||
|
|
||||||
# Filter source directory in warnings/errors (out-of-tree builds)
|
# Filter source directory in warnings/errors (out-of-tree builds)
|
||||||
FILTER = 2>&1 | sed 's,$(SRC)/,,g'
|
FILTER = 2>&1 | sed 's,$(SRC)/,,g'
|
||||||
# Filter some always-warning
|
# Filter some always-warning
|
||||||
|
Loading…
Reference in New Issue
Block a user