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
911911
912912 /* symbol was created by tccasm.c first */
913913 #define VT_ASM (VT_VOID | VT_UNSIGNED)
914−#define VT_ASM_GLOBAL VT_DEFSIGN
915914 #define IS_ASM_SYM(sym) (((sym)->type.t & (VT_BTYPE | VT_ASM)) == VT_ASM)
916915
917916 /* 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
14261425 ST_FUNC void put_stabn(int type, int other, int desc, int value);
14271426 ST_FUNC void put_stabd(int type, int other, int desc);
14281427
1429−ST_FUNC void relocate_common_syms(void);
1428+ST_FUNC void resolve_regular_syms(void);
14301429 ST_FUNC void relocate_syms(TCCState *s1, Section *symtab, int do_resolve);
14311430 ST_FUNC void relocate_section(TCCState *s1, Section *s);
14321431
1433−ST_FUNC void tcc_add_linker_symbols(TCCState *s1);
14341432 ST_FUNC int tcc_object_type(int fd, ElfW(Ehdr) *h);
14351433 ST_FUNC int tcc_load_object_file(TCCState *s1, int fd, unsigned long file_offset);
14361434 ST_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
4242 return sym;
4343 }
4444
45−static Sym *asm_label_push(int v, int t)
45+static Sym *asm_label_push(int v)
4646 {
47− Sym *sym = global_identifier_push(v, t, 0);
4847 /* We always add VT_EXTERN, for sym definition that's tentative
4948 (for .set, removed for real defs), for mere references it's correct
5049 as is. */
51− sym->type.t |= VT_ASM | VT_EXTERN;
50+ Sym *sym = global_identifier_push(v, VT_ASM | VT_EXTERN | VT_STATIC, 0);
5251 sym->r = VT_CONST | VT_SYM;
5352 return sym;
5453 }
@@ -67,7 +66,7 @@ ST_FUNC Sym* get_asm_sym(int name, Sym *csym) · 12 unmodified lines
6766 {
6867 Sym *sym = asm_label_find(name);
6968 if (!sym) {
70− sym = asm_label_push(name, 0);
69+ sym = asm_label_push(name);
7170 if (csym)
7271 sym->c = csym->c;
7372 }
@@ -102,7 +101,7 @@ static void asm_expr_unary(TCCState *s1, ExprValue *pe) · 28 unmodified lines
102101 /* forward */
103102 if (!sym || (sym->c && elfsym(sym)->st_shndx != SHN_UNDEF)) {
104103 /* 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);
106105 }
107106 }
108107 pe->v = 0;
@@ -381,7 +380,7 @@ static Sym* asm_new_label1(TCCState *s1, int label, int is_local, · 272 unmodified lines
381380 }
382381 } else {
383382 new_label:
384− sym = asm_label_push(label, is_local == 1 ? VT_STATIC : 0);
383+ sym = asm_label_push(label);
385384 }
386385 if (!sym->c)
387386 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
392391 if (is_local != 2)
393392 sym->type.t &= ~VT_EXTERN;
394393
395− if (IS_ASM_SYM(sym) && !(sym->type.t & VT_ASM_GLOBAL)) {
396− sym->type.t |= VT_STATIC;
397− update_storage(sym);
398− }
399−
400394 return sym;
401395 }
402396
@@ -679,11 +673,8 @@ static void asm_parse_directive(TCCState *s1, int global) · 276 unmodified lines
679673 Sym *sym;
680674 next();
681675 sym = get_asm_sym(tok, NULL);
682− if (tok1 != TOK_ASMDIR_hidden) {
676+ if (tok1 != TOK_ASMDIR_hidden)
683677 sym->type.t &= ~VT_STATIC;
684− if (IS_ASM_SYM(sym))
685− sym->type.t |= VT_ASM_GLOBAL;
686− }
687678 if (tok1 == TOK_ASMDIR_weak)
688679 sym->a.weak = 1;
689680 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
299299 strtab = s->link->data;
300300 nb_syms = s->data_offset / sizeof(ElfW(Sym));
301301
302+ if (!nb_buckets)
303+ nb_buckets = ((int*)s->hash->data)[0];
304+
302305 s->hash->data_offset = 0;
303306 ptr = section_ptr_add(s->hash, (2 + nb_buckets + nb_syms) * sizeof(int));
304307 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
370373 return sym_index;
371374 }
372375
373−/* find global ELF symbol 'name' and return its index. Return 0 if not
374− found. */
375−ST_FUNC int find_elf_sym(Section *s, const char *name)
376+static int find_elf_sym_1(Section *s, const char *name, int onlydef)
376377 {
377378 ElfW(Sym) *sym;
378379 Section *hs;
@@ -388,13 +389,21 @@ ST_FUNC int find_elf_sym(Section *s, const char *name) · 9 unmodified lines
388389 while (sym_index != 0) {
389390 sym = &((ElfW(Sym) *)s->data)[sym_index];
390391 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))
392394 return sym_index;
393395 sym_index = ((int *)hs->data)[2 + nbuckets + sym_index];
394396 }
395397 return 0;
396398 }
397399
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+
398407 /* return elf symbol value, signal error if 'err' is nonzero */
399408 ST_FUNC addr_t get_elf_sym_addr(TCCState *s, const char *name, int err)
400409 {
@@ -716,21 +725,6 @@ static void sort_syms(TCCState *s1, Section *s) · 315 unmodified lines
716725 tcc_free(old_to_new_syms);
717726 }
718727
719−/* relocate common symbols in the .bss section */
720−ST_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−
734728 /* relocate symbol table, resolve undefined symbols if do_resolve is
735729 true and output error if undefined symbol. */
736730 ST_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
11671161 /* add various standard linker symbols (must be done after the
11681162 sections are filled (for example after allocating common
11691163 symbols)) */
1170−ST_FUNC void tcc_add_linker_symbols(TCCState *s1)
1164+static void tcc_add_linker_symbols(TCCState *s1)
11711165 {
11721166 char buf[1024];
11731167 int i;
@@ -1226,6 +1220,47 @@ ST_FUNC void tcc_add_linker_symbols(TCCState *s1) · 52 unmodified lines
12261220 }
12271221 }
12281222
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)
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+
12291264 static void tcc_output_binary(TCCState *s1, FILE *f,
12301265 const int *sec_order)
12311266 {
@@ -2016,8 +2051,7 @@ static int elf_output_file(TCCState *s1, const char *filename) · 784 unmodified lines
20162051 if (file_type != TCC_OUTPUT_OBJ) {
20172052 /* if linking, also link in runtime libraries (libc, libgcc, etc.) */
20182053 tcc_add_runtime(s1);
2019− relocate_common_syms();
2020− tcc_add_linker_symbols(s1);
2054+ resolve_regular_syms();
20212055
20222056 if (!s1->static_link) {
20232057 if (file_type == TCC_OUTPUT_EXE) {
@@ -2058,6 +2092,14 @@ static int elf_output_file(TCCState *s1, const char *filename) · 34 unmodified lines
20582092 }
20592093 }
20602094 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+ }
20612103 }
20622104
20632105 /* 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
19701970
19711971 tcc_add_bcheck(s1);
19721972 pe_add_runtime(s1, &pe);
1973− relocate_common_syms(); /* assign bss addresses */
1974− tcc_add_linker_symbols(s1);
1973+ resolve_regular_syms();
19751974 pe_set_options(s1, &pe);
19761975
19771976 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
188188 pe_output_file(s1, NULL);
189189 #else
190190 tcc_add_runtime(s1);
191− relocate_common_syms();
192− tcc_add_linker_symbols(s1);
191+ resolve_regular_syms();
193192 build_got_entries(s1);
194193 #endif
195194 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