aboutsummaryrefslogtreecommitdiff
path: root/tccelf.c
diff options
context:
space:
mode:
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",