Unified · Split
| @@ -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 | #endif | 1445 | #endif |
| 1444 | ST_FUNC void greloca(Section *s, Sym *sym, unsigned long offset, int type, addr_t addend); | 1446 | ST_FUNC void greloca(Section *s, Sym *sym, unsigned long offset, int type, addr_t addend); |
| 1445 | 1447 | ||
| 1448 | ST_FUNC void add_init_array (TCCState *s1, Sym *sym); | ||
| 1449 | ST_FUNC void add_fini_array (TCCState *s1, Sym *sym); | ||
| 1450 | |||
| 1446 | ST_FUNC int put_elf_str(Section *s, const char *sym); | 1451 | ST_FUNC int put_elf_str(Section *s, const char *sym); |
| 1447 | ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name); | 1452 | ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name); |
| 1448 | ST_FUNC int set_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name); | 1453 | ST_FUNC int set_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name); |
| @@ -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 not | 342 | static Section *find_section_create (TCCState *s1, const char *name, int create) |
| 343 | exists */ | ||
| 344 | ST_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 */ | ||
| 357 | ST_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 | #endif | 1442 | #endif |
| 1438 | 1443 | ||
| 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 | |||
| 1439 | ST_FUNC void tcc_add_bcheck(TCCState *s1) | 1468 | ST_FUNC void tcc_add_bcheck(TCCState *s1) |
| 1440 | { | 1469 | { |
| 1441 | #ifdef CONFIG_TCC_BCHECK | 1470 | #ifdef CONFIG_TCC_BCHECK |
| @@ -2081,6 +2110,7 @@ static void fill_unloadable_phdr(ElfW(Phdr) *phdr, int phnum, Section *interp, · 639 unmodified lines | |||
| 2081 | static void fill_dynamic(TCCState *s1, struct dyn_inf *dyninf) | 2110 | static 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); |
| @@ -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 in | 7569 | /* parse a function defined by symbol 'sym' and generate its code in |
| 7562 | 'cur_text_section' */ | 7570 | 'cur_text_section' */ |
| 7563 | static void gen_function(Sym *sym) | 7571 | static 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 { |
| @@ -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__") |
| @@ -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 | } | ||
| @@ -0,0 +1,3 @@ | |||
| 1 | constructor | ||
| 2 | main | ||
| 3 | destructor | ||
| @@ -33,6 +33,7 @@ ifeq (-$(CONFIG_WIN32)-$(CONFIG_i386)$(CONFIG_arm)-,--yes-) · 32 unmodified lines | |||
| 33 | endif | 33 | endif |
| 34 | ifneq (-$(CONFIG_WIN32)$(CONFIG_WIN64)-,--) | 34 | ifneq (-$(CONFIG_WIN32)$(CONFIG_WIN64)-,--) |
| 35 | SKIP += 106_pthread.test # No pthread support | 35 | SKIP += 106_pthread.test # No pthread support |
| 36 | SKIP += 108_constructor.test # No contructor/destructor support | ||
| 36 | endif | 37 | endif |
| 37 | 38 | ||
| 38 | # Some tests might need arguments | 39 | # Some tests might need arguments |
| @@ -67,6 +68,9 @@ GEN-ALWAYS = · 28 unmodified lines | |||
| 67 | 106_pthread.test: FLAGS += -pthread | 68 | 106_pthread.test: FLAGS += -pthread |
| 68 | 106_pthread.test: NORUN = true | 69 | 106_pthread.test: NORUN = true |
| 69 | 70 | ||
| 71 | # constructor/destructor | ||
| 72 | 108_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) |
| 71 | FILTER = 2>&1 | sed 's,$(SRC)/,,g' | 75 | FILTER = 2>&1 | sed 's,$(SRC)/,,g' |
| 72 | # Filter some always-warning | 76 | # Filter some always-warning |