aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tccelf.c36
1 files changed, 19 insertions, 17 deletions
diff --git a/tccelf.c b/tccelf.c
index b8fa5ba..e6f4f8f 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,