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
468 dllexport : 1,468 dllexport : 1,
469 nodecorate : 1,469 nodecorate : 1,
470 dllimport : 1,470 dllimport : 1,
471 unused : 4;471 constructor : 1,
472 destructor : 1,
473 unused : 2;
472};474};
473 475
474/* function attributes or temporary attributes for parsing */476/* 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
1443#endif1445#endif
1444ST_FUNC void greloca(Section *s, Sym *sym, unsigned long offset, int type, addr_t addend);1446ST_FUNC void greloca(Section *s, Sym *sym, unsigned long offset, int type, addr_t addend);
1445 1447
1448ST_FUNC void add_init_array (TCCState *s1, Sym *sym);
1449ST_FUNC void add_fini_array (TCCState *s1, Sym *sym);
1450
1446ST_FUNC int put_elf_str(Section *s, const char *sym);1451ST_FUNC int put_elf_str(Section *s, const char *sym);
1447ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name);1452ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name);
1448ST_FUNC int set_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name);1453ST_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
339 sec->data_offset = size;339 sec->data_offset = size;
340}340}
341 341
342/* return a reference to a section, and create it if it does not342static Section *find_section_create (TCCState *s1, const char *name, int create)
343 exists */
344ST_FUNC Section *find_section(TCCState *s1, const char *name)
345{343{
346 Section *sec;344 Section *sec;
347 int i;345 int i;
@@ -351,7 +349,14 @@ ST_FUNC Section *find_section(TCCState *s1, const char *name) · 3 unmodified lines
351 return sec;349 return sec;
352 }350 }
353 /* sections are created as PROGBITS */351 /* 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 */
357ST_FUNC Section *find_section(TCCState *s1, const char *name)
358{
359 return find_section_create (s1, name, 1);
355}360}
356 361
357/* ------------------------------------------------------------------------- */362/* ------------------------------------------------------------------------- */
@@ -1436,6 +1441,30 @@ static int tcc_add_support(TCCState *s1, const char *filename) · 1078 unmodified lines
1436}1441}
1437#endif1442#endif
1438 1443
1444static 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
1458ST_FUNC void add_init_array (TCCState *s1, Sym *sym)
1459{
1460 add_array (".init_array", s1, sym);
1461}
1462
1463ST_FUNC void add_fini_array (TCCState *s1, Sym *sym)
1464{
1465 add_array (".fini_array", s1, sym);
1466}
1467
1439ST_FUNC void tcc_add_bcheck(TCCState *s1)1468ST_FUNC void tcc_add_bcheck(TCCState *s1)
1440{1469{
1441#ifdef CONFIG_TCC_BCHECK1470#ifdef CONFIG_TCC_BCHECK
@@ -2081,6 +2110,7 @@ static void fill_unloadable_phdr(ElfW(Phdr) *phdr, int phnum, Section *interp, · 639 unmodified lines
2081static void fill_dynamic(TCCState *s1, struct dyn_inf *dyninf)2110static void fill_dynamic(TCCState *s1, struct dyn_inf *dyninf)
2082{2111{
2083 Section *dynamic = dyninf->dynamic;2112 Section *dynamic = dyninf->dynamic;
2113 Section *s;
2084 2114
2085 /* put dynamic section entries */2115 /* put dynamic section entries */
2086 put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);2116 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
2109 put_dt(dynamic, DT_VERNEED, verneed_section->sh_addr);2139 put_dt(dynamic, DT_VERNEED, verneed_section->sh_addr);
2110 put_dt(dynamic, DT_VERNEEDNUM, dt_verneednum);2140 put_dt(dynamic, DT_VERNEEDNUM, dt_verneednum);
2111 put_dt(dynamic, DT_VERSYM, versym_section->sh_addr);2141 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 }
2112 if (s1->do_debug)2165 if (s1->do_debug)
2113 put_dt(dynamic, DT_DEBUG, 0);2166 put_dt(dynamic, DT_DEBUG, 0);
2114 put_dt(dynamic, DT_NULL, 0);2167 put_dt(dynamic, DT_NULL, 0);
tccgen.c+18−3
@@ -3578,6 +3578,14 @@ redo: · 3577 unmodified lines
3578 skip(')');3578 skip(')');
3579 break;3579 break;
3580 }3580 }
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;
3581 case TOK_SECTION1:3589 case TOK_SECTION1:
3582 case TOK_SECTION2:3590 case TOK_SECTION2:
3583 skip('(');3591 skip('(');
@@ -7560,7 +7568,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 3976 unmodified lines
7560 7568
7561/* parse a function defined by symbol 'sym' and generate its code in7569/* parse a function defined by symbol 'sym' and generate its code in
7562 'cur_text_section' */7570 'cur_text_section' */
7563static void gen_function(Sym *sym)7571static void gen_function(Sym *sym, AttributeDef *ad)
7564{7572{
7565 /* Initialize VLA state */7573 /* Initialize VLA state */
7566 struct scope f = { 0 };7574 struct scope f = { 0 };
@@ -7576,6 +7584,13 @@ static void gen_function(Sym *sym) · 9 unmodified lines
7576 /* NOTE: we patch the symbol size later */7584 /* NOTE: we patch the symbol size later */
7577 put_extern_sym(sym, cur_text_section, ind, 0);7585 put_extern_sym(sym, cur_text_section, ind, 0);
7578 7586
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
7579 funcname = get_tok_str(sym->v, NULL);7594 funcname = get_tok_str(sym->v, NULL);
7580 func_ind = ind;7595 func_ind = ind;
7581 7596
@@ -7634,7 +7649,7 @@ static void gen_inline_functions(TCCState *s) · 52 unmodified lines
7634 begin_macro(fn->func_str, 1);7649 begin_macro(fn->func_str, 1);
7635 next();7650 next();
7636 cur_text_section = text_section;7651 cur_text_section = text_section;
7637 gen_function(sym);7652 gen_function(sym, NULL);
7638 end_macro();7653 end_macro();
7639 7654
7640 inline_generated = 1;7655 inline_generated = 1;
@@ -7814,7 +7829,7 @@ static int decl0(int l, int is_for_loop_init, Sym *func_sym) · 173 unmodified lines
7814 cur_text_section = ad.section;7829 cur_text_section = ad.section;
7815 if (!cur_text_section)7830 if (!cur_text_section)
7816 cur_text_section = text_section;7831 cur_text_section = text_section;
7817 gen_function(sym);7832 gen_function(sym, &ad);
7818 }7833 }
7819 break;7834 break;
7820 } else {7835 } else {
tcctok.h+4−0
@@ -127,6 +127,10 @@ · 126 unmodified lines
127 DEF(TOK_REGPARM2, "__regparm__")127 DEF(TOK_REGPARM2, "__regparm__")
128 DEF(TOK_CLEANUP1, "cleanup")128 DEF(TOK_CLEANUP1, "cleanup")
129 DEF(TOK_CLEANUP2, "__cleanup__")129 DEF(TOK_CLEANUP2, "__cleanup__")
130 DEF(TOK_CONSTRUCTOR1, "constructor")
131 DEF(TOK_CONSTRUCTOR2, "__constructor__")
132 DEF(TOK_DESTRUCTOR1, "destructor")
133 DEF(TOK_DESTRUCTOR2, "__destructor__")
130 134
131 DEF(TOK_MODE, "__mode__")135 DEF(TOK_MODE, "__mode__")
132 DEF(TOK_MODE_QI, "__QI__")136 DEF(TOK_MODE_QI, "__QI__")
tests/tests2/108_constructor.c+20−0
@@ -0,0 +1,20 @@
1extern int write (int fd, void *buf, int len);
2
3static void __attribute__ ((constructor))
4testc (void)
5{
6 write (1, "constructor\n", 12);
7}
8
9static void __attribute__ ((destructor))
10testd (void)
11{
12 write (1, "destructor\n", 11);
13}
14
15int
16main (void)
17{
18 write (1, "main\n", 5);
19 return 0;
20}
tests/tests2/108_constructor.expect+3−0
@@ -0,0 +1,3 @@
1constructor
2main
3destructor
tests/tests2/Makefile+4−0
@@ -33,6 +33,7 @@ ifeq (-$(CONFIG_WIN32)-$(CONFIG_i386)$(CONFIG_arm)-,--yes-) · 32 unmodified lines
33endif33endif
34ifneq (-$(CONFIG_WIN32)$(CONFIG_WIN64)-,--)34ifneq (-$(CONFIG_WIN32)$(CONFIG_WIN64)-,--)
35 SKIP += 106_pthread.test # No pthread support35 SKIP += 106_pthread.test # No pthread support
36 SKIP += 108_constructor.test # No contructor/destructor support
36endif37endif
37 38
38# Some tests might need arguments39# Some tests might need arguments
@@ -67,6 +68,9 @@ GEN-ALWAYS = · 28 unmodified lines
67106_pthread.test: FLAGS += -pthread68106_pthread.test: FLAGS += -pthread
68106_pthread.test: NORUN = true69106_pthread.test: NORUN = true
69 70
71# constructor/destructor
72108_constructor.test: NORUN = true
73
70# Filter source directory in warnings/errors (out-of-tree builds)74# Filter source directory in warnings/errors (out-of-tree builds)
71FILTER = 2>&1 | sed 's,$(SRC)/,,g'75FILTER = 2>&1 | sed 's,$(SRC)/,,g'
72# Filter some always-warning76# 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