Add constructor/destructor support

This commit is contained in:
herman ten brugge 2019-10-29 07:02:58 +01:00
parent c4c5ea4381
commit 800c3a5e0b
7 changed files with 112 additions and 8 deletions

7
tcc.h
View File

@ -468,7 +468,9 @@ struct SymAttr {
dllexport : 1,
nodecorate : 1,
dllimport : 1,
unused : 4;
constructor : 1,
destructor : 1,
unused : 2;
};
/* 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
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_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);

View File

@ -339,9 +339,7 @@ ST_FUNC void section_reserve(Section *sec, unsigned long size)
sec->data_offset = size;
}
/* return a reference to a section, and create it if it does not
exists */
ST_FUNC Section *find_section(TCCState *s1, const char *name)
static Section *find_section_create (TCCState *s1, const char *name, int create)
{
Section *sec;
int i;
@ -351,7 +349,14 @@ ST_FUNC Section *find_section(TCCState *s1, const char *name)
return sec;
}
/* 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
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)
{
#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)
{
Section *dynamic = dyninf->dynamic;
Section *s;
/* put dynamic section entries */
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_VERNEEDNUM, dt_verneednum);
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)
put_dt(dynamic, DT_DEBUG, 0);
put_dt(dynamic, DT_NULL, 0);

View File

@ -3578,6 +3578,14 @@ redo:
skip(')');
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_SECTION2:
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
'cur_text_section' */
static void gen_function(Sym *sym)
static void gen_function(Sym *sym, AttributeDef *ad)
{
/* Initialize VLA state */
struct scope f = { 0 };
@ -7576,6 +7584,13 @@ static void gen_function(Sym *sym)
/* NOTE: we patch the symbol size later */
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);
func_ind = ind;
@ -7634,7 +7649,7 @@ static void gen_inline_functions(TCCState *s)
begin_macro(fn->func_str, 1);
next();
cur_text_section = text_section;
gen_function(sym);
gen_function(sym, NULL);
end_macro();
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;
if (!cur_text_section)
cur_text_section = text_section;
gen_function(sym);
gen_function(sym, &ad);
}
break;
} else {

View File

@ -127,6 +127,10 @@
DEF(TOK_REGPARM2, "__regparm__")
DEF(TOK_CLEANUP1, "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_QI, "__QI__")

View 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;
}

View File

@ -0,0 +1,3 @@
constructor
main
destructor

View File

@ -33,6 +33,7 @@ ifeq (-$(CONFIG_WIN32)-$(CONFIG_i386)$(CONFIG_arm)-,--yes-)
endif
ifneq (-$(CONFIG_WIN32)$(CONFIG_WIN64)-,--)
SKIP += 106_pthread.test # No pthread support
SKIP += 108_constructor.test # No contructor/destructor support
endif
# Some tests might need arguments
@ -67,6 +68,9 @@ GEN-ALWAYS =
106_pthread.test: FLAGS += -pthread
106_pthread.test: NORUN = true
# constructor/destructor
108_constructor.test: NORUN = true
# Filter source directory in warnings/errors (out-of-tree builds)
FILTER = 2>&1 | sed 's,$(SRC)/,,g'
# Filter some always-warning