diff --git a/tccelf.c b/tccelf.c index b8fa5baf..e6f4f8f1 100644 --- a/tccelf.c +++ b/tccelf.c @@ -1544,23 +1544,25 @@ static int elf_output_file(TCCState *s1, const char *filename) index = put_elf_sym(s1->dynsym, offset, esym->st_size, esym->st_info, 0, bss_section->sh_num, name); - /* Ensure symbol aliases (that is, symbols with - the same st_value) resolve to the same - address in program .bss or .data section. */ - dynsym_end = (ElfW(Sym) *) - (s1->dynsymtab_section->data + - s1->dynsymtab_section->data_offset); - for(dynsym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1; - dynsym < dynsym_end; dynsym++) { - if (dynsym->st_value == esym->st_value) { - char *dynname; - dynname = s1->dynsymtab_section->link->data - + dynsym->st_name; - put_elf_sym(s1->dynsym, offset, - dynsym->st_size, - dynsym->st_info, 0, - bss_section->sh_num, - dynname); + // Ensure R_COPY works for weak symbol aliases + if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) { + dynsym_end = (ElfW(Sym) *) + (s1->dynsymtab_section->data + + s1->dynsymtab_section->data_offset); + for(dynsym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1; + dynsym < dynsym_end; dynsym++) { + if ((dynsym->st_value == esym->st_value) + && (ELFW(ST_BIND)(dynsym->st_info) == STB_GLOBAL)) { + char *dynname; + dynname = s1->dynsymtab_section->link->data + + dynsym->st_name; + put_elf_sym(s1->dynsym, offset, + dynsym->st_size, + dynsym->st_info, 0, + bss_section->sh_num, + dynname); + break; + } } } put_elf_reloc(s1->dynsym, bss_section,