| @@ -130,6 +130,59 @@ ST_FUNC void tccelf_delete(TCCState *s1) · 129 unmodified lines |
| 130 | 130 | tcc_free(s1->sym_attrs); |
| 131 | 131 | } |
| 132 | 132 | |
| 133 | +/* save section data state */ |
| 134 | +ST_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 */ |
| 150 | +ST_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 | + |
| 133 | 186 | ST_FUNC Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags) |
| 134 | 187 | { |
| 135 | 188 | Section *sec; |
| @@ -269,7 +322,7 @@ ST_FUNC int put_elf_str(Section *s, const char *sym) · 133 unmodified lines |
| 269 | 322 | len = strlen(sym) + 1; |
| 270 | 323 | offset = s->data_offset; |
| 271 | 324 | ptr = section_ptr_add(s, len); |
| 272 | | − memcpy(ptr, sym, len); |
| 325 | + memmove(ptr, sym, len); |
| 273 | 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 | 388 | Section *hs; |
| 336 | 389 | |
| 337 | 390 | sym = section_ptr_add(s, sizeof(ElfW(Sym))); |
| 338 | | − if (name) |
| 391 | + if (name && name[0]) |
| 339 | 392 | name_offset = put_elf_str(s->link, name); |
| 340 | 393 | else |
| 341 | 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 | 409 | if (ELFW(ST_BIND)(info) != STB_LOCAL) { |
| 357 | 410 | /* add another hashing entry */ |
| 358 | 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 | 413 | *ptr = base[2 + h]; |
| 361 | 414 | base[2 + h] = sym_index; |
| 362 | 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 | 426 | return sym_index; |
| 374 | 427 | } |
| 375 | 428 | |
| 376 | | −static int find_elf_sym_1(Section *s, const char *name, int onlydef) |
| 429 | +ST_FUNC int find_elf_sym(Section *s, const char *name) |
| 377 | 430 | { |
| 378 | 431 | ElfW(Sym) *sym; |
| 379 | 432 | Section *hs; |
| @@ -389,21 +442,13 @@ static int find_elf_sym_1(Section *s, const char *name, int onlydef) · 9 unmodified lines |
| 389 | 442 | while (sym_index != 0) { |
| 390 | 443 | sym = &((ElfW(Sym) *)s->data)[sym_index]; |
| 391 | 444 | name1 = (char *) s->link->data + sym->st_name; |
| 392 | | − if (!strcmp(name, name1) && ELFW(ST_BIND)(sym->st_info) != STB_LOCAL |
| 393 | | − && (!onlydef || sym->st_shndx != SHN_UNDEF)) |
| 445 | + if (!strcmp(name, name1)) |
| 394 | 446 | return sym_index; |
| 395 | 447 | sym_index = ((int *)hs->data)[2 + nbuckets + sym_index]; |
| 396 | 448 | } |
| 397 | 449 | return 0; |
| 398 | 450 | } |
| 399 | 451 | |
| 400 | | −/* find global ELF symbol 'name' and return its index. Return 0 if not |
| 401 | | − found. */ |
| 402 | | −ST_FUNC int find_elf_sym(Section *s, const char *name) |
| 403 | | −{ |
| 404 | | − return find_elf_sym_1(s, name, 0); |
| 405 | | −} |
| 406 | | − |
| 407 | 452 | /* return elf symbol value, signal error if 'err' is nonzero */ |
| 408 | 453 | ST_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 | 492 | sym_type = ELFW(ST_TYPE)(info); |
| 448 | 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 | 495 | if (sym_bind != STB_LOCAL) { |
| 458 | 496 | /* we search global or weak symbols */ |
| 497 | + sym_index = find_elf_sym(s, name); |
| 459 | 498 | if (!sym_index) |
| 460 | 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 | 504 | if (esym->st_shndx != SHN_UNDEF) { |
| 462 | 505 | esym_bind = ELFW(ST_BIND)(esym->st_info); |
| 463 | 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, |
| 1224 | | − not from shared libs) */ |
| 1225 | | −ST_FUNC void resolve_regular_syms(void) |
| 1266 | +ST_FUNC void resolve_common_syms(TCCState *s1) |
| 1226 | 1267 | { |
| 1227 | | − int rebuild = 0; |
| 1228 | 1268 | ElfW(Sym) *sym; |
| 1229 | 1269 | |
| 1230 | 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 | 1280 | /* Now assign linker provided symbols their value. */ |
| 1241 | | − tcc_add_linker_symbols(tcc_state); |
| 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); |
| 1281 | + tcc_add_linker_symbols(s1); |
| 1262 | 1282 | } |
| 1263 | 1283 | |
| 1264 | 1284 | static 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 | 2071 | if (file_type != TCC_OUTPUT_OBJ) { |
| 2052 | 2072 | /* if linking, also link in runtime libraries (libc, libgcc, etc.) */ |
| 2053 | 2073 | tcc_add_runtime(s1); |
| 2054 | | − resolve_regular_syms(); |
| 2074 | + resolve_common_syms(s1); |
| 2055 | 2075 | |
| 2056 | 2076 | if (!s1->static_link) { |
| 2057 | 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 | 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 | 2117 | /* we add a section for symbols */ |