mirror of
https://github.com/frida/tinycc
synced 2024-11-27 18:19:35 +03: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,
|
||||
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);
|
||||
|
61
tccelf.c
61
tccelf.c
@ -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);
|
||||
|
21
tccgen.c
21
tccgen.c
@ -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 {
|
||||
|
4
tcctok.h
4
tcctok.h
@ -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__")
|
||||
|
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
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user