History

Fix some multi-file corner cases with asm

for this we have to create also asm symbols as VT_STATIC initially except if there's an indication that it should be global (.globl or undefined at end of unit). For this to work we need to be able to globalize symbols after they were local and enter them into the ELF hash tables, and also adjust the symbols that were potentially already used in relocs when they were still local. The easiest is to do a proper symbol resolution step also in multi-file mode, for regular symbols (the non-dynamic ones, i.e. not from shared libs).

Michael Matz committed 8 years ago

Commit 8490c541 parent 3ae1a2a5 files · +73 −44Browse files

Unified · Split

5 files
  1. tcc.h +1 −3
  2. tccasm.c +6 −15
  3. tccelf.c +64 −22
  4. tccpe.c +1 −2
  5. tccrun.c +1 −2
tcc.h+1−3
@@ -911,7 +911,6 @@ struct filespec { · 910 unmodified lines
911 911
912/* symbol was created by tccasm.c first */912/* symbol was created by tccasm.c first */
913#define VT_ASM (VT_VOID | VT_UNSIGNED)913#define VT_ASM (VT_VOID | VT_UNSIGNED)
914#define VT_ASM_GLOBAL VT_DEFSIGN
915#define IS_ASM_SYM(sym) (((sym)->type.t & (VT_BTYPE | VT_ASM)) == VT_ASM)914#define IS_ASM_SYM(sym) (((sym)->type.t & (VT_BTYPE | VT_ASM)) == VT_ASM)
916 915
917/* token values */916/* token values */
@@ -1426,11 +1425,10 @@ ST_FUNC void put_stabs_r(const char *str, int type, int other, int desc, unsigne · 508 unmodified lines
1426ST_FUNC void put_stabn(int type, int other, int desc, int value);1425ST_FUNC void put_stabn(int type, int other, int desc, int value);
1427ST_FUNC void put_stabd(int type, int other, int desc);1426ST_FUNC void put_stabd(int type, int other, int desc);
1428 1427
1429ST_FUNC void relocate_common_syms(void);1428ST_FUNC void resolve_regular_syms(void);
1430ST_FUNC void relocate_syms(TCCState *s1, Section *symtab, int do_resolve);1429ST_FUNC void relocate_syms(TCCState *s1, Section *symtab, int do_resolve);
1431ST_FUNC void relocate_section(TCCState *s1, Section *s);1430ST_FUNC void relocate_section(TCCState *s1, Section *s);
1432 1431
1433ST_FUNC void tcc_add_linker_symbols(TCCState *s1);
1434ST_FUNC int tcc_object_type(int fd, ElfW(Ehdr) *h);1432ST_FUNC int tcc_object_type(int fd, ElfW(Ehdr) *h);
1435ST_FUNC int tcc_load_object_file(TCCState *s1, int fd, unsigned long file_offset);1433ST_FUNC int tcc_load_object_file(TCCState *s1, int fd, unsigned long file_offset);
1436ST_FUNC int tcc_load_archive(TCCState *s1, int fd);1434ST_FUNC int tcc_load_archive(TCCState *s1, int fd);
tccasm.c+6−15
@@ -42,13 +42,12 @@ static Sym *asm_label_find(int v) · 41 unmodified lines
42 return sym;42 return sym;
43}43}
44 44
45static Sym *asm_label_push(int v, int t)45static Sym *asm_label_push(int v)
46{46{
47 Sym *sym = global_identifier_push(v, t, 0);
48 /* We always add VT_EXTERN, for sym definition that's tentative47 /* We always add VT_EXTERN, for sym definition that's tentative
49 (for .set, removed for real defs), for mere references it's correct48 (for .set, removed for real defs), for mere references it's correct
50 as is. */49 as is. */
51 sym->type.t |= VT_ASM | VT_EXTERN;50 Sym *sym = global_identifier_push(v, VT_ASM | VT_EXTERN | VT_STATIC, 0);
52 sym->r = VT_CONST | VT_SYM;51 sym->r = VT_CONST | VT_SYM;
53 return sym;52 return sym;
54}53}
@@ -67,7 +66,7 @@ ST_FUNC Sym* get_asm_sym(int name, Sym *csym) · 12 unmodified lines
67{66{
68 Sym *sym = asm_label_find(name);67 Sym *sym = asm_label_find(name);
69 if (!sym) {68 if (!sym) {
70 sym = asm_label_push(name, 0);69 sym = asm_label_push(name);
71 if (csym)70 if (csym)
72 sym->c = csym->c;71 sym->c = csym->c;
73 }72 }
@@ -102,7 +101,7 @@ static void asm_expr_unary(TCCState *s1, ExprValue *pe) · 28 unmodified lines
102 /* forward */101 /* forward */
103 if (!sym || (sym->c && elfsym(sym)->st_shndx != SHN_UNDEF)) {102 if (!sym || (sym->c && elfsym(sym)->st_shndx != SHN_UNDEF)) {
104 /* if the last label is defined, then define a new one */103 /* if the last label is defined, then define a new one */
105 sym = asm_label_push(label, VT_STATIC);104 sym = asm_label_push(label);
106 }105 }
107 }106 }
108 pe->v = 0;107 pe->v = 0;
@@ -381,7 +380,7 @@ static Sym* asm_new_label1(TCCState *s1, int label, int is_local, · 272 unmodified lines
381 }380 }
382 } else {381 } else {
383 new_label:382 new_label:
384 sym = asm_label_push(label, is_local == 1 ? VT_STATIC : 0);383 sym = asm_label_push(label);
385 }384 }
386 if (!sym->c)385 if (!sym->c)
387 put_extern_sym2(sym, NULL, 0, 0, 0);386 put_extern_sym2(sym, NULL, 0, 0, 0);
@@ -392,11 +391,6 @@ static Sym* asm_new_label1(TCCState *s1, int label, int is_local, · 4 unmodified lines
392 if (is_local != 2)391 if (is_local != 2)
393 sym->type.t &= ~VT_EXTERN;392 sym->type.t &= ~VT_EXTERN;
394 393
395 if (IS_ASM_SYM(sym) && !(sym->type.t & VT_ASM_GLOBAL)) {
396 sym->type.t |= VT_STATIC;
397 update_storage(sym);
398 }
399
400 return sym;394 return sym;
401}395}
402 396
@@ -679,11 +673,8 @@ static void asm_parse_directive(TCCState *s1, int global) · 276 unmodified lines
679 Sym *sym;673 Sym *sym;
680 next();674 next();
681 sym = get_asm_sym(tok, NULL);675 sym = get_asm_sym(tok, NULL);
682 if (tok1 != TOK_ASMDIR_hidden) {676 if (tok1 != TOK_ASMDIR_hidden)
683 sym->type.t &= ~VT_STATIC;677 sym->type.t &= ~VT_STATIC;
684 if (IS_ASM_SYM(sym))
685 sym->type.t |= VT_ASM_GLOBAL;
686 }
687 if (tok1 == TOK_ASMDIR_weak)678 if (tok1 == TOK_ASMDIR_weak)
688 sym->a.weak = 1;679 sym->a.weak = 1;
689 else if (tok1 == TOK_ASMDIR_hidden)680 else if (tok1 == TOK_ASMDIR_hidden)
tccelf.c+64−22
@@ -299,6 +299,9 @@ static void rebuild_hash(Section *s, unsigned int nb_buckets) · 298 unmodified lines
299 strtab = s->link->data;299 strtab = s->link->data;
300 nb_syms = s->data_offset / sizeof(ElfW(Sym));300 nb_syms = s->data_offset / sizeof(ElfW(Sym));
301 301
302 if (!nb_buckets)
303 nb_buckets = ((int*)s->hash->data)[0];
304
302 s->hash->data_offset = 0;305 s->hash->data_offset = 0;
303 ptr = section_ptr_add(s->hash, (2 + nb_buckets + nb_syms) * sizeof(int));306 ptr = section_ptr_add(s->hash, (2 + nb_buckets + nb_syms) * sizeof(int));
304 ptr[0] = nb_buckets;307 ptr[0] = nb_buckets;
@@ -370,9 +373,7 @@ ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size, · 65 unmodified lines
370 return sym_index;373 return sym_index;
371}374}
372 375
373/* find global ELF symbol 'name' and return its index. Return 0 if not376static int find_elf_sym_1(Section *s, const char *name, int onlydef)
374 found. */
375ST_FUNC int find_elf_sym(Section *s, const char *name)
376{377{
377 ElfW(Sym) *sym;378 ElfW(Sym) *sym;
378 Section *hs;379 Section *hs;
@@ -388,13 +389,21 @@ ST_FUNC int find_elf_sym(Section *s, const char *name) · 9 unmodified lines
388 while (sym_index != 0) {389 while (sym_index != 0) {
389 sym = &((ElfW(Sym) *)s->data)[sym_index];390 sym = &((ElfW(Sym) *)s->data)[sym_index];
390 name1 = (char *) s->link->data + sym->st_name;391 name1 = (char *) s->link->data + sym->st_name;
391 if (!strcmp(name, name1) && ELFW(ST_BIND)(sym->st_info) != STB_LOCAL)392 if (!strcmp(name, name1) && ELFW(ST_BIND)(sym->st_info) != STB_LOCAL
393 && (!onlydef || sym->st_shndx != SHN_UNDEF))
392 return sym_index;394 return sym_index;
393 sym_index = ((int *)hs->data)[2 + nbuckets + sym_index];395 sym_index = ((int *)hs->data)[2 + nbuckets + sym_index];
394 }396 }
395 return 0;397 return 0;
396}398}
397 399
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
398/* return elf symbol value, signal error if 'err' is nonzero */407/* return elf symbol value, signal error if 'err' is nonzero */
399ST_FUNC addr_t get_elf_sym_addr(TCCState *s, const char *name, int err)408ST_FUNC addr_t get_elf_sym_addr(TCCState *s, const char *name, int err)
400{409{
@@ -716,21 +725,6 @@ static void sort_syms(TCCState *s1, Section *s) · 315 unmodified lines
716 tcc_free(old_to_new_syms);725 tcc_free(old_to_new_syms);
717}726}
718 727
719/* relocate common symbols in the .bss section */
720ST_FUNC void relocate_common_syms(void)
721{
722 ElfW(Sym) *sym;
723
724 for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
725 if (sym->st_shndx == SHN_COMMON) {
726 /* symbol alignment is in st_value for SHN_COMMONs */
727 sym->st_value = section_add(bss_section, sym->st_size,
728 sym->st_value);
729 sym->st_shndx = bss_section->sh_num;
730 }
731 }
732}
733
734/* relocate symbol table, resolve undefined symbols if do_resolve is728/* relocate symbol table, resolve undefined symbols if do_resolve is
735 true and output error if undefined symbol. */729 true and output error if undefined symbol. */
736ST_FUNC void relocate_syms(TCCState *s1, Section *symtab, int do_resolve)730ST_FUNC void relocate_syms(TCCState *s1, Section *symtab, int do_resolve)
@@ -1167,7 +1161,7 @@ ST_FUNC void tcc_add_runtime(TCCState *s1) · 430 unmodified lines
1167/* add various standard linker symbols (must be done after the1161/* add various standard linker symbols (must be done after the
1168 sections are filled (for example after allocating common1162 sections are filled (for example after allocating common
1169 symbols)) */1163 symbols)) */
1170ST_FUNC void tcc_add_linker_symbols(TCCState *s1)1164static void tcc_add_linker_symbols(TCCState *s1)
1171{1165{
1172 char buf[1024];1166 char buf[1024];
1173 int i;1167 int i;
@@ -1226,6 +1220,47 @@ ST_FUNC void tcc_add_linker_symbols(TCCState *s1) · 52 unmodified lines
1226 }1220 }
1227}1221}
1228 1222
1223/* Do final regular symbol preparation (for those coming from .c/.o/.s files,
1224 not from shared libs) */
1225ST_FUNC void resolve_regular_syms(void)
1226{
1227 int rebuild = 0;
1228 ElfW(Sym) *sym;
1229
1230 /* Allocate common symbols in BSS. */
1231 for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
1232 if (sym->st_shndx == SHN_COMMON) {
1233 /* symbol alignment is in st_value for SHN_COMMONs */
1234 sym->st_value = section_add(bss_section, sym->st_size,
1235 sym->st_value);
1236 sym->st_shndx = bss_section->sh_num;
1237 }
1238 }
1239
1240 /* 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);
1262}
1263
1229static void tcc_output_binary(TCCState *s1, FILE *f,1264static void tcc_output_binary(TCCState *s1, FILE *f,
1230 const int *sec_order)1265 const int *sec_order)
1231{1266{
@@ -2016,8 +2051,7 @@ static int elf_output_file(TCCState *s1, const char *filename) · 784 unmodified lines
2016 if (file_type != TCC_OUTPUT_OBJ) {2051 if (file_type != TCC_OUTPUT_OBJ) {
2017 /* if linking, also link in runtime libraries (libc, libgcc, etc.) */2052 /* if linking, also link in runtime libraries (libc, libgcc, etc.) */
2018 tcc_add_runtime(s1);2053 tcc_add_runtime(s1);
2019 relocate_common_syms();2054 resolve_regular_syms();
2020 tcc_add_linker_symbols(s1);
2021 2055
2022 if (!s1->static_link) {2056 if (!s1->static_link) {
2023 if (file_type == TCC_OUTPUT_EXE) {2057 if (file_type == TCC_OUTPUT_EXE) {
@@ -2058,6 +2092,14 @@ static int elf_output_file(TCCState *s1, const char *filename) · 34 unmodified lines
2058 }2092 }
2059 }2093 }
2060 build_got_entries(s1);2094 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 }
2061 }2103 }
2062 2104
2063 /* we add a section for symbols */2105 /* we add a section for symbols */
tccpe.c+1−2
@@ -1970,8 +1970,7 @@ ST_FUNC int pe_output_file(TCCState *s1, const char *filename) · 1969 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 relocate_common_syms(); /* assign bss addresses */1973 resolve_regular_syms();
1974 tcc_add_linker_symbols(s1);
1975 pe_set_options(s1, &pe);1974 pe_set_options(s1, &pe);
1976 1975
1977 ret = pe_check_symbols(&pe);1976 ret = pe_check_symbols(&pe);
tccrun.c+1−2
@@ -188,8 +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 relocate_common_syms();191 resolve_regular_syms();
192 tcc_add_linker_symbols(s1);
193 build_got_entries(s1);192 build_got_entries(s1);
194#endif193#endif
195 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