aboutsummaryrefslogtreecommitdiff
path: root/tccelf.c
diff options
context:
space:
mode:
authorMichael Matz <matz@suse.de>2017-11-27 04:03:03 +0100
committerMichael Matz <matz@suse.de>2017-11-27 04:59:29 +0100
commit9e0d23cc47359149a39eafffdbb133963980b6ed (patch)
tree84ca4bd202768b2c71d3ed4f09abcd3e1a729e7d /tccelf.c
parent3494e5de3a03d021845666f55340d35af44e3bfc (diff)
downloadtinycc-9e0d23cc47359149a39eafffdbb133963980b6ed.tar.gz
tinycc-9e0d23cc47359149a39eafffdbb133963980b6ed.tar.bz2
tccasm: Unify C and asm symbol table
This makes the asm symbols use the same members as the C symbols for global decls, e.g. using the ELF symbol to hold offset and section. That allows us to use only one symbol table for C and asm symbols and to get rid of hacks to synch between them. We still need some special handling for symbols that come purely from asm sources.
Diffstat (limited to 'tccelf.c')
-rw-r--r--tccelf.c12
1 files changed, 9 insertions, 3 deletions
diff --git a/tccelf.c b/tccelf.c
index 22ce5df..422dfd6 100644
--- a/tccelf.c
+++ b/tccelf.c
@@ -310,7 +310,8 @@ static void rebuild_hash(Section *s, unsigned int nb_buckets)
sym = (ElfW(Sym) *)s->data + 1;
for(sym_index = 1; sym_index < nb_syms; sym_index++) {
- if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
+ if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL
+ || sym->st_shndx == SHN_UNDEF) {
h = elf_hash(strtab + sym->st_name) % nb_buckets;
*ptr = hash[h];
hash[h] = sym_index;
@@ -349,8 +350,9 @@ ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size,
int *ptr, *base;
ptr = section_ptr_add(hs, sizeof(int));
base = (int *)hs->data;
- /* only add global or weak symbols */
- if (ELFW(ST_BIND)(info) != STB_LOCAL) {
+ /* only add global, weak or undef symbols. The latter might
+ become global late (from asm references). */
+ if (ELFW(ST_BIND)(info) != STB_LOCAL || shndx == SHN_UNDEF) {
/* add another hashing entry */
nbuckets = base[0];
h = elf_hash((unsigned char *) name) % nbuckets;
@@ -486,6 +488,10 @@ ST_FUNC int set_elf_sym(Section *s, addr_t value, unsigned long size,
/* data symbol keeps precedence over common/bss */
} else if (s == tcc_state->dynsymtab_section) {
/* we accept that two DLL define the same symbol */
+ } else if (esym->st_other & ST_ASM_SET) {
+ /* If the existing symbol came from an asm .set
+ we can override. */
+ goto do_patch;
} else {
#if 0
printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n",