aboutsummaryrefslogtreecommitdiff
path: root/tccelf.c
diff options
context:
space:
mode:
authorThomas Preud'homme <thomas.preudhomme@celest.fr>2010-04-26 00:46:39 +0200
committerThomas Preud'homme <thomas.preudhomme@celest.fr>2010-05-01 16:45:36 +0200
commita28b18fa16edaeb6bc7d34cf1ddac690b27ba610 (patch)
tree909b72cbe83ba6cc163d38afbba2c1f063d91810 /tccelf.c
parent036ff17916586febc968b964ee416e1d4d1da70f (diff)
downloadtinycc-a28b18fa16edaeb6bc7d34cf1ddac690b27ba610.tar.gz
tinycc-a28b18fa16edaeb6bc7d34cf1ddac690b27ba610.tar.bz2
Link alias symbols together
Make sure alias symbols resolve to the same address in program .bss or .data section. This ensure for example that if a program reference environ (via an extern char **environ declaration) and the libc change its value via the __environ alias after the R_ARCH_COPY relocation have been performed, then the program will see the new value.
Diffstat (limited to 'tccelf.c')
-rw-r--r--tccelf.c20
1 files changed, 20 insertions, 0 deletions
diff --git a/tccelf.c b/tccelf.c
index a35206e..91a203e 100644
--- a/tccelf.c
+++ b/tccelf.c
@@ -1510,12 +1510,32 @@ static int elf_output_file(TCCState *s1, const char *filename)
sym - (ElfW(Sym) *)symtab_section->data);
} else if (type == STT_OBJECT) {
unsigned long offset;
+ ElfW(Sym) *dynsym, *dynsym_end;
offset = bss_section->data_offset;
/* XXX: which alignment ? */
offset = (offset + 16 - 1) & -16;
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);
+ }
+ }
put_elf_reloc(s1->dynsym, bss_section,
offset, R_COPY, index);
offset += esym->st_size;