From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 27229 invoked by alias); 29 Sep 2008 15:31:07 -0000 Received: (qmail 27217 invoked by uid 22791); 29 Sep 2008 15:31:04 -0000 X-Spam-Status: No, hits=-1.3 required=5.0 tests=AWL,BAYES_05,J_CHICKENPOX_22,SPF_PASS X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (65.74.133.4) by sourceware.org (qpsmtpd/0.31) with ESMTP; Mon, 29 Sep 2008 15:30:21 +0000 Received: (qmail 14385 invoked from network); 29 Sep 2008 15:30:19 -0000 Received: from unknown (HELO digraph.polyomino.org.uk) (joseph@127.0.0.2) by mail.codesourcery.com with ESMTPA; 29 Sep 2008 15:30:19 -0000 Received: from jsm28 (helo=localhost) by digraph.polyomino.org.uk with local-esmtp (Exim 4.68) (envelope-from ) id 1KkKhV-0004yK-L5 for prelink@sourceware.org; Mon, 29 Sep 2008 15:30:17 +0000 Date: Mon, 29 Sep 2008 15:31:00 -0000 From: "Joseph S. Myers" X-X-Sender: jsm28@digraph.polyomino.org.uk To: prelink@sourceware.org Subject: SPARC64 prelink TLS and current kernels support Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII 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: 2008-q3/txt/msg00000.txt.bz2 This patch adds TLS support to SPARC64 prelink - largely cut-and-pasted from the 32-bit SPARC support - and updates it to work with kernels postdating the patch 8bcd17411643beb9a601e032d0cf1016909a81d3 "[SPARC64]: Do not allow mapping pages within 4GB of 64-bit VA hole." (March 2006), which changed TASK_UNMAPPED_BASE causing anything prelinked at the old address to segfault on startup. Please commit if OK. 2008-09-29 Joseph Myers * src/arch-sparc64.c (sparc64_prelink_rela, sparc64_prelink_conflict_rela, sparc64_undo_prelink_rela, sparc64_reloc_class): Handle TLS relocations. (PL_ARCH): Update mmap_base and mmap_end for TASK_UNMAPPED_BASE change to 0xfffff80100000000. Index: src/arch-sparc64.c =================================================================== --- src/arch-sparc64.c (revision 163) +++ src/arch-sparc64.c (working copy) @@ -232,6 +232,38 @@ (((value - rela->r_offset) >> 2) & 0x3fffffff) | (read_ube32 (dso, rela->r_offset) & 0xc0000000)); break; + case R_SPARC_TLS_DTPOFF64: + write_be64 (dso, rela->r_offset, value + rela->r_addend); + break; + /* DTPMOD64 and TPOFF64 is impossible to predict in shared libraries + unless prelink sets the rules. */ + case R_SPARC_TLS_DTPMOD64: + if (dso->ehdr.e_type == ET_EXEC) + { + error (0, 0, "%s: R_SPARC_TLS_DTPMOD64 reloc in executable?", + dso->filename); + return 1; + } + break; + case R_SPARC_TLS_TPOFF64: + if (dso->ehdr.e_type == ET_EXEC && info->resolvetls) + write_be64 (dso, rela->r_offset, + value + rela->r_addend - info->resolvetls->offset); + break; + case R_SPARC_TLS_LE_HIX22: + if (dso->ehdr.e_type == ET_EXEC && info->resolvetls) + write_be32 (dso, rela->r_offset, + (read_ube32 (dso, rela->r_offset) & 0xffc00000) + | (((~(value + rela->r_addend - info->resolvetls->offset)) + >> 10) & 0x3fffff)); + break; + case R_SPARC_TLS_LE_LOX10: + if (dso->ehdr.e_type == ET_EXEC && info->resolvetls) + write_be32 (dso, rela->r_offset, + (read_ube32 (dso, rela->r_offset) & 0xffffe000) | 0x1c00 + | ((value + rela->r_addend - info->resolvetls->offset) + & 0x3ff)); + break; case R_SPARC_H44: write_be32 (dso, rela->r_offset, ((value >> 22) & 0x3fffff) @@ -405,6 +437,7 @@ { GElf_Addr value; struct prelink_conflict *conflict; + struct prelink_tls *tls; GElf_Rela *ret; int r_type; @@ -415,8 +448,33 @@ conflict = prelink_conflict (info, GELF_R_SYM (rela->r_info), SPARC64_R_TYPE (rela->r_info)); if (conflict == NULL) - return 0; - value = conflict_lookup_value (conflict); + { + if (info->curtls == NULL) + return 0; + switch (SPARC64_R_TYPE (rela->r_info)) + { + /* Even local DTPMOD64 and TPOFF64 relocs need conflicts. */ + case R_SPARC_TLS_DTPMOD64: + case R_SPARC_TLS_TPOFF64: + case R_SPARC_TLS_LE_HIX22: + case R_SPARC_TLS_LE_LOX10: + break; + default: + return 0; + } + value = 0; + } + else + { + /* DTPOFF64 wants to see only real conflicts, not lookups + with reloc_class RTYPE_CLASS_TLS. */ + if (SPARC64_R_TYPE (rela->r_info) == R_SPARC_TLS_DTPOFF64 + && 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; @@ -500,6 +558,47 @@ case R_SPARC_UA32: case R_SPARC_UA64: break; + case R_SPARC_TLS_DTPMOD64: + case R_SPARC_TLS_DTPOFF64: + case R_SPARC_TLS_TPOFF64: + case R_SPARC_TLS_LE_HIX22: + case R_SPARC_TLS_LE_LOX10: + if (conflict != NULL + && (conflict->reloc_class != RTYPE_CLASS_TLS + || conflict->lookup.tls == NULL)) + { + error (0, 0, "%s: TLS reloc not resolving to STT_TLS symbol", + dso->filename); + return 1; + } + tls = conflict ? conflict->lookup.tls : info->curtls; + switch (r_type) + { + case R_SPARC_TLS_DTPMOD64: + r_type = R_SPARC_64; + value = tls->modid; + break; + case R_SPARC_TLS_DTPOFF64: + r_type = R_SPARC_64; + break; + case R_SPARC_TLS_TPOFF64: + r_type = R_SPARC_64; + value -= tls->offset; + break; + case R_SPARC_TLS_LE_HIX22: + r_type = R_SPARC_32; + value -= tls->offset; + value = (read_ube32 (dso, rela->r_offset) & 0xffc00000) + | (((~value) >> 10) & 0x3fffff); + break; + case R_SPARC_TLS_LE_LOX10: + r_type = R_SPARC_32; + value -= tls->offset; + value = (read_ube32 (dso, rela->r_offset) & 0xffffe000) | 0x1c00 + | (value & 0x3ff); + break; + } + break; default: error (0, 0, "%s: Unknown Sparc relocation type %d", dso->filename, r_type); @@ -582,6 +681,9 @@ case R_SPARC_64: case R_SPARC_UA64: case R_SPARC_DISP64: + case R_SPARC_TLS_DTPMOD64: + case R_SPARC_TLS_DTPOFF64: + case R_SPARC_TLS_TPOFF64: write_be64 (dso, rela->r_offset, 0); break; case R_SPARC_32: @@ -635,6 +737,14 @@ write_be32 (dso, rela->r_offset, read_ube32 (dso, rela->r_offset) & ~0x1fff); break; + case R_SPARC_TLS_LE_LOX10: + write_be32 (dso, rela->r_offset, + read_ube32 (dso, rela->r_offset) & 0xffffe000); + break; + case R_SPARC_TLS_LE_HIX22: + write_be32 (dso, rela->r_offset, + read_ube32 (dso, rela->r_offset) & 0xffc00000); + break; case R_SPARC_COPY: if (dso->ehdr.e_type == ET_EXEC) /* COPY relocs are handled specially in generic code. */ @@ -679,6 +789,12 @@ { case R_SPARC_COPY: return RTYPE_CLASS_COPY; case R_SPARC_JMP_SLOT: return RTYPE_CLASS_PLT; + case R_SPARC_TLS_DTPMOD64: + case R_SPARC_TLS_DTPOFF64: + case R_SPARC_TLS_TPOFF64: + case R_SPARC_TLS_LE_HIX22: + case R_SPARC_TLS_LE_LOX10: + return RTYPE_CLASS_TLS; default: return RTYPE_CLASS_VALID; } } @@ -709,17 +825,17 @@ .max_reloc_size = 8, .arch_prelink = sparc64_arch_prelink, .undo_prelink_rela = sparc64_undo_prelink_rela, - /* Although TASK_UNMAPPED_BASE is 0xfffff80000000000, we leave some + /* Although TASK_UNMAPPED_BASE is 0xfffff80100000000, we leave some area so that mmap of /etc/ld.so.cache and ld.so's malloc does not take some library's VA slot. Also, if this guard area isn't too small, typically even dlopened libraries will get the slots they desire. */ - .mmap_base = 0xfffff80001000000LL, + .mmap_base = 0xfffff80101000000LL, /* If we need yet more space for shared libraries, we can of course expand, but limiting all DSOs into 4 GB means stack overflows jumping to shared library functions is much harder (there is '\0' byte in the address before the bytes that matter). */ - .mmap_end = 0xfffff80100000000LL, + .mmap_end = 0xfffff80200000000LL, .max_page_size = 0x100000, .page_size = 0x2000 }; -- Joseph S. Myers joseph@codesourcery.com