History

Fix initializing members multiple times

When intializing members where the initializer needs relocations and the member is initialized multiple times we can't allow that to lead to multiple relocations to the same place. The last one must win.

Michael Matz committed 10 years ago

Commit ddd461d1 parent f081acb5 files · +73 −0Browse files

Unified · Split

5 files
  1. tcc.h +2 −0
  2. tccelf.c +37 −0
  3. tccgen.c +11 −0
  4. tests/tests2/86-struct-init.c +20 −0
  5. tests/tests2/86-struct-init.expect +3 −0
tcc.h+2−0
@@ -1384,6 +1384,8 @@ ST_FUNC void tcc_add_runtime(TCCState *s1); · 1383 unmodified lines
1384 1384
1385ST_FUNC void build_got_entries(TCCState *s1);1385ST_FUNC void build_got_entries(TCCState *s1);
1386ST_FUNC struct sym_attr *get_sym_attr(TCCState *s1, int index, int alloc);1386ST_FUNC struct sym_attr *get_sym_attr(TCCState *s1, int index, int alloc);
1387ST_FUNC void squeeze_multi_relocs(Section *sec, size_t oldrelocoffset);
1388
1387ST_FUNC addr_t get_elf_sym_addr(TCCState *s, const char *name, int err);1389ST_FUNC addr_t get_elf_sym_addr(TCCState *s, const char *name, int err);
1388#if defined TCC_IS_NATIVE || defined TCC_TARGET_PE1390#if defined TCC_IS_NATIVE || defined TCC_TARGET_PE
1389ST_FUNC void *tcc_get_symbol_err(TCCState *s, const char *name);1391ST_FUNC void *tcc_get_symbol_err(TCCState *s, const char *name);
tccelf.c+37−0
@@ -535,6 +535,43 @@ ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset, · 534 unmodified lines
535 put_elf_reloca(symtab, s, offset, type, symbol, 0);535 put_elf_reloca(symtab, s, offset, type, symbol, 0);
536}536}
537 537
538/* Remove relocations for section S->reloc starting at oldrelocoffset
539 that are to the same place, retaining the last of them. As side effect
540 the relocations are sorted. Possibly reduces the number of relocs. */
541ST_FUNC void squeeze_multi_relocs(Section *s, size_t oldrelocoffset)
542{
543 Section *sr = s->reloc;
544 ElfW_Rel *r, *dest;
545 ssize_t a;
546 ElfW(Addr) addr;
547
548 if (oldrelocoffset + sizeof(*r) >= sr->data_offset)
549 return;
550 /* The relocs we're dealing with are the result of initializer parsing.
551 So they will be mostly in order and there aren't many of them.
552 Secondly we need a stable sort (which qsort isn't). We use
553 a simple insertion sort. */
554 for (a = oldrelocoffset + sizeof(*r); a < sr->data_offset; a += sizeof(*r)) {
555 ssize_t i = a - sizeof(*r);
556 addr = ((ElfW_Rel*)(sr->data + a))->r_offset;
557 for (; i >= (ssize_t)oldrelocoffset &&
558 ((ElfW_Rel*)(sr->data + i))->r_offset > addr; i -= sizeof(*r)) {
559 ElfW_Rel tmp = *(ElfW_Rel*)(sr->data + a);
560 *(ElfW_Rel*)(sr->data + a) = *(ElfW_Rel*)(sr->data + i);
561 *(ElfW_Rel*)(sr->data + i) = tmp;
562 }
563 }
564
565 r = (ElfW_Rel*)(sr->data + oldrelocoffset);
566 dest = r;
567 for (; r < (ElfW_Rel*)(sr->data + sr->data_offset); r++) {
568 if (dest->r_offset != r->r_offset)
569 dest++;
570 *dest = *r;
571 }
572 sr->data_offset = (unsigned char*)dest - sr->data + sizeof(*r);
573}
574
538/* put stab debug information */575/* put stab debug information */
539 576
540ST_FUNC void put_stabs(const char *str, int type, int other, int desc,577ST_FUNC void put_stabs(const char *str, int type, int other, int desc,
tccgen.c+11−0
@@ -6019,6 +6019,12 @@ static void init_putv(CType *type, Section *sec, unsigned long c) · 6018 unmodified lines
6019 continue;6019 continue;
6020 if (rel->r_offset < esym->st_value)6020 if (rel->r_offset < esym->st_value)
6021 break;6021 break;
6022 /* Note: if the same fields are initialized multiple
6023 times (possible with designators) then we possibly
6024 add multiple relocations for the same offset here.
6025 That would lead to wrong code, the last reloc needs
6026 to win. We clean this up later after the whole
6027 initializer is parsed. */
6022 put_elf_reloca(symtab_section, sec,6028 put_elf_reloca(symtab_section, sec,
6023 c + rel->r_offset - esym->st_value,6029 c + rel->r_offset - esym->st_value,
6024 ELFW(R_TYPE)(rel->r_info),6030 ELFW(R_TYPE)(rel->r_info),
@@ -6602,7 +6608,12 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 577 unmodified lines
6602 vla_sp_loc = addr;6608 vla_sp_loc = addr;
6603 vlas_in_scope++;6609 vlas_in_scope++;
6604 } else if (has_init) {6610 } else if (has_init) {
6611 size_t oldreloc_offset = 0;
6612 if (sec && sec->reloc)
6613 oldreloc_offset = sec->reloc->data_offset;
6605 decl_initializer(type, sec, addr, 1, 0);6614 decl_initializer(type, sec, addr, 1, 0);
6615 if (sec && sec->reloc)
6616 squeeze_multi_relocs(sec, oldreloc_offset);
6606 /* patch flexible array member size back to -1, */6617 /* patch flexible array member size back to -1, */
6607 /* for possible subsequent similar declarations */6618 /* for possible subsequent similar declarations */
6608 if (flexible_array)6619 if (flexible_array)
tests/tests2/86-struct-init.c+20−0
@@ -199,6 +199,25 @@ void test_compound_with_relocs (void) · 198 unmodified lines
199 p = local_wrap[1].func; p();199 p = local_wrap[1].func; p();
200}200}
201 201
202void sys_ni(void) { printf("ni\n"); }
203void sys_one(void) { printf("one\n"); }
204void sys_two(void) { printf("two\n"); }
205void sys_three(void) { printf("three\n"); }
206typedef void (*fptr)(void);
207const fptr table[3] = {
208 [0 ... 2] = &sys_ni,
209 [0] = sys_one,
210 [1] = sys_two,
211 [2] = sys_three,
212};
213
214void test_multi_relocs(void)
215{
216 int i;
217 for (i = 0; i < sizeof(table)/sizeof(table[0]); i++)
218 table[i]();
219}
220
202int main()221int main()
203{222{
204 print(ce);223 print(ce);
@@ -224,5 +243,6 @@ int main() · 19 unmodified lines
224 foo(&gw, &phdr);243 foo(&gw, &phdr);
225 //printf("q: %s\n", q);244 //printf("q: %s\n", q);
226 test_compound_with_relocs();245 test_compound_with_relocs();
246 test_multi_relocs();
227 return 0;247 return 0;
228}248}
tests/tests2/86-struct-init.expect+3−0
@@ -35,3 +35,6 @@ lv2: 1 2 3 4 68 69 68 69 0 0 0 0 0 0 0 0 0 0 0 0 2f 30 · 34 unmodified lines
35lv3: 7 8 9 a 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3235lv3: 7 8 9 a 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 32
36lt2: 0 9 9 9 43 43 43 43 42 42 42 0 0 0 0 0 136lt2: 0 9 9 9 43 43 43 43 42 42 42 0 0 0 0 0 1
37flow: 9 8 7 6 0 0 0 0 0 0 0 0 0 0 0 0 6 5 4 3 0 0 0 0 0 0 0 0 0 0 0 037flow: 9 8 7 6 0 0 0 0 0 0 0 0 0 0 0 0 6 5 4 3 0 0 0 0 0 0 0 0 0 0 0 0
38one
39two
40three

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