From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 31707 invoked by alias); 1 Jul 2009 07:04:34 -0000 Received: (qmail 31689 invoked by uid 22791); 1 Jul 2009 07:04:32 -0000 X-SWARE-Spam-Status: No, hits=-1.5 required=5.0 tests=AWL,BAYES_00 X-Spam-Check-By: sourceware.org Received: from eu1sys200aog106.obsmtp.com (HELO eu1sys200aog106.obsmtp.com) (207.126.144.121) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 01 Jul 2009 07:04:22 +0000 Received: from source ([164.129.1.35]) (using TLSv1) by eu1sys200aob106.postini.com ([207.126.147.11]) with SMTP ID DSNKSksKc7N53mUqK0uDtRH4t5r23++BWipG@postini.com; Wed, 01 Jul 2009 07:04:21 UTC Received: from zeta.dmz-eu.st.com (ns2.st.com [164.129.230.9]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id E3963112 for ; Wed, 1 Jul 2009 07:04:18 +0000 (GMT) Received: from mail1.ctn.st.com (mail1.ctn.st.com [164.130.116.128]) by zeta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 89C724BE50 for ; Wed, 1 Jul 2009 07:04:18 +0000 (GMT) Received: from localhost (mdt-dhcp33.ctn.st.com [10.52.139.33]) by mail1.ctn.st.com (MOS 3.8.7a) with ESMTP id DBQ58028 (AUTH arcidiaf); Wed, 1 Jul 2009 09:04:19 +0200 (CEST) From: Filippo ARCIDIACONO To: prelink@sourceware.org Cc: Filippo Arcidiacono Subject: [PATCH] Add TLS support for SH architecture. Date: Wed, 01 Jul 2009 07:04:00 -0000 Message-Id: <1246431789-3106-1-git-send-email-filippo.arcidiacono@st.com> X-IsSubscribed: yes Mailing-List: contact prelink-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Post: List-Help: , Sender: prelink-owner@sourceware.org X-SW-Source: 2009-q3/txt/msg00000.txt.bz2 This patch extend the prelink tool also for sh architecture adding the tls support, and fixes some architecture specific issue. The fix in the sh_undo_prelink_rela function is needed to restore all the GOT entries to the original value. In the prelink stage GOT[1] has been set to the first plt entry just after the plt header (This is the necessary code to jump at PLT[0]). To retrieve the other ones we need to add (28 * n) byte to the first one, where n is the n-th entry of the PLTn (n = 0,1,2,...). The fix in src/dwarf2.c avoid assertion fail at line 808 for layout[12], cxx[12] and undosyslibs tests. 2009-06-25 Filippo Arcidiacono * src/arch-sh.c: Added TLS relocation support on SH. * src/dwarf2.c: SH specific fix. * testsuite/reloc8.sh: Update test for SH. * testsuite/reloc9.sh: Update test for SH. * testsuite/tls3.sh: Update test for SH. --- src/arch-sh.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++---- src/dwarf2.c | 7 ++++ testsuite/reloc8.sh | 3 ++ testsuite/reloc9.sh | 3 ++ testsuite/tls3.sh | 2 +- 5 files changed, 108 insertions(+), 8 deletions(-) diff --git a/src/arch-sh.c b/src/arch-sh.c index c5c9f52..1944a74 100644 --- a/src/arch-sh.c +++ b/src/arch-sh.c @@ -85,8 +85,10 @@ sh_adjust_rela (DSO *dso, GElf_Rela *rela, GElf_Addr start, if (rela->r_addend && (Elf32_Addr) rela->r_addend >= start) { rela->r_addend += (Elf32_Sword) adjust; + write_ne32 (dso, rela->r_offset, rela->r_addend); break; } + break; /* FALLTHROUGH */ case R_SH_JMP_SLOT: data = read_une32 (dso, rela->r_offset); @@ -133,8 +135,26 @@ sh_prelink_rela (struct prelink_info *info, GElf_Rela *rela, write_ne32 (dso, rela->r_offset, value); break; case R_SH_REL32: - write_ne32 (dso, rela->r_offset, value - rela->r_addend); + write_ne32 (dso, rela->r_offset, value - rela->r_offset); break; + case R_SH_TLS_DTPOFF32: + write_ne32 (dso, rela->r_offset, value); + break; + /* DTPMOD32 and TPOFF{32,} is impossible to predict unless prelink + sets the rules. */ + case R_SH_TLS_DTPMOD32: + if (dso->ehdr.e_type == ET_EXEC) + { + error (0, 0, "%s: R_SH_TLS_DTPMOD32 reloc in executable?", + dso->filename); + return 1; + } + break; + case R_SH_TLS_TPOFF32: + if (dso->ehdr.e_type == ET_EXEC && info->resolvetls) + write_ne32 (dso, rela->r_offset, + (value + info->resolvetls->offset)); + break; case R_SH_COPY: if (dso->ehdr.e_type == ET_EXEC) /* COPY relocs are handled specially in generic code. */ @@ -218,6 +238,7 @@ sh_prelink_conflict_rela (DSO *dso, struct prelink_info *info, { GElf_Addr value; struct prelink_conflict *conflict; + struct prelink_tls *tls; GElf_Rela *ret; if (GELF_R_TYPE (rela->r_info) == R_SH_RELATIVE @@ -227,8 +248,31 @@ sh_prelink_conflict_rela (DSO *dso, struct prelink_info *info, conflict = prelink_conflict (info, GELF_R_SYM (rela->r_info), GELF_R_TYPE (rela->r_info)); if (conflict == NULL) + { + if (info->curtls == NULL) return 0; - value = conflict_lookup_value (conflict); + switch (GELF_R_TYPE (rela->r_info)) + { + /* Even local DTPMOD and TPOFF relocs need conflicts. */ + case R_SH_TLS_DTPMOD32: + case R_SH_TLS_TPOFF32: + break; + default: + return 0; + } + value = 0; + } + else + { + /* DTPOFF32 wants to see only real conflicts, not lookups + with reloc_class RTYPE_CLASS_TLS. */ + if (GELF_R_TYPE (rela->r_info) == R_SH_TLS_DTPOFF32 + && conflict->lookup.tls == conflict->conflict.tls + && conflict->lookupval == conflict->conflictval) + return 0; + + value = conflict_lookup_value (conflict); + } ret = prelink_conflict_add_rela (info); if (ret == NULL) return 1; @@ -247,11 +291,38 @@ sh_prelink_conflict_rela (DSO *dso, struct prelink_info *info, /* FALLTHROUGH */ case R_SH_GLOB_DAT: case R_SH_JMP_SLOT: - ret->r_addend = (Elf32_Sword) (value + rela->r_addend); + ret->r_addend = (Elf32_Sword) (value); break; case R_SH_COPY: error (0, 0, "R_SH_COPY should not be present in shared libraries"); return 1; + case R_SH_TLS_DTPMOD32: + case R_SH_TLS_DTPOFF32: + case R_SH_TLS_TPOFF32: + if (conflict != NULL + && (conflict->reloc_class != RTYPE_CLASS_TLS + || conflict->lookup.tls == NULL)) + { + error (0, 0, "%s: R_SH_TLS not resolving to STT_TLS symbol", + dso->filename); + return 1; + } + tls = conflict ? conflict->lookup.tls : info->curtls; + ret->r_info = GELF_R_INFO (0, R_SH_DIR32); + switch (GELF_R_TYPE (rela->r_info)) + { + case R_SH_TLS_DTPMOD32: + ret->r_addend = tls->modid; + break; + case R_SH_TLS_DTPOFF32: + ret->r_addend += value; + break; + case R_SH_TLS_TPOFF32: + ret->r_addend = value + tls->offset; + break; + } + break; + default: error (0, 0, "%s: Unknown sh relocation type %d", dso->filename, (int) GELF_R_TYPE (rela->r_info)); @@ -348,7 +419,7 @@ sh_undo_prelink_rela (DSO *dso, GElf_Rela *rela, GElf_Addr relaaddr) break; case R_SH_RELATIVE: if (rela->r_addend) - write_le32 (dso, rela->r_offset, 0); + write_ne32 (dso, rela->r_offset, 0); break; case R_SH_JMP_SLOT: sec = addr_to_sec (dso, rela->r_offset); @@ -365,15 +436,22 @@ sh_undo_prelink_rela (DSO *dso, GElf_Rela *rela, GElf_Addr relaaddr) assert (rela->r_offset >= dso->shdr[sec].sh_addr + 12); assert (((rela->r_offset - dso->shdr[sec].sh_addr) & 3) == 0); + /* + * In the prelink stage GOT[1] has been set to the first plt entry + * just after the plt header (This is the necessary code to jump at + * PLT[0]). + * To retrieve the other ones we need to add (28 * n) byte to the + * first one, where n is the n-th entry of the PLTn (n = 0,1,2,...). + */ write_ne32 (dso, rela->r_offset, - 7 * (rela->r_offset - dso->shdr[sec].sh_addr - 12) + 28 * ((rela->r_offset - dso->shdr[sec].sh_addr - 12) / 4) + data); } break; case R_SH_GLOB_DAT: case R_SH_DIR32: case R_SH_REL32: - write_ne32 (dso, rela->r_offset, 0); + write_ne32 (dso, rela->r_offset, rela->r_addend); break; case R_SH_COPY: if (dso->ehdr.e_type == ET_EXEC) @@ -381,6 +459,11 @@ sh_undo_prelink_rela (DSO *dso, GElf_Rela *rela, GElf_Addr relaaddr) return 0; error (0, 0, "%s: R_SH_COPY reloc in shared library?", dso->filename); return 1; + case R_SH_TLS_DTPMOD32: + case R_SH_TLS_DTPOFF32: + case R_SH_TLS_TPOFF32: + write_ne32 (dso, rela->r_offset, 0); + break; default: error (0, 0, "%s: Unknown sh relocation type %d", dso->filename, (int) GELF_R_TYPE (rela->r_info)); @@ -402,6 +485,10 @@ sh_reloc_class (int reloc_type) { case R_SH_COPY: return RTYPE_CLASS_COPY; case R_SH_JMP_SLOT: return RTYPE_CLASS_PLT; + case R_SH_TLS_DTPMOD32: + case R_SH_TLS_DTPOFF32: + case R_SH_TLS_TPOFF32: + return RTYPE_CLASS_TLS; default: return RTYPE_CLASS_VALID; } } @@ -441,6 +528,6 @@ PL_ARCH = { even dlopened libraries will get the slots they desire. */ .mmap_base = 0x30000000, .mmap_end = 0x40000000, - .max_page_size = 0x2000, + .max_page_size = 0x10000, .page_size = 0x1000 }; diff --git a/src/dwarf2.c b/src/dwarf2.c index 4c27836..4d3e1b9 100644 --- a/src/dwarf2.c +++ b/src/dwarf2.c @@ -789,6 +789,13 @@ adjust_dwarf2_aranges (DSO *dso, GElf_Addr start, GElf_Addr adjust) } ptr += 6; +#ifdef __SH4__ +/* + * This fix skips padding to avoid assertion fail at line 808 for + * layout[12], cxx[12] and undosyslibs tests. + */ + ptr += 8; +#endif while (ptr < endcu) { addr = read_ptr (ptr); diff --git a/testsuite/reloc8.sh b/testsuite/reloc8.sh index ea0a89e..d2377f0 100755 --- a/testsuite/reloc8.sh +++ b/testsuite/reloc8.sh @@ -8,6 +8,9 @@ NOCOPYRELOC=-Wl,-z,nocopyreloc case "`uname -m`" in x86_64|s390*) if file reloc1lib1.so | grep -q 64-bit; then NOCOPYRELOC=; fi;; esac +case "`uname -m`" in + sh4) NOCOPYRELOC=; +esac $CC -shared -O2 -Wl,-z,nocombreloc -fpic -o reloc8lib1.so $srcdir/reloc3lib1.c $CC -shared -O2 -Wl,-z,nocombreloc -fpic -o reloc8lib2.so $srcdir/reloc1lib2.c reloc8lib1.so BINS="reloc8" diff --git a/testsuite/reloc9.sh b/testsuite/reloc9.sh index 41fe578..4b2b57c 100755 --- a/testsuite/reloc9.sh +++ b/testsuite/reloc9.sh @@ -8,6 +8,9 @@ NOCOPYRELOC=-Wl,-z,nocopyreloc case "`uname -m`" in x86_64|s390*) if file reloc1lib1.so | grep -q 64-bit; then NOCOPYRELOC=; fi;; esac +case "`uname -m`" in + sh4) NOCOPYRELOC=; +esac $CC -shared -O2 -Wl,-z,nocombreloc -fpic -o reloc9lib1.so $srcdir/reloc3lib1.c $CC -shared -O2 -Wl,-z,nocombreloc -fpic -o reloc9lib2.so $srcdir/reloc1lib2.c reloc9lib1.so BINS="reloc9" diff --git a/testsuite/tls3.sh b/testsuite/tls3.sh index 34cbfd7..6ccb159 100755 --- a/testsuite/tls3.sh +++ b/testsuite/tls3.sh @@ -7,7 +7,7 @@ echo '__thread int a; int main (void) { return a; }' \ ( ./tlstest || { rm -f tlstest; exit 77; } ) 2>/dev/null || exit 77 SHFLAGS= case "`uname -m`" in - ia64|ppc*|x86_64|alpha*|s390*|mips*|arm*) SHFLAGS=-fpic;; # Does not support non-pic shared libs + ia64|ppc*|x86_64|alpha*|s390*|mips*|arm*|sh4) SHFLAGS=-fpic;; # Does not support non-pic shared libs esac # Disable this test under SELinux if textrel test -z "$SHFLAGS" -a -x /usr/sbin/getenforce -a "`/usr/sbin/getenforce`" = Enforcing && exit 77 -- 1.6.0.6