From 0da93838c13412eff9ab1c17586119a186af0d31 Mon Sep 17 00:00:00 2001 From: herman ten brugge Date: Thu, 1 Oct 2020 17:50:20 +0200 Subject: [PATCH] Init range wth symbols The init range with symbols did only init the first value. The relocation for all other symbols was missing. Also see testcase. tccgen.c: - New function get_init_string - Use macro processing in decl_designator for each init string - Use get_init_string in decl_initializer_alloc tccelf.c: - Fix insertion sort in squeeze_multi_relocs tests/tests2/90_struct-init.c: - Add test case test_init_ranges --- tccelf.c | 8 ++-- tccgen.c | 69 ++++++++++++++---------------- tests/tests2/90_struct-init.c | 28 ++++++++++++ tests/tests2/90_struct-init.expect | 1 + 4 files changed, 66 insertions(+), 40 deletions(-) diff --git a/tccelf.c b/tccelf.c index a213048e..c8745aa6 100644 --- a/tccelf.c +++ b/tccelf.c @@ -774,13 +774,13 @@ ST_FUNC void squeeze_multi_relocs(Section *s, size_t oldrelocoffset) a simple insertion sort. */ for (a = oldrelocoffset + sizeof(*r); a < sr->data_offset; a += sizeof(*r)) { ssize_t i = a - sizeof(*r); - addr = ((ElfW_Rel*)(sr->data + a))->r_offset; + ElfW_Rel tmp = *(ElfW_Rel*)(sr->data + a); + addr = tmp.r_offset; for (; i >= (ssize_t)oldrelocoffset && ((ElfW_Rel*)(sr->data + i))->r_offset > addr; i -= sizeof(*r)) { - ElfW_Rel tmp = *(ElfW_Rel*)(sr->data + a); - *(ElfW_Rel*)(sr->data + a) = *(ElfW_Rel*)(sr->data + i); - *(ElfW_Rel*)(sr->data + i) = tmp; + *(ElfW_Rel*)(sr->data + i + sizeof(*r)) = *(ElfW_Rel*)(sr->data + i); } + *(ElfW_Rel*)(sr->data + i + sizeof(*r)) = tmp; } r = (ElfW_Rel*)(sr->data + oldrelocoffset); diff --git a/tccgen.c b/tccgen.c index 73bc7d72..136e4b80 100644 --- a/tccgen.c +++ b/tccgen.c @@ -7296,6 +7296,23 @@ static void skip_or_save_block(TokenString **str) } } +static void get_init_string(TokenString **str, int has_init) +{ + if (has_init == 2) { + *str = tok_str_alloc(); + /* only get strings */ + while (tok == TOK_STR || tok == TOK_LSTR) { + tok_str_add_tok(*str); + next(); + } + tok_str_add(*str, -1); + tok_str_add(*str, 0); + } + else + skip_or_save_block(str); + unget_tok(0); +} + #define EXPR_CONST 1 #define EXPR_ANY 2 @@ -7361,6 +7378,7 @@ static int decl_designator(CType *type, Section *sec, unsigned long c, Sym *s, *f; int index, index_last, align, l, nb_elems, elem_size; unsigned long corig = c; + TokenString *init_str = NULL; elem_size = 0; nb_elems = 1; @@ -7454,34 +7472,26 @@ static int decl_designator(CType *type, Section *sec, unsigned long c, init_putz(sec, corig + al, zlen); } + if (!(flags & DIF_SIZE_ONLY) && nb_elems > 1) { + get_init_string(&init_str, tok == TOK_STR || tok == TOK_LSTR ? 2 : 0); + begin_macro(init_str, 1); + next(); + } + decl_initializer(type, sec, c, flags & ~DIF_FIRST); - /* XXX: make it more general */ if (!(flags & DIF_SIZE_ONLY) && nb_elems > 1) { - unsigned long c_end; - uint8_t *src, *dst; int i; - if (!sec) { - vset(type, VT_LOCAL|VT_LVAL, c); - for (i = 1; i < nb_elems; i++) { - vset(type, VT_LOCAL|VT_LVAL, c + elem_size * i); - vswap(); - vstore(); - } - vpop(); - } else if (!NODATA_WANTED) { - c_end = c + nb_elems * elem_size; - if (c_end > sec->data_allocated) - section_realloc(sec, c_end); - src = sec->data + c; - dst = src; - for(i = 1; i < nb_elems; i++) { - dst += elem_size; - memcpy(dst, src, elem_size); - } - } + for(i = 1; i < nb_elems; i++) { + macro_ptr = init_str->str; + next(); + decl_initializer(type, sec, c + i * elem_size, flags & ~DIF_FIRST); + } + end_macro(); + next(); } + c += nb_elems * type_size(type, &align); if (c - corig > al) al = c - corig; @@ -7919,20 +7929,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, if (size < 0 || (flexible_array && has_init)) { if (!has_init) tcc_error("unknown type size"); - /* get all init string */ - if (has_init == 2) { - init_str = tok_str_alloc(); - /* only get strings */ - while (tok == TOK_STR || tok == TOK_LSTR) { - tok_str_add_tok(init_str); - next(); - } - tok_str_add(init_str, -1); - tok_str_add(init_str, 0); - } else { - skip_or_save_block(&init_str); - } - unget_tok(0); + get_init_string(&init_str, has_init); /* compute size */ begin_macro(init_str, 1); diff --git a/tests/tests2/90_struct-init.c b/tests/tests2/90_struct-init.c index ade7fad7..e3535bd0 100644 --- a/tests/tests2/90_struct-init.c +++ b/tests/tests2/90_struct-init.c @@ -235,6 +235,33 @@ void test_multi_relocs(void) for (i = 0; i < sizeof(table)/sizeof(table[0]); i++) table[i](); } + +void test_init_ranges(void) { + int i,c=0; + static void *gostring[] = { + [0 ... 31] = &&l_bad, [127] = &&l_bad, + [32 ... 126] = &&l_loop, + ['\\'] = &&l_esc, ['"'] = &&l_qdown, + [128 ... 191] = &&l_bad, + [192 ... 223] = &&l_utf8_2, + [224 ... 239] = &&l_utf8_3, + [240 ... 247] = &&l_utf8_4, + [248 ... 255] = &&l_bad + }; + + for (i = 0; i < 256; i++) { + goto *gostring[i]; + l_bad: c++; + l_loop: c++; + l_esc: c++; + l_qdown: c++; + l_utf8_2: c++; + l_utf8_3: c++; + l_utf8_4: c++; + } + printf ("%d\n", c); +} + /* Following is from GCC gcc.c-torture/execute/20050613-1.c. */ @@ -298,5 +325,6 @@ int main() test_compound_with_relocs(); test_multi_relocs(); test_zero_init(); + test_init_ranges(); return 0; } diff --git a/tests/tests2/90_struct-init.expect b/tests/tests2/90_struct-init.expect index c55cb476..70b9de1b 100644 --- a/tests/tests2/90_struct-init.expect +++ b/tests/tests2/90_struct-init.expect @@ -46,3 +46,4 @@ three sea_fill0: okay sea_fill1: okay sea_fill2: okay +1438