History

tccgen_begin/end_file

This is supposed to make compilation and linking with multiple source files (tcc f1.c f2.S ...) behave just the same as linking object files. tccgen.c:put_extern_sym2(): - use put_elf_sym to enter new symbols unconditionally tccelf.c: - save section state before compilation - disable symbol hashing during compilation - merge symbols and update relocations after compilation tccpe.c: - re-create s1->uw_sym for each compilation (because it may change)

grischka committed 8 years ago

Commit 1a4d4b71 parent 8490c546 files · +81 −68Browse files

Unified · Split

6 files
  1. libtcc.c +3 −4
  2. tcc.h +3 −1
  3. tccelf.c +66 −54
  4. tccgen.c +1 −1
  5. tccpe.c +7 −7
  6. tccrun.c +1 −1
libtcc.c+3−4
@@ -486,7 +486,7 @@ static void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap) · 485 unmodified lines
486 for(pf = s1->include_stack; pf < s1->include_stack_ptr; pf++)486 for(pf = s1->include_stack; pf < s1->include_stack_ptr; pf++)
487 strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",487 strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
488 (*pf)->filename, (*pf)->line_num);488 (*pf)->filename, (*pf)->line_num);
489 if (f->line_num > 0) {489 if (s1->error_set_jmp_enabled) {
490 strcat_printf(buf, sizeof(buf), "%s:%d: ",490 strcat_printf(buf, sizeof(buf), "%s:%d: ",
491 f->filename, f->line_num - !!(tok_flags & TOK_FLAG_BOL));491 f->filename, f->line_num - !!(tok_flags & TOK_FLAG_BOL));
492 } else {492 } else {
@@ -629,6 +629,7 @@ static int tcc_compile(TCCState *s1) · 136 unmodified lines
629 define_start = define_stack;629 define_start = define_stack;
630 filetype = s1->filetype;630 filetype = s1->filetype;
631 is_asm = filetype == AFF_TYPE_ASM || filetype == AFF_TYPE_ASMPP;631 is_asm = filetype == AFF_TYPE_ASM || filetype == AFF_TYPE_ASMPP;
632 tccelf_begin_file(s1);
632 633
633 if (setjmp(s1->error_jmp_buf) == 0) {634 if (setjmp(s1->error_jmp_buf) == 0) {
634 s1->nb_errors = 0;635 s1->nb_errors = 0;
@@ -655,6 +656,7 @@ static int tcc_compile(TCCState *s1) · 20 unmodified lines
655 free_defines(define_start);656 free_defines(define_start);
656 sym_pop(&global_stack, NULL, 0);657 sym_pop(&global_stack, NULL, 0);
657 sym_pop(&local_stack, NULL, 0);658 sym_pop(&local_stack, NULL, 0);
659 tccelf_end_file(s1);
658 return s1->nb_errors != 0 ? -1 : 0;660 return s1->nb_errors != 0 ? -1 : 0;
659}661}
660 662
@@ -1016,9 +1018,6 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags) · 355 unmodified lines
1016 obj_type = tcc_object_type(fd, &ehdr);1018 obj_type = tcc_object_type(fd, &ehdr);
1017 lseek(fd, 0, SEEK_SET);1019 lseek(fd, 0, SEEK_SET);
1018 1020
1019 /* do not display line number if error */
1020 file->line_num = 0;
1021
1022#ifdef TCC_TARGET_MACHO1021#ifdef TCC_TARGET_MACHO
1023 if (0 == obj_type && 0 == strcmp(tcc_fileextension(filename), ".dylib"))1022 if (0 == obj_type && 0 == strcmp(tcc_fileextension(filename), ".dylib"))
1024 obj_type = AFF_BINTYPE_DYN;1023 obj_type = AFF_BINTYPE_DYN;
tcc.h+3−1
@@ -1397,6 +1397,8 @@ ST_DATA Section *stab_section, *stabstr_section; · 1396 unmodified lines
1397ST_FUNC void tccelf_new(TCCState *s);1397ST_FUNC void tccelf_new(TCCState *s);
1398ST_FUNC void tccelf_delete(TCCState *s);1398ST_FUNC void tccelf_delete(TCCState *s);
1399ST_FUNC void tccelf_stab_new(TCCState *s);1399ST_FUNC void tccelf_stab_new(TCCState *s);
1400ST_FUNC void tccelf_begin_file(TCCState *s1);
1401ST_FUNC void tccelf_end_file(TCCState *s1);
1400 1402
1401ST_FUNC Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags);1403ST_FUNC Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags);
1402ST_FUNC void section_realloc(Section *sec, unsigned long new_size);1404ST_FUNC void section_realloc(Section *sec, unsigned long new_size);
@@ -1425,7 +1427,7 @@ ST_FUNC void put_stabs_r(const char *str, int type, int other, int desc, unsigne · 22 unmodified lines
1425ST_FUNC void put_stabn(int type, int other, int desc, int value);1427ST_FUNC void put_stabn(int type, int other, int desc, int value);
1426ST_FUNC void put_stabd(int type, int other, int desc);1428ST_FUNC void put_stabd(int type, int other, int desc);
1427 1429
1428ST_FUNC void resolve_regular_syms(void);1430ST_FUNC void resolve_common_syms(TCCState *s1);
1429ST_FUNC void relocate_syms(TCCState *s1, Section *symtab, int do_resolve);1431ST_FUNC void relocate_syms(TCCState *s1, Section *symtab, int do_resolve);
1430ST_FUNC void relocate_section(TCCState *s1, Section *s);1432ST_FUNC void relocate_section(TCCState *s1, Section *s);
1431 1433
tccelf.c+66−54
@@ -130,6 +130,59 @@ ST_FUNC void tccelf_delete(TCCState *s1) · 129 unmodified lines
130 tcc_free(s1->sym_attrs);130 tcc_free(s1->sym_attrs);
131}131}
132 132
133/* save section data state */
134ST_FUNC void tccelf_begin_file(TCCState *s1)
135{
136 Section *s; int i;
137 for (i = 1; i < s1->nb_sections; i++) {
138 s = s1->sections[i];
139 s->sh_offset = s->data_offset;
140 }
141 /* disable symbol hashing during compilation */
142 s = s1->symtab, s->reloc = s->hash, s->hash = NULL;
143#if defined TCC_TARGET_X86_64 && defined TCC_TARGET_PE
144 s1->uw_sym = 0;
145#endif
146}
147
148/* At the end of compilation, convert any UNDEF syms to global, and merge
149 with previously existing symbols */
150ST_FUNC void tccelf_end_file(TCCState *s1)
151{
152 Section *s = s1->symtab;
153 int first_sym, nb_syms, *tr, i;
154
155 first_sym = s->sh_offset / sizeof (ElfSym);
156 nb_syms = s->data_offset / sizeof (ElfSym) - first_sym;
157 s->data_offset = s->sh_offset;
158 s->link->data_offset = s->link->sh_offset;
159 s->hash = s->reloc, s->reloc = NULL;
160 tr = tcc_mallocz(nb_syms * sizeof *tr);
161
162 for (i = 0; i < nb_syms; ++i) {
163 ElfSym *sym = (ElfSym*)s->data + first_sym + i;
164 if (sym->st_shndx == SHN_UNDEF
165 && ELFW(ST_BIND)(sym->st_info) == STB_LOCAL)
166 sym->st_info = ELFW(ST_INFO)(STB_GLOBAL, ELFW(ST_TYPE)(sym->st_info));
167 tr[i] = set_elf_sym(s, sym->st_value, sym->st_size, sym->st_info,
168 sym->st_other, sym->st_shndx, s->link->data + sym->st_name);
169 }
170 /* now update relocations */
171 for (i = 1; i < s1->nb_sections; i++) {
172 Section *sr = s1->sections[i];
173 if (sr->sh_type == SHT_RELX && sr->link == s) {
174 ElfW_Rel *rel = (ElfW_Rel*)(sr->data + sr->sh_offset);
175 ElfW_Rel *rel_end = (ElfW_Rel*)(sr->data + sr->data_offset);
176 for (; rel < rel_end; ++rel) {
177 int n = ELFW(R_SYM)(rel->r_info) - first_sym;
178 //if (n < 0) tcc_error("internal: invalid symbol index in relocation");
179 rel->r_info = ELFW(R_INFO)(tr[n], ELFW(R_TYPE)(rel->r_info));
180 }
181 }
182 }
183 tcc_free(tr);
184}
185
133ST_FUNC Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)186ST_FUNC Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
134{187{
135 Section *sec;188 Section *sec;
@@ -269,7 +322,7 @@ ST_FUNC int put_elf_str(Section *s, const char *sym) · 133 unmodified lines
269 len = strlen(sym) + 1;322 len = strlen(sym) + 1;
270 offset = s->data_offset;323 offset = s->data_offset;
271 ptr = section_ptr_add(s, len);324 ptr = section_ptr_add(s, len);
272 memcpy(ptr, sym, len);325 memmove(ptr, sym, len);
273 return offset;326 return offset;
274}327}
275 328
@@ -335,7 +388,7 @@ ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size, · 59 unmodified lines
335 Section *hs;388 Section *hs;
336 389
337 sym = section_ptr_add(s, sizeof(ElfW(Sym)));390 sym = section_ptr_add(s, sizeof(ElfW(Sym)));
338 if (name)391 if (name && name[0])
339 name_offset = put_elf_str(s->link, name);392 name_offset = put_elf_str(s->link, name);
340 else393 else
341 name_offset = 0;394 name_offset = 0;
@@ -356,7 +409,7 @@ ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size, · 14 unmodified lines
356 if (ELFW(ST_BIND)(info) != STB_LOCAL) {409 if (ELFW(ST_BIND)(info) != STB_LOCAL) {
357 /* add another hashing entry */410 /* add another hashing entry */
358 nbuckets = base[0];411 nbuckets = base[0];
359 h = elf_hash((unsigned char *) name) % nbuckets;412 h = elf_hash((unsigned char *)s->link->data + name_offset) % nbuckets;
360 *ptr = base[2 + h];413 *ptr = base[2 + h];
361 base[2 + h] = sym_index;414 base[2 + h] = sym_index;
362 base[1]++;415 base[1]++;
@@ -373,7 +426,7 @@ ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size, · 10 unmodified lines
373 return sym_index;426 return sym_index;
374}427}
375 428
376static int find_elf_sym_1(Section *s, const char *name, int onlydef)429ST_FUNC int find_elf_sym(Section *s, const char *name)
377{430{
378 ElfW(Sym) *sym;431 ElfW(Sym) *sym;
379 Section *hs;432 Section *hs;
@@ -389,21 +442,13 @@ static int find_elf_sym_1(Section *s, const char *name, int onlydef) · 9 unmodified lines
389 while (sym_index != 0) {442 while (sym_index != 0) {
390 sym = &((ElfW(Sym) *)s->data)[sym_index];443 sym = &((ElfW(Sym) *)s->data)[sym_index];
391 name1 = (char *) s->link->data + sym->st_name;444 name1 = (char *) s->link->data + sym->st_name;
392 if (!strcmp(name, name1) && ELFW(ST_BIND)(sym->st_info) != STB_LOCAL445 if (!strcmp(name, name1))
393 && (!onlydef || sym->st_shndx != SHN_UNDEF))
394 return sym_index;446 return sym_index;
395 sym_index = ((int *)hs->data)[2 + nbuckets + sym_index];447 sym_index = ((int *)hs->data)[2 + nbuckets + sym_index];
396 }448 }
397 return 0;449 return 0;
398}450}
399 451
400/* find global ELF symbol 'name' and return its index. Return 0 if not
401 found. */
402ST_FUNC int find_elf_sym(Section *s, const char *name)
403{
404 return find_elf_sym_1(s, name, 0);
405}
406
407/* return elf symbol value, signal error if 'err' is nonzero */452/* return elf symbol value, signal error if 'err' is nonzero */
408ST_FUNC addr_t get_elf_sym_addr(TCCState *s, const char *name, int err)453ST_FUNC addr_t get_elf_sym_addr(TCCState *s, const char *name, int err)
409{454{
@@ -447,17 +492,15 @@ ST_FUNC int set_elf_sym(Section *s, addr_t value, unsigned long size, · 37 unmodified lines
447 sym_type = ELFW(ST_TYPE)(info);492 sym_type = ELFW(ST_TYPE)(info);
448 sym_vis = ELFW(ST_VISIBILITY)(other);493 sym_vis = ELFW(ST_VISIBILITY)(other);
449 494
450 sym_index = find_elf_sym(s, name);
451 esym = &((ElfW(Sym) *)s->data)[sym_index];
452 if (sym_index && esym->st_value == value && esym->st_size == size
453 && esym->st_info == info && esym->st_other == other
454 && esym->st_shndx == shndx)
455 return sym_index;
456
457 if (sym_bind != STB_LOCAL) {495 if (sym_bind != STB_LOCAL) {
458 /* we search global or weak symbols */496 /* we search global or weak symbols */
497 sym_index = find_elf_sym(s, name);
459 if (!sym_index)498 if (!sym_index)
460 goto do_def;499 goto do_def;
500 esym = &((ElfW(Sym) *)s->data)[sym_index];
501 if (esym->st_value == value && esym->st_size == size && esym->st_info == info
502 && esym->st_other == other && esym->st_shndx == shndx)
503 return sym_index;
461 if (esym->st_shndx != SHN_UNDEF) {504 if (esym->st_shndx != SHN_UNDEF) {
462 esym_bind = ELFW(ST_BIND)(esym->st_info);505 esym_bind = ELFW(ST_BIND)(esym->st_info);
463 /* propagate the most constraining visibility */506 /* propagate the most constraining visibility */
@@ -1220,11 +1263,8 @@ static void tcc_add_linker_symbols(TCCState *s1) · 756 unmodified lines
1220 }1263 }
1221}1264}
1222 1265
1223/* Do final regular symbol preparation (for those coming from .c/.o/.s files,1266ST_FUNC void resolve_common_syms(TCCState *s1)
1224 not from shared libs) */
1225ST_FUNC void resolve_regular_syms(void)
1226{1267{
1227 int rebuild = 0;
1228 ElfW(Sym) *sym;1268 ElfW(Sym) *sym;
1229 1269
1230 /* Allocate common symbols in BSS. */1270 /* Allocate common symbols in BSS. */
@@ -1238,27 +1278,7 @@ ST_FUNC void resolve_regular_syms(void) · 7 unmodified lines
1238 }1278 }
1239 1279
1240 /* Now assign linker provided symbols their value. */1280 /* Now assign linker provided symbols their value. */
1241 tcc_add_linker_symbols(tcc_state);1281 tcc_add_linker_symbols(s1);
1242
1243 /* And finally resolve still UNDEF symbols (for multi-file mode),
1244 and globalize those that are still UNDEF. */
1245 rebuild_hash(symtab_section, 0);
1246 for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
1247 if (sym->st_shndx == SHN_UNDEF) {
1248 const char *name = (char *) symtab_section->link->data + sym->st_name;
1249 int symndx = find_elf_sym_1(symtab_section, name, 1);
1250 if (symndx) {
1251 *sym = ((ElfSym *)symtab_section->data)[symndx];
1252 rebuild = 1;
1253 } else if (ELFW(ST_BIND)(sym->st_info) == STB_LOCAL) {
1254 sym->st_info
1255 = ELFW(ST_INFO)(STB_GLOBAL, ELFW(ST_TYPE)(sym->st_info));
1256 rebuild = 1;
1257 }
1258 }
1259 }
1260 if (rebuild)
1261 rebuild_hash(symtab_section, 0);
1262}1282}
1263 1283
1264static void tcc_output_binary(TCCState *s1, FILE *f,1284static void tcc_output_binary(TCCState *s1, FILE *f,
@@ -2051,7 +2071,7 @@ static int elf_output_file(TCCState *s1, const char *filename) · 786 unmodified lines
2051 if (file_type != TCC_OUTPUT_OBJ) {2071 if (file_type != TCC_OUTPUT_OBJ) {
2052 /* if linking, also link in runtime libraries (libc, libgcc, etc.) */2072 /* if linking, also link in runtime libraries (libc, libgcc, etc.) */
2053 tcc_add_runtime(s1);2073 tcc_add_runtime(s1);
2054 resolve_regular_syms();2074 resolve_common_syms(s1);
2055 2075
2056 if (!s1->static_link) {2076 if (!s1->static_link) {
2057 if (file_type == TCC_OUTPUT_EXE) {2077 if (file_type == TCC_OUTPUT_EXE) {
@@ -2092,14 +2112,6 @@ static int elf_output_file(TCCState *s1, const char *filename) · 34 unmodified lines
2092 }2112 }
2093 }2113 }
2094 build_got_entries(s1);2114 build_got_entries(s1);
2095 } else {
2096 for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
2097 if (sym->st_shndx == SHN_UNDEF
2098 && ELFW(ST_BIND)(sym->st_info) == STB_LOCAL) {
2099 sym->st_info
2100 = ELFW(ST_INFO)(STB_GLOBAL, ELFW(ST_TYPE)(sym->st_info));
2101 }
2102 }
2103 }2115 }
2104 2116
2105 /* we add a section for symbols */2117 /* we add a section for symbols */
tccgen.c+1−1
@@ -418,7 +418,7 @@ ST_FUNC void put_extern_sym2(Sym *sym, Section *section, · 417 unmodified lines
418 if (sym->asm_label)418 if (sym->asm_label)
419 name = get_tok_str(sym->asm_label, NULL);419 name = get_tok_str(sym->asm_label, NULL);
420 info = ELFW(ST_INFO)(sym_bind, sym_type);420 info = ELFW(ST_INFO)(sym_bind, sym_type);
421 sym->c = set_elf_sym(symtab_section, value, size, info, other, sh_num, name);421 sym->c = put_elf_sym(symtab_section, value, size, info, other, sh_num, name);
422 } else {422 } else {
423 esym = elfsym(sym);423 esym = elfsym(sym);
424 esym->st_value = value;424 esym->st_value = value;
tccpe.c+7−7
@@ -1633,7 +1633,7 @@ static int pe_load_res(TCCState *s1, int fd) · 1632 unmodified lines
1633{1633{
1634 struct pe_rsrc_header hdr;1634 struct pe_rsrc_header hdr;
1635 Section *rsrc_section;1635 Section *rsrc_section;
1636 int i, ret = -1;1636 int i, ret = -1, sym_index;
1637 BYTE *ptr;1637 BYTE *ptr;
1638 unsigned offs;1638 unsigned offs;
1639 1639
@@ -1651,8 +1651,8 @@ static int pe_load_res(TCCState *s1, int fd) · 11 unmodified lines
1651 if (!read_mem(fd, offs, ptr, hdr.sectionhdr.SizeOfRawData))1651 if (!read_mem(fd, offs, ptr, hdr.sectionhdr.SizeOfRawData))
1652 goto quit;1652 goto quit;
1653 offs = hdr.sectionhdr.PointerToRelocations;1653 offs = hdr.sectionhdr.PointerToRelocations;
1654 for (i = 0; i < hdr.sectionhdr.NumberOfRelocations; ++i)1654 sym_index = put_elf_sym(symtab_section, 0, 0, 0, 0, rsrc_section->sh_num, ".rsrc");
1655 {1655 for (i = 0; i < hdr.sectionhdr.NumberOfRelocations; ++i) {
1656 struct pe_rsrc_reloc rel;1656 struct pe_rsrc_reloc rel;
1657 if (!read_mem(fd, offs, &rel, sizeof rel))1657 if (!read_mem(fd, offs, &rel, sizeof rel))
1658 goto quit;1658 goto quit;
@@ -1660,7 +1660,7 @@ static int pe_load_res(TCCState *s1, int fd) · 1 unmodified line
1660 if (rel.type != RSRC_RELTYPE)1660 if (rel.type != RSRC_RELTYPE)
1661 goto quit;1661 goto quit;
1662 put_elf_reloc(symtab_section, rsrc_section,1662 put_elf_reloc(symtab_section, rsrc_section,
1663 rel.offset, R_XXX_RELATIVE, 0);1663 rel.offset, R_XXX_RELATIVE, sym_index);
1664 offs += sizeof rel;1664 offs += sizeof rel;
1665 }1665 }
1666 ret = 0;1666 ret = 0;
@@ -1779,9 +1779,9 @@ static unsigned pe_add_uwwind_info(TCCState *s1) · 112 unmodified lines
1779 if (NULL == s1->uw_pdata) {1779 if (NULL == s1->uw_pdata) {
1780 s1->uw_pdata = find_section(tcc_state, ".pdata");1780 s1->uw_pdata = find_section(tcc_state, ".pdata");
1781 s1->uw_pdata->sh_addralign = 4;1781 s1->uw_pdata->sh_addralign = 4;
1782 s1->uw_sym = put_elf_sym(symtab_section, 0, 0, 0, 0, text_section->sh_num, NULL);
1783 }1782 }
1784 1783 if (0 == s1->uw_sym)
1784 s1->uw_sym = put_elf_sym(symtab_section, 0, 0, 0, 0, text_section->sh_num, ".uw_base");
1785 if (0 == s1->uw_offs) {1785 if (0 == s1->uw_offs) {
1786 /* As our functions all have the same stackframe, we use one entry for all */1786 /* As our functions all have the same stackframe, we use one entry for all */
1787 static const unsigned char uw_info[] = {1787 static const unsigned char uw_info[] = {
@@ -1970,7 +1970,7 @@ ST_FUNC int pe_output_file(TCCState *s1, const char *filename) · 182 unmodified lines
1970 1970
1971 tcc_add_bcheck(s1);1971 tcc_add_bcheck(s1);
1972 pe_add_runtime(s1, &pe);1972 pe_add_runtime(s1, &pe);
1973 resolve_regular_syms();1973 resolve_common_syms(s1);
1974 pe_set_options(s1, &pe);1974 pe_set_options(s1, &pe);
1975 1975
1976 ret = pe_check_symbols(&pe);1976 ret = pe_check_symbols(&pe);
tccrun.c+1−1
@@ -188,7 +188,7 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff) · 187 unmodified lines
188 pe_output_file(s1, NULL);188 pe_output_file(s1, NULL);
189#else189#else
190 tcc_add_runtime(s1);190 tcc_add_runtime(s1);
191 resolve_regular_syms();191 resolve_common_syms(s1);
192 build_got_entries(s1);192 build_got_entries(s1);
193#endif193#endif
194 if (s1->nb_errors)194 if (s1->nb_errors)

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