diff options
-rw-r--r-- | bfd/ChangeLog | 14 | ||||
-rw-r--r-- | bfd/elflink.c | 30 | ||||
-rw-r--r-- | bfd/elfxx-mips.c | 58 |
3 files changed, 91 insertions, 11 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 937acc924ba..76e740c8476 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,17 @@ +2006-05-22 Daniel Jacobowitz <dan@codesourcery.com> + + * 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. + 2006-05-19 H.J. Lu <hongjiu.lu@intel.com> * elfxx-ia64.c (ELF_MAXPAGESIZE): Fix a typo in comment. diff --git a/bfd/elflink.c b/bfd/elflink.c index 338ee0610fc..ff401f2c7d0 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -2810,10 +2810,6 @@ _bfd_elf_add_dynamic_entry (struct bfd_link_info *info, 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 bfd_link_info *info) 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 diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c index e86f7127149..b22d2a2fe7f 100644 --- a/bfd/elfxx-mips.c +++ b/bfd/elfxx-mips.c @@ -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" @@ -4912,6 +4917,12 @@ mips_elf_create_dynamic_relocation (bfd *output_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; } @@ -6507,15 +6518,13 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, 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; @@ -6528,8 +6537,7 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, 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; @@ -7446,6 +7454,12 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_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)) @@ -8472,6 +8486,7 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd, 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); @@ -8626,15 +8641,44 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd, + 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) |