From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 11733 invoked by alias); 18 May 2006 21:31:56 -0000 Received: (qmail 11721 invoked by uid 22791); 18 May 2006 21:31:55 -0000 X-Spam-Check-By: sourceware.org Received: from nevyn.them.org (HELO nevyn.them.org) (66.93.172.17) by sourceware.org (qpsmtpd/0.31.1) with ESMTP; Thu, 18 May 2006 21:31:51 +0000 Received: from drow by nevyn.them.org with local (Exim 4.54) id 1Fgq61-0004Eo-9g for binutils@sourceware.org; Thu, 18 May 2006 17:31:49 -0400 Date: Fri, 19 May 2006 00:37:00 -0000 From: Daniel Jacobowitz To: binutils@sourceware.org Subject: MIPS textrel fix Message-ID: <20060518213149.GA14720@nevyn.them.org> Mail-Followup-To: binutils@sourceware.org MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.11+cvs20060403 Mailing-List: contact binutils-help@sourceware.org; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: binutils-owner@sourceware.org X-SW-Source: 2006-05/txt/msg00317.txt.bz2 While stuck offline earlier today, I revisited the textrel-1 MIPS failure. Eric originally tried setting DF_TEXTREL during section relocation, but it's too late: we add the entry in size_dynamic_sections. But I couldn't see any other way to get it right, since there's no hook to predict whether elf-eh-frame.c will eliminate a relocation. The easiest approach I found was to annul the DT_TEXTREL and DT_FLAGS changes in finish_dynamic_sections if no text relocations were actually generated. This is not immensely pretty, but does work. OK? For background, the problem arises from the use of absolute addresses in .eh_frame. In this case, they're being produced by gas CFI directives. Is there a reason we can't mix and match encodings? i.e. why not have gas use a PC-relative format? I'm sure there's a reason, but I can't think of it... -- Daniel Jacobowitz CodeSourcery 2006-05-18 Daniel Jacobowitz * elflink.c (_bfd_elf_add_dynamic_entry): Remove DT_TEXTREL check. (bfd_elf_final_link): Add a late DT_TEXTREL check. * elfxx-mips.c (MIPS_ELF_READONLY_SECTION): Define. (mips_elf_create_dynamic_relocation): Set DF_TEXTREL. (_bfd_mips_elf_check_relocs): Delete MIPS_READONLY_SECTION. Use MIPS_ELF_READONLY_SECTION. (_bfd_mips_elf_size_dynamic_sections): Clear DF_TEXTREL after creating DT_TEXTREL. (_bfd_mips_elf_finish_dynamic_sections): Clear textrel markers if no text relocations were generated. Index: elflink.c =================================================================== RCS file: /cvs/src/src/bfd/elflink.c,v retrieving revision 1.210.2.3 diff -u -p -r1.210.2.3 elflink.c --- elflink.c 17 May 2006 05:14:21 -0000 1.210.2.3 +++ elflink.c 18 May 2006 21:24:41 -0000 @@ -2810,10 +2810,6 @@ _bfd_elf_add_dynamic_entry (struct bfd_l if (! is_elf_hash_table (hash_table)) return FALSE; - if (info->warn_shared_textrel && info->shared && tag == DT_TEXTREL) - _bfd_error_handler - (_("warning: creating a DT_TEXTREL in a shared object.")); - bed = get_elf_backend_data (hash_table->dynobj); s = bfd_get_section_by_name (hash_table->dynobj, ".dynamic"); BFD_ASSERT (s != NULL); @@ -8655,6 +8651,32 @@ bfd_elf_final_link (bfd *abfd, struct bf if (! (*bed->elf_backend_finish_dynamic_sections) (abfd, info)) goto error_return; + /* Check for DT_TEXTREL (late, in case the backend removes it). */ + if (info->warn_shared_textrel && info->shared) + { + bfd_byte *dyncon, *dynconend; + + /* Fix up .dynamic entries. */ + o = bfd_get_section_by_name (dynobj, ".dynamic"); + BFD_ASSERT (o != NULL); + + dyncon = o->contents; + dynconend = o->contents + o->size; + for (; dyncon < dynconend; dyncon += bed->s->sizeof_dyn) + { + Elf_Internal_Dyn dyn; + + bed->s->swap_dyn_in (dynobj, dyncon, &dyn); + + if (dyn.d_tag == DT_TEXTREL) + { + _bfd_error_handler + (_("warning: creating a DT_TEXTREL in a shared object.")); + break; + } + } + } + for (o = dynobj->sections; o != NULL; o = o->next) { if ((o->flags & SEC_HAS_CONTENTS) == 0 Index: elfxx-mips.c =================================================================== RCS file: /cvs/src/src/bfd/elfxx-mips.c,v retrieving revision 1.165 diff -u -p -r1.165 elfxx-mips.c --- elfxx-mips.c 27 Mar 2006 11:30:53 -0000 1.165 +++ elfxx-mips.c 18 May 2006 21:24:42 -0000 @@ -535,6 +535,11 @@ static bfd *reldyn_sorting_bfd; #define MIPS_ELF_OPTIONS_SECTION_NAME_P(NAME) \ (strcmp (NAME, ".MIPS.options") == 0 || strcmp (NAME, ".options") == 0) +/* Whether the section is readonly. */ +#define MIPS_ELF_READONLY_SECTION(sec) \ + ((sec->flags & (SEC_ALLOC | SEC_LOAD | SEC_READONLY)) \ + == (SEC_ALLOC | SEC_LOAD | SEC_READONLY)) + /* The name of the stub section. */ #define MIPS_ELF_STUB_SECTION_NAME(abfd) ".MIPS.stubs" @@ -4909,6 +4914,12 @@ mips_elf_create_dynamic_relocation (bfd } } + /* If we've written this relocation for a readonly section, + we need to set DF_TEXTREL again, so that we do not delete the + DT_TEXTREL tag. */ + if (MIPS_ELF_READONLY_SECTION (input_section)) + info->flags |= DF_TEXTREL; + return TRUE; } @@ -6513,15 +6524,13 @@ _bfd_mips_elf_check_relocs (bfd *abfd, s if (sreloc == NULL) return FALSE; } -#define MIPS_READONLY_SECTION (SEC_ALLOC | SEC_LOAD | SEC_READONLY) if (info->shared) { /* When creating a shared object, we must copy these reloc types into the output file as R_MIPS_REL32 relocs. Make room for this reloc in .rel(a).dyn. */ mips_elf_allocate_dynamic_relocations (dynobj, info, 1); - if ((sec->flags & MIPS_READONLY_SECTION) - == MIPS_READONLY_SECTION) + if (MIPS_ELF_READONLY_SECTION (sec)) /* We tell the dynamic linker that there are relocations against the text segment. */ info->flags |= DF_TEXTREL; @@ -6534,8 +6543,7 @@ _bfd_mips_elf_check_relocs (bfd *abfd, s defined in a dynamic object. */ hmips = (struct mips_elf_link_hash_entry *) h; ++hmips->possibly_dynamic_relocs; - if ((sec->flags & MIPS_READONLY_SECTION) - == MIPS_READONLY_SECTION) + if (MIPS_ELF_READONLY_SECTION (sec)) /* We need it to tell the dynamic linker if there are relocations against the text segment. */ hmips->readonly_reloc = TRUE; @@ -7452,6 +7460,12 @@ _bfd_mips_elf_size_dynamic_sections (bfd { if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_TEXTREL, 0)) return FALSE; + + /* Clear the DF_TEXTREL flag. It will be set again if we + write out an actual text relocation; we may not, because + at this point we do not know whether e.g. any .eh_frame + absolute relocations have been converted to PC-relative. */ + info->flags &= ~DF_TEXTREL; } if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_PLTGOT, 0)) @@ -8478,6 +8492,7 @@ _bfd_mips_elf_finish_dynamic_sections (b if (elf_hash_table (info)->dynamic_sections_created) { bfd_byte *b; + int dyn_to_skip = 0, dyn_skipped = 0; BFD_ASSERT (sdyn != NULL); BFD_ASSERT (g != NULL); @@ -8632,15 +8647,44 @@ _bfd_mips_elf_finish_dynamic_sections (b + htab->srelplt->output_offset); break; + case DT_TEXTREL: + /* If we didn't need any text relocations after all, delete + the dynamic tag. */ + if (!(info->flags & DF_TEXTREL)) + { + dyn_to_skip = MIPS_ELF_DYN_SIZE (dynobj); + swap_out_p = FALSE; + } + break; + + case DT_FLAGS: + /* If we didn't need any text relocations after all, clear + DF_TEXTREL from DT_FLAGS. */ + if (!(info->flags & DF_TEXTREL)) + dyn.d_un.d_val &= ~DF_TEXTREL; + else + swap_out_p = FALSE; + break; + default: swap_out_p = FALSE; break; } - if (swap_out_p) + if (swap_out_p || dyn_skipped) (*get_elf_backend_data (dynobj)->s->swap_dyn_out) - (dynobj, &dyn, b); + (dynobj, &dyn, b - dyn_skipped); + + if (dyn_to_skip) + { + dyn_skipped += dyn_to_skip; + dyn_to_skip = 0; + } } + + /* Wipe out any trailing entries if we shifted down a dynamic tag. */ + if (dyn_skipped > 0) + memset (b - dyn_skipped, 0, dyn_skipped); } if (sgot != NULL && sgot->size > 0)