History

Add constructor/destructor support

herman ten brugge committed 7 years ago

Commit 800c3a51 parent c4c5ea47 files · +112 −8Browse files

Unified · Split

7 files
  1. tcc.h +6 −1
  2. tccelf.c +57 −4
  3. tccgen.c +18 −3
  4. tcctok.h +4 −0
  5. tests/tests2/108_constructor.c +20 −0
  6. tests/tests2/108_constructor.expect +3 −0
  7. tests/tests2/Makefile +4 −0
tcc.h+6−1
@@ -468,7 +468,9 @@ struct SymAttr { · 467 unmodified lines
468468 dllexport : 1,
469469 nodecorate : 1,
470470 dllimport : 1,
471− unused : 4;
471+ constructor : 1,
472+ destructor : 1,
473+ unused : 2;
472474 };
473475
474476 /* function attributes or temporary attributes for parsing */
@@ -1443,6 +1445,9 @@ ST_FUNC void greloc(Section *s, Sym *sym, unsigned long offset, int type); · 968 unmodified lines
14431445 #endif
14441446 ST_FUNC void greloca(Section *s, Sym *sym, unsigned long offset, int type, addr_t addend);
14451447
1448+ST_FUNC void add_init_array (TCCState *s1, Sym *sym);
1449+ST_FUNC void add_fini_array (TCCState *s1, Sym *sym);
1450+
14461451 ST_FUNC int put_elf_str(Section *s, const char *sym);
14471452 ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name);
14481453 ST_FUNC int set_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name);
tccelf.c+57−4
@@ -339,9 +339,7 @@ ST_FUNC void section_reserve(Section *sec, unsigned long size) · 338 unmodified lines
339339 sec->data_offset = size;
340340 }
341341
342−/* return a reference to a section, and create it if it does not
343− exists */
344−ST_FUNC Section *find_section(TCCState *s1, const char *name)
342+static Section *find_section_create (TCCState *s1, const char *name, int create)
345343 {
346344 Section *sec;
347345 int i;
@@ -351,7 +349,14 @@ ST_FUNC Section *find_section(TCCState *s1, const char *name) · 3 unmodified lines
351349 return sec;
352350 }
353351 /* sections are created as PROGBITS */
354− return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
352+ return create ? new_section(s1, name, SHT_PROGBITS, SHF_ALLOC) : NULL;
353+}
354+
355+/* return a reference to a section, and create it if it does not
356+ exists */
357+ST_FUNC Section *find_section(TCCState *s1, const char *name)
358+{
359+ return find_section_create (s1, name, 1);
355360 }
356361
357362 /* ------------------------------------------------------------------------- */
@@ -1436,6 +1441,30 @@ static int tcc_add_support(TCCState *s1, const char *filename) · 1078 unmodified lines
14361441 }
14371442 #endif
14381443
1444+static void add_array (const char *section, TCCState *s1, Sym *sym)
1445+{
1446+ Section *s;
1447+ unsigned char *ptr;
1448+
1449+ s = find_section(s1, section);
1450+ if (s) {
1451+ s->sh_flags |= SHF_WRITE;
1452+ ptr = section_ptr_add(s, PTR_SIZE);
1453+ memset (ptr, 0, PTR_SIZE);
1454+ put_elf_reloc (s1->symtab, s, ptr - s->data, R_DATA_PTR, sym->c);
1455+ }
1456+}
1457+
1458+ST_FUNC void add_init_array (TCCState *s1, Sym *sym)
1459+{
1460+ add_array (".init_array", s1, sym);
1461+}
1462+
1463+ST_FUNC void add_fini_array (TCCState *s1, Sym *sym)
1464+{
1465+ add_array (".fini_array", s1, sym);
1466+}
1467+
14391468 ST_FUNC void tcc_add_bcheck(TCCState *s1)
14401469 {
14411470 #ifdef CONFIG_TCC_BCHECK
@@ -2081,6 +2110,7 @@ static void fill_unloadable_phdr(ElfW(Phdr) *phdr, int phnum, Section *interp, · 639 unmodified lines
20812110 static void fill_dynamic(TCCState *s1, struct dyn_inf *dyninf)
20822111 {
20832112 Section *dynamic = dyninf->dynamic;
2113+ Section *s;
20842114
20852115 /* put dynamic section entries */
20862116 put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
@@ -2109,6 +2139,29 @@ static void fill_dynamic(TCCState *s1, struct dyn_inf *dyninf) · 22 unmodified lines
21092139 put_dt(dynamic, DT_VERNEED, verneed_section->sh_addr);
21102140 put_dt(dynamic, DT_VERNEEDNUM, dt_verneednum);
21112141 put_dt(dynamic, DT_VERSYM, versym_section->sh_addr);
2142+ s = find_section_create (s1, ".preinit_array", 0);
2143+ if (s && s->data_offset) {
2144+ put_dt(dynamic, DT_PREINIT_ARRAY, s->sh_addr);
2145+ put_dt(dynamic, DT_PREINIT_ARRAYSZ, s->data_offset);
2146+ }
2147+ s = find_section_create (s1, ".init_array", 0);
2148+ if (s && s->data_offset) {
2149+ put_dt(dynamic, DT_INIT_ARRAY, s->sh_addr);
2150+ put_dt(dynamic, DT_INIT_ARRAYSZ, s->data_offset);
2151+ }
2152+ s = find_section_create (s1, ".fini_array", 0);
2153+ if (s && s->data_offset) {
2154+ put_dt(dynamic, DT_FINI_ARRAY, s->sh_addr);
2155+ put_dt(dynamic, DT_FINI_ARRAYSZ, s->data_offset);
2156+ }
2157+ s = find_section_create (s1, ".init", 0);
2158+ if (s && s->data_offset) {
2159+ put_dt(dynamic, DT_INIT, s->sh_addr);
2160+ }
2161+ s = find_section_create (s1, ".fini", 0);
2162+ if (s && s->data_offset) {
2163+ put_dt(dynamic, DT_FINI, s->sh_addr);
2164+ }
21122165 if (s1->do_debug)
21132166 put_dt(dynamic, DT_DEBUG, 0);
21142167 put_dt(dynamic, DT_NULL, 0);
tccgen.c+18−3
@@ -3578,6 +3578,14 @@ redo: · 3577 unmodified lines
35783578 skip(')');
35793579 break;
35803580 }
3581+ case TOK_CONSTRUCTOR1:
3582+ case TOK_CONSTRUCTOR2:
3583+ ad->a.constructor = 1;
3584+ break;
3585+ case TOK_DESTRUCTOR1:
3586+ case TOK_DESTRUCTOR2:
3587+ ad->a.destructor = 1;
3588+ break;
35813589 case TOK_SECTION1:
35823590 case TOK_SECTION2:
35833591 skip('(');
@@ -7560,7 +7568,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 3976 unmodified lines
75607568
75617569 /* parse a function defined by symbol 'sym' and generate its code in
75627570 'cur_text_section' */
7563−static void gen_function(Sym *sym)
7571+static void gen_function(Sym *sym, AttributeDef *ad)
75647572 {
75657573 /* Initialize VLA state */
75667574 struct scope f = { 0 };
@@ -7576,6 +7584,13 @@ static void gen_function(Sym *sym) · 9 unmodified lines
75767584 /* NOTE: we patch the symbol size later */
75777585 put_extern_sym(sym, cur_text_section, ind, 0);
75787586
7587+ if (ad && ad->a.constructor) {
7588+ add_init_array (tcc_state, sym);
7589+ }
7590+ if (ad && ad->a.destructor) {
7591+ add_fini_array (tcc_state, sym);
7592+ }
7593+
75797594 funcname = get_tok_str(sym->v, NULL);
75807595 func_ind = ind;
75817596
@@ -7634,7 +7649,7 @@ static void gen_inline_functions(TCCState *s) · 52 unmodified lines
76347649 begin_macro(fn->func_str, 1);
76357650 next();
76367651 cur_text_section = text_section;
7637− gen_function(sym);
7652+ gen_function(sym, NULL);
76387653 end_macro();
76397654
76407655 inline_generated = 1;
@@ -7814,7 +7829,7 @@ static int decl0(int l, int is_for_loop_init, Sym *func_sym) · 173 unmodified lines
78147829 cur_text_section = ad.section;
78157830 if (!cur_text_section)
78167831 cur_text_section = text_section;
7817− gen_function(sym);
7832+ gen_function(sym, &ad);
78187833 }
78197834 break;
78207835 } else {
tcctok.h+4−0
@@ -127,6 +127,10 @@ · 126 unmodified lines
127127 DEF(TOK_REGPARM2, "__regparm__")
128128 DEF(TOK_CLEANUP1, "cleanup")
129129 DEF(TOK_CLEANUP2, "__cleanup__")
130+ DEF(TOK_CONSTRUCTOR1, "constructor")
131+ DEF(TOK_CONSTRUCTOR2, "__constructor__")
132+ DEF(TOK_DESTRUCTOR1, "destructor")
133+ DEF(TOK_DESTRUCTOR2, "__destructor__")
130134
131135 DEF(TOK_MODE, "__mode__")
132136 DEF(TOK_MODE_QI, "__QI__")
tests/tests2/108_constructor.c+20−0
@@ -0,0 +1,20 @@
1+extern int write (int fd, void *buf, int len);
2+
3+static void __attribute__ ((constructor))
4+testc (void)
5+{
6+ write (1, "constructor\n", 12);
7+}
8+
9+static void __attribute__ ((destructor))
10+testd (void)
11+{
12+ write (1, "destructor\n", 11);
13+}
14+
15+int
16+main (void)
17+{
18+ write (1, "main\n", 5);
19+ return 0;
20+}
tests/tests2/108_constructor.expect+3−0
@@ -0,0 +1,3 @@
1+constructor
2+main
3+destructor
tests/tests2/Makefile+4−0
@@ -33,6 +33,7 @@ ifeq (-$(CONFIG_WIN32)-$(CONFIG_i386)$(CONFIG_arm)-,--yes-) · 32 unmodified lines
3333 endif
3434 ifneq (-$(CONFIG_WIN32)$(CONFIG_WIN64)-,--)
3535 SKIP += 106_pthread.test # No pthread support
36+ SKIP += 108_constructor.test # No contructor/destructor support
3637 endif
3738
3839 # Some tests might need arguments
@@ -67,6 +68,9 @@ GEN-ALWAYS = · 28 unmodified lines
6768 106_pthread.test: FLAGS += -pthread
6869 106_pthread.test: NORUN = true
6970
71+# constructor/destructor
72+108_constructor.test: NORUN = true
73+
7074 # Filter source directory in warnings/errors (out-of-tree builds)
7175 FILTER = 2>&1 | sed 's,$(SRC)/,,g'
7276 # Filter some always-warning

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t