aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Glöckner <daniel-gl@gmx.net>2010-06-23 00:20:32 +0200
committerThomas Preud'homme <thomas.preudhomme@celest.fr>2011-08-12 18:28:45 +0200
commitab7ed48ee8c244276c73e6893cf8ce2c52d9b6db (patch)
treeff3993d95e1ab548ca166f554ea0fc39704e6222
parentbf374a5f238360d6a5055d79f53065fa95a26047 (diff)
downloadtinycc-ab7ed48ee8c244276c73e6893cf8ce2c52d9b6db.tar.gz
tinycc-ab7ed48ee8c244276c73e6893cf8ce2c52d9b6db.tar.bz2
Fix problem with PLT and GOT relocs on armel.
TinyCC fails to link correctly to libraries when both R_ARM_PLT32 and R_ARM_GOT32 relocation to a same symbol exist (see http://lists.nongnu.org/archive/html/tinycc-devel/2010-05/msg00032.html for more details). The patch marks all undefined weak symbols found in external libraries as strong. The value of all remaining weak symbols is set to zero just before the section is output. Note by Thomas Preud'homme: it's been 2 months in Debian without any new bug report, hence commiting.
-rw-r--r--tccelf.c15
1 files changed, 12 insertions, 3 deletions
diff --git a/tccelf.c b/tccelf.c
index e166393..e20752c 100644
--- a/tccelf.c
+++ b/tccelf.c
@@ -1356,6 +1356,17 @@ void patch_dynsym_undef(TCCState *s1, Section *s)
#else
#define HAVE_PHDR 0
#define EXTRA_RELITEMS 9
+
+/* zero plt offsets of weak symbols in .dynsym */
+void patch_dynsym_undef(TCCState *s1, Section *s)
+{
+ ElfW(Sym) *sym, *sym_end;
+
+ sym_end = (ElfW(Sym) *)(s->data + s->data_offset);
+ for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++)
+ if (sym->st_shndx == SHN_UNDEF && ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
+ sym->st_value = 0;
+}
#endif
ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel)
@@ -1499,7 +1510,7 @@ static int elf_output_file(TCCState *s1, const char *filename)
type = ELFW(ST_TYPE)(esym->st_info);
if ((type == STT_FUNC) || (type == STT_GNU_IFUNC)) {
put_got_entry(s1, R_JMP_SLOT, esym->st_size,
- esym->st_info,
+ ELFW(ST_INFO)(STB_GLOBAL,type),
sym - (ElfW(Sym) *)symtab_section->data);
} else if (type == STT_OBJECT) {
unsigned long offset;
@@ -2125,10 +2136,8 @@ static int elf_output_file(TCCState *s1, const char *filename)
for(i=1;i<s1->nb_sections;i++) {
s = s1->sections[section_order[i]];
if (s->sh_type != SHT_NOBITS) {
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
if (s->sh_type == SHT_DYNSYM)
patch_dynsym_undef(s1, s);
-#endif
while (offset < s->sh_offset) {
fputc(0, f);
offset++;