From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 19067 invoked by alias); 25 Aug 2009 12:23:14 -0000 Received: (qmail 19057 invoked by uid 22791); 25 Aug 2009 12:23:13 -0000 X-SWARE-Spam-Status: No, hits=-1.2 required=5.0 tests=AWL,BAYES_00,KAM_STOCKGEN,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.43rc1) with ESMTP; Tue, 25 Aug 2009 12:23:06 +0000 Received: (qmail 8304 invoked from network); 25 Aug 2009 12:23:02 -0000 Received: from unknown (HELO mbp.local) (maxim@127.0.0.2) by mail.codesourcery.com with ESMTPA; 25 Aug 2009 12:23:02 -0000 Message-ID: <4A93D79D.8050202@codesourcery.com> Date: Tue, 25 Aug 2009 18:52:00 -0000 From: Maxim Kuvyrkov User-Agent: Thunderbird 2.0.0.23 (Macintosh/20090812) MIME-Version: 1.0 To: binutils CC: Nick Clifton , Andreas Schwab Subject: [patch 2/2, m68k] Fix bugs in the handling of TLS relocations Content-Type: multipart/mixed; boundary="------------060104040804020004020604" X-IsSubscribed: yes Mailing-List: contact binutils-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: binutils-owner@sourceware.org X-SW-Source: 2009-08/txt/msg00463.txt.bz2 This is a multi-part message in MIME format. --------------060104040804020004020604 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Content-length: 462 Good day again, This second patch rewrites initialization of GOT entries and output of dynamic relocations. In the course of that it also fixes several bugs in the said processes. Unfortunately, I didn't get this work right the first time, so I have spent quite some time debugging relocation bugs in GLIBC. But now, with this brand new shiny patch everything seems to work as expected. Any comments? OK to check in? Thanks, -- Maxim K. CodeSourcery --------------060104040804020004020604 Content-Type: text/plain; x-mac-type="0"; x-mac-creator="0"; name="binutils-m68k-fix-2.ChangeLog" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="binutils-m68k-fix-2.ChangeLog" Content-length: 525 2009-08-25 Maxim Kuvyrkov * elf32-m68k.c: Rewrite initialization of GOT entries for TLS relocations. Rewrite output of dynamic TLS relocations. (DTP_OFFSET, TP_OFFSET): New constants. (dtpoff_base): Update. (tpoff): Rename to tpoff_base, update. (elf_m68k_init_got_entry_static, elf_m68k_init_got_entry_local_shared): New functions. Move code from elf_m68k_relocate_section here. (elf_m68k_relocate_section): Update. (elf_m68k_finish_dynamic_symbol): Fix handling of local TLS symbols. --------------060104040804020004020604 Content-Type: text/plain; x-mac-type="0"; x-mac-creator="0"; name="binutils-m68k-fix-2.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="binutils-m68k-fix-2.patch" Content-length: 13290 Index: elf32-m68k.c =================================================================== RCS file: /scratch/gcc/repos/src/src/bfd/elf32-m68k.c,v retrieving revision 1.112 diff -u -p -r1.112 elf32-m68k.c --- elf32-m68k.c 18 Jun 2009 14:18:29 -0000 1.112 +++ elf32-m68k.c 24 Aug 2009 21:30:16 -0000 @@ -3422,9 +3446,11 @@ elf_m68k_install_rela (bfd *output_bfd, bfd_elf32_swap_reloca_out (output_bfd, rela, loc); } -/* Return the base VMA address which should be subtracted from real addresses - when resolving @dtpoff relocation. - This is PT_TLS segment p_vaddr. */ +/* Find the base offsets for thread-local storage in this object, + for GD/LD and IE/LE respectively. */ + +#define DTP_OFFSET 0x8000 +#define TP_OFFSET 0x7000 static bfd_vma dtpoff_base (struct bfd_link_info *info) @@ -3432,23 +3458,116 @@ dtpoff_base (struct bfd_link_info *info) /* If tls_sec is NULL, we should have signalled an error already. */ if (elf_hash_table (info)->tls_sec == NULL) return 0; - return elf_hash_table (info)->tls_sec->vma; + return elf_hash_table (info)->tls_sec->vma + DTP_OFFSET; } -/* Return the relocation value for @tpoff relocation - if STT_TLS virtual address is ADDRESS. */ - static bfd_vma -tpoff (struct bfd_link_info *info, bfd_vma address) +tpoff_base (struct bfd_link_info *info) { - struct elf_link_hash_table *htab = elf_hash_table (info); - bfd_vma base; - /* If tls_sec is NULL, we should have signalled an error already. */ - if (htab->tls_sec == NULL) + if (elf_hash_table (info)->tls_sec == NULL) return 0; - base = align_power ((bfd_vma) 8, htab->tls_sec->alignment_power); - return address - htab->tls_sec->vma + base; + return elf_hash_table (info)->tls_sec->vma + TP_OFFSET; +} + +/* Output necessary relocation to handle a symbol during static link. + This function is called from elf_m68k_relocate_section. */ + +static void +elf_m68k_init_got_entry_static (struct bfd_link_info *info, + bfd *output_bfd, + enum elf_m68k_reloc_type r_type, + asection *sgot, + bfd_vma got_entry_offset, + bfd_vma relocation) +{ + switch (elf_m68k_reloc_got_type (r_type)) + { + case R_68K_GOT32O: + bfd_put_32 (output_bfd, relocation, sgot->contents + got_entry_offset); + break; + + case R_68K_TLS_GD32: + /* We know the offset within the module, + put it into the second GOT slot. */ + bfd_put_32 (output_bfd, relocation - dtpoff_base (info), + sgot->contents + got_entry_offset + 4); + /* FALLTHRU */ + + case R_68K_TLS_LDM32: + /* Mark it as belonging to module 1, the executable. */ + bfd_put_32 (output_bfd, 1, sgot->contents + got_entry_offset); + break; + + case R_68K_TLS_IE32: + bfd_put_32 (output_bfd, relocation - tpoff_base (info), + sgot->contents + got_entry_offset); + break; + + default: + BFD_ASSERT (FALSE); + } +} + +/* Output necessary relocation to handle a local symbol + during dynamic link. + This function is called either from elf_m68k_relocate_section + or from elf_m68k_finish_dynamic_symbol. */ + +static void +elf_m68k_init_got_entry_local_shared (struct bfd_link_info *info, + bfd *output_bfd, + enum elf_m68k_reloc_type r_type, + asection *sgot, + bfd_vma got_entry_offset, + bfd_vma relocation, + asection *srela) +{ + Elf_Internal_Rela outrel; + + switch (elf_m68k_reloc_got_type (r_type)) + { + case R_68K_GOT32O: + /* Emit RELATIVE relocation to initialize GOT slot + at run-time. */ + outrel.r_info = ELF32_R_INFO (0, R_68K_RELATIVE); + outrel.r_addend = relocation; + break; + + case R_68K_TLS_GD32: + /* We know the offset within the module, + put it into the second GOT slot. */ + bfd_put_32 (output_bfd, relocation - dtpoff_base (info), + sgot->contents + got_entry_offset + 4); + /* FALLTHRU */ + + case R_68K_TLS_LDM32: + /* We don't know the module number, + create a relocation for it. */ + outrel.r_info = ELF32_R_INFO (0, R_68K_TLS_DTPMOD32); + outrel.r_addend = 0; + break; + + case R_68K_TLS_IE32: + /* Emit TPREL relocation to initialize GOT slot + at run-time. */ + outrel.r_info = ELF32_R_INFO (0, R_68K_TLS_TPREL32); + outrel.r_addend = relocation - elf_hash_table (info)->tls_sec->vma; + break; + + default: + BFD_ASSERT (FALSE); + } + + /* Offset of the GOT entry. */ + outrel.r_offset = (sgot->output_section->vma + + sgot->output_offset + + got_entry_offset); + + /* Install one of the above relocations. */ + elf_m68k_install_rela (output_bfd, srela, &outrel); + + bfd_put_32 (output_bfd, outrel.r_addend, sgot->contents + got_entry_offset); } /* Relocate an M68K ELF section. */ @@ -3471,6 +3590,7 @@ elf_m68k_relocate_section (output_bfd, i asection *sgot; asection *splt; asection *sreloc; + asection *srela; struct elf_m68k_got *got; Elf_Internal_Rela *rel; Elf_Internal_Rela *relend; @@ -3482,6 +3602,7 @@ elf_m68k_relocate_section (output_bfd, i sgot = NULL; splt = NULL; sreloc = NULL; + srela = NULL; got = NULL; @@ -3680,7 +3801,7 @@ elf_m68k_relocate_section (output_bfd, i /* This is actually a static link, or it is a -Bsymbolic link and the symbol is defined locally, or the symbol was forced to be local - because of a version file.. We must initialize + because of a version file. We must initialize this entry in the global offset table. Since the offset must always be a multiple of 4, we use the least significant bit to record whether @@ -3690,26 +3811,12 @@ elf_m68k_relocate_section (output_bfd, i relocation entry to initialize the value. This is done in the finish_dynamic_symbol routine. */ - if (elf_m68k_reloc_got_type (r_type) == R_68K_GOT32O) - bfd_put_32 (output_bfd, relocation, - sgot->contents + off); - else if (elf_m68k_reloc_got_type (r_type) - == R_68K_TLS_GD32) - /* Mark it as belonging to module 1, - the executable. */ - { - bfd_put_32 (output_bfd, 1, - sgot->contents + off); - bfd_put_32 (output_bfd, (relocation - - dtpoff_base (info)), - sgot->contents + off + 4); - } - else if (elf_m68k_reloc_got_type (r_type) - == R_68K_TLS_IE32) - bfd_put_32 (output_bfd, tpoff (info, relocation), - sgot->contents + off); - else - BFD_ASSERT (FALSE); + elf_m68k_init_got_entry_static (info, + output_bfd, + r_type, + sgot, + off, + relocation); *off_ptr |= 1; } @@ -3717,103 +3824,32 @@ elf_m68k_relocate_section (output_bfd, i unresolved_reloc = FALSE; } else if (info->shared) /* && h == NULL */ + /* Process local symbol during dynamic link. */ { - asection *srela; - Elf_Internal_Rela outrel; - - srela = bfd_get_section_by_name (dynobj, ".rela.got"); - BFD_ASSERT (srela != NULL); - - if (elf_m68k_reloc_got_type (r_type) == R_68K_GOT32O) - { - /* Emit RELATIVE relocation to initialize GOT slot - at run-time. */ - outrel.r_info = ELF32_R_INFO (0, R_68K_RELATIVE); - outrel.r_addend = relocation; - outrel.r_offset = (sgot->output_section->vma - + sgot->output_offset - + off); - - elf_m68k_install_rela (output_bfd, srela, &outrel); - } - else if (elf_m68k_reloc_got_type (r_type) - == R_68K_TLS_LDM32) - { - /* If we don't know the module number, create - a relocation for it. */ - outrel.r_info = ELF32_R_INFO (0, R_68K_TLS_DTPMOD32); - outrel.r_addend = 0; - outrel.r_offset = (sgot->output_section->vma - + sgot->output_offset - + off); - - elf_m68k_install_rela (output_bfd, srela, &outrel); - } - else if (elf_m68k_reloc_got_type (r_type) - == R_68K_TLS_GD32) - { - /* If we don't know the module number, create - a relocation for it. */ - outrel.r_info = ELF32_R_INFO (0, R_68K_TLS_DTPMOD32); - outrel.r_addend = 0; - outrel.r_offset = (sgot->output_section->vma - + sgot->output_offset - + off); - - elf_m68k_install_rela (output_bfd, srela, &outrel); - - bfd_put_32 (output_bfd, (relocation - - dtpoff_base (info)), - sgot->contents + off + 4); - } - else if (elf_m68k_reloc_got_type (r_type) - == R_68K_TLS_IE32) + if (srela == NULL) { - outrel.r_info = ELF32_R_INFO (0, R_68K_TLS_TPREL32); - outrel.r_addend = relocation - dtpoff_base (info); - outrel.r_offset = (sgot->output_section->vma - + sgot->output_offset - + off); - - elf_m68k_install_rela (output_bfd, srela, &outrel); + srela = bfd_get_section_by_name (dynobj, ".rela.got"); + BFD_ASSERT (srela != NULL); } - else - BFD_ASSERT (FALSE); - bfd_put_32 (output_bfd, outrel.r_addend, - sgot->contents + off); + elf_m68k_init_got_entry_local_shared (info, + output_bfd, + r_type, + sgot, + off, + relocation, + srela); *off_ptr |= 1; } else /* h == NULL && !info->shared */ { - if (elf_m68k_reloc_got_type (r_type) == R_68K_GOT32O) - bfd_put_32 (output_bfd, relocation, - sgot->contents + off); - else if (elf_m68k_reloc_got_type (r_type) - == R_68K_TLS_LDM32) - /* If this is a static link, put the number of the - only module in the GOT slot. */ - bfd_put_32 (output_bfd, 1, sgot->contents + off); - else if (elf_m68k_reloc_got_type (r_type) - == R_68K_TLS_GD32) - { - /* If we are not emitting relocations for a - general dynamic reference, then we must be in a - static link or an executable link with the - symbol binding locally. Mark it as belonging - to module 1, the executable. */ - bfd_put_32 (output_bfd, 1, sgot->contents + off); - bfd_put_32 (output_bfd, (relocation - - dtpoff_base (info)), - sgot->contents + off + 4); - } - else if (elf_m68k_reloc_got_type (r_type) - == R_68K_TLS_IE32) - bfd_put_32 (output_bfd, tpoff (info, relocation), - sgot->contents + off); - else - BFD_ASSERT (FALSE); + elf_m68k_init_got_entry_static (info, + output_bfd, + r_type, + sgot, + off, + relocation); *off_ptr |= 1; } @@ -3843,7 +3879,6 @@ elf_m68k_relocate_section (output_bfd, i } /* This relocation does not use the addend. */ - BFD_ASSERT (rel->r_addend == 0); rel->r_addend = 0; } else @@ -3871,7 +3906,7 @@ elf_m68k_relocate_section (output_bfd, i return FALSE; } else - relocation = tpoff (info, relocation); + relocation -= tpoff_base (info); break; @@ -4270,15 +4305,12 @@ elf_m68k_finish_dynamic_symbol (output_b while (got_entry != NULL) { - Elf_Internal_Rela rela; + enum elf_m68k_reloc_type r_type; bfd_vma got_entry_offset; + r_type = got_entry->key_.type; got_entry_offset = got_entry->u.s2.offset &~ (bfd_vma) 1; - rela.r_offset = (sgot->output_section->vma - + sgot->output_offset - + got_entry_offset); - /* If this is a -Bsymbolic link, and the symbol is defined locally, we just want to emit a RELATIVE reloc. Likewise if the symbol was forced to be local because of a version file. @@ -4287,33 +4319,43 @@ elf_m68k_finish_dynamic_symbol (output_b if (info->shared && SYMBOL_REFERENCES_LOCAL (info, h)) { - rela.r_addend = bfd_get_signed_32 (output_bfd, - (sgot->contents - + got_entry_offset)); + bfd_vma relocation; + + relocation = bfd_get_signed_32 (output_bfd, + (sgot->contents + + got_entry_offset)); - switch (elf_m68k_reloc_got_type (got_entry->key_.type)) + /* Undo TP bias. */ + switch (elf_m68k_reloc_got_type (r_type)) { case R_68K_GOT32O: - rela.r_info = ELF32_R_INFO (0, R_68K_RELATIVE); + case R_68K_TLS_LDM32: break; case R_68K_TLS_GD32: - rela.r_info = ELF32_R_INFO (0, R_68K_TLS_DTPMOD32); + relocation += dtpoff_base (info); break; case R_68K_TLS_IE32: - rela.r_info = ELF32_R_INFO (0, R_68K_TLS_TPREL32); + relocation += tpoff_base (info); break; default: BFD_ASSERT (FALSE); - break; } - elf_m68k_install_rela (output_bfd, srela, &rela); + elf_m68k_init_got_entry_local_shared (info, + output_bfd, + r_type, + sgot, + got_entry_offset, + relocation, + srela); } else { + Elf_Internal_Rela rela; + /* Put zeros to GOT slots that will be initialized at run-time. */ { @@ -4327,8 +4369,11 @@ elf_m68k_finish_dynamic_symbol (output_b } rela.r_addend = 0; + rela.r_offset = (sgot->output_section->vma + + sgot->output_offset + + got_entry_offset); - switch (elf_m68k_reloc_got_type (got_entry->key_.type)) + switch (elf_m68k_reloc_got_type (r_type)) { case R_68K_GOT32O: rela.r_info = ELF32_R_INFO (h->dynindx, R_68K_GLOB_DAT); --------------060104040804020004020604--