| @@ -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 */ |
| | 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 | ST_FUNC Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags) | 186 | ST_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 | else | 393 | 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 | |
| 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 | 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_LOCAL | 445 | 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. */ | | |
| 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 | /* return elf symbol value, signal error if 'err' is nonzero */ | 452 | /* return elf symbol value, signal error if 'err' is nonzero */ |
| 408 | ST_FUNC addr_t get_elf_sym_addr(TCCState *s, const char *name, int err) | 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 | 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, | 1266 | ST_FUNC void resolve_common_syms(TCCState *s1) |
| 1224 | not from shared libs) */ | | |
| 1225 | ST_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 | |
| 1264 | static void tcc_output_binary(TCCState *s1, FILE *f, | 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 | 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 */ |