X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felfxx-mips.c;h=9bae5d58378349261c9beef049416c1119d18270;hb=0bf60745767d2465c81ee57ae7705a62d6d8fafe;hp=951d1a72f300b94e7eba4b7c94f2d1dfc653fc8c;hpb=cc27e1dc443cce3873732b05a22c3ce4462e866a;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c index 951d1a72f3..9bae5d5837 100644 --- a/bfd/elfxx-mips.c +++ b/bfd/elfxx-mips.c @@ -23,7 +23,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ /* This file handles functionality common to the different MIPS ABI's. */ @@ -242,7 +242,8 @@ struct mips_elf_link_hash_entry being called returns a floating point value. */ asection *call_fp_stub; - /* Are we forced local? .*/ + /* Are we forced local? This will only be set if we have converted + the initial global GOT entry to a local GOT entry. */ bfd_boolean forced_local; #define GOT_NORMAL 0 @@ -478,10 +479,10 @@ static bfd *reldyn_sorting_bfd; #define MIPS_ELF_OPTIONS_SECTION_NAME(abfd) \ (NEWABI_P (abfd) ? ".MIPS.options" : ".options") -/* 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)) +/* True if NAME is the recognized name of any SHT_MIPS_OPTIONS section. + Some IRIX system files do not use MIPS_ELF_OPTIONS_SECTION_NAME. */ +#define MIPS_ELF_OPTIONS_SECTION_NAME_P(NAME) \ + (strcmp (NAME, ".MIPS.options") == 0 || strcmp (NAME, ".options") == 0) /* The name of the stub section. */ #define MIPS_ELF_STUB_SECTION_NAME(abfd) ".MIPS.stubs" @@ -961,7 +962,7 @@ mips_elf_create_procedure_table (void *handle, bfd *abfd, /* Skip this section later on (I don't think this currently matters, but someday it might). */ - s->link_order_head = NULL; + s->map_head.link_order = NULL; if (epdr != NULL) free (epdr); @@ -1907,15 +1908,14 @@ mips_elf_rel_dyn_section (bfd *dynobj, bfd_boolean create_p) sreloc = bfd_get_section_by_name (dynobj, dname); if (sreloc == NULL && create_p) { - sreloc = bfd_make_section (dynobj, dname); + sreloc = bfd_make_section_with_flags (dynobj, dname, + (SEC_ALLOC + | SEC_LOAD + | SEC_HAS_CONTENTS + | SEC_IN_MEMORY + | SEC_LINKER_CREATED + | SEC_READONLY)); if (sreloc == NULL - || ! bfd_set_section_flags (dynobj, sreloc, - (SEC_ALLOC - | SEC_LOAD - | SEC_HAS_CONTENTS - | SEC_IN_MEMORY - | SEC_LINKER_CREATED - | SEC_READONLY)) || ! bfd_set_section_alignment (dynobj, sreloc, MIPS_ELF_LOG_FILE_ALIGN (dynobj))) return NULL; @@ -2463,7 +2463,7 @@ mips_elf_create_local_got_entry (bfd *abfd, bfd *ibfd, global entry then. It doesn't matter whether an entry is local or global for TLS, since the dynamic linker does not automatically relocate TLS GOT entries. */ - BFD_ASSERT (h == NULL || h->forced_local); + BFD_ASSERT (h == NULL || h->root.forced_local); if (TLS_RELOC_P (r_type)) { struct mips_got_entry *p; @@ -3511,9 +3511,8 @@ mips_elf_create_compact_rel_section flags = (SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED | SEC_READONLY); - s = bfd_make_section (abfd, ".compact_rel"); + s = bfd_make_section_with_flags (abfd, ".compact_rel", flags); if (s == NULL - || ! bfd_set_section_flags (abfd, s, flags) || ! bfd_set_section_alignment (abfd, s, MIPS_ELF_LOG_FILE_ALIGN (abfd))) return FALSE; @@ -3554,9 +3553,8 @@ mips_elf_create_got_section (bfd *abfd, struct bfd_link_info *info, /* We have to use an alignment of 2**4 here because this is hardcoded in the function stub generation and in the linker script. */ - s = bfd_make_section (abfd, ".got"); + s = bfd_make_section_with_flags (abfd, ".got", flags); if (s == NULL - || ! bfd_set_section_flags (abfd, s, flags) || ! bfd_set_section_alignment (abfd, s, 4)) return FALSE; @@ -4010,10 +4008,6 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, &value, input_section)) return bfd_reloc_undefined; - - /* If we've written this we need to set DF_TEXTREL here. */ - if (MIPS_ELF_READONLY_SECTION (input_section)) - info->flags |= DF_TEXTREL; } else { @@ -4993,6 +4987,13 @@ _bfd_mips_elf_section_processing (bfd *abfd, Elf_Internal_Shdr *hdr) bfd_mips_elf_swap_options_in (abfd, (Elf_External_Options *) l, &intopt); + if (intopt.size < sizeof (Elf_External_Options)) + { + (*_bfd_error_handler) + (_("%B: Warning: bad `%s' option size %u smaller than its header"), + abfd, MIPS_ELF_OPTIONS_SECTION_NAME (abfd), intopt.size); + break; + } if (ABI_64_P (abfd) && intopt.kind == ODK_REGINFO) { bfd_byte buf[8]; @@ -5131,7 +5132,7 @@ _bfd_mips_elf_section_from_shdr (bfd *abfd, return FALSE; break; case SHT_MIPS_OPTIONS: - if (strcmp (name, MIPS_ELF_OPTIONS_SECTION_NAME (abfd)) != 0) + if (!MIPS_ELF_OPTIONS_SECTION_NAME_P (name)) return FALSE; break; case SHT_MIPS_DWARF: @@ -5149,7 +5150,7 @@ _bfd_mips_elf_section_from_shdr (bfd *abfd, return FALSE; break; default: - return FALSE; + break; } if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex)) @@ -5207,6 +5208,13 @@ _bfd_mips_elf_section_from_shdr (bfd *abfd, bfd_mips_elf_swap_options_in (abfd, (Elf_External_Options *) l, &intopt); + if (intopt.size < sizeof (Elf_External_Options)) + { + (*_bfd_error_handler) + (_("%B: Warning: bad `%s' option size %u smaller than its header"), + abfd, MIPS_ELF_OPTIONS_SECTION_NAME (abfd), intopt.size); + break; + } if (ABI_64_P (abfd) && intopt.kind == ODK_REGINFO) { Elf64_Internal_RegInfo intreg; @@ -5245,8 +5253,10 @@ bfd_boolean _bfd_mips_elf_fake_sections (bfd *abfd, Elf_Internal_Shdr *hdr, asection *sec) { register const char *name; + unsigned int sh_type; name = bfd_get_section_name (abfd, sec); + sh_type = hdr->sh_type; if (strcmp (name, ".liblist") == 0) { @@ -5319,7 +5329,7 @@ _bfd_mips_elf_fake_sections (bfd *abfd, Elf_Internal_Shdr *hdr, asection *sec) hdr->sh_flags |= SHF_MIPS_NOSTRIP; /* The sh_info field is set in final_write_processing. */ } - else if (strcmp (name, MIPS_ELF_OPTIONS_SECTION_NAME (abfd)) == 0) + else if (MIPS_ELF_OPTIONS_SECTION_NAME_P (name)) { hdr->sh_type = SHT_MIPS_OPTIONS; hdr->sh_entsize = 1; @@ -5348,6 +5358,12 @@ _bfd_mips_elf_fake_sections (bfd *abfd, Elf_Internal_Shdr *hdr, asection *sec) hdr->sh_entsize = 8; } + /* In the unlikely event a special section is empty it has to lose its + special meaning. This may happen e.g. when using `strip' with the + "--only-keep-debug" option. */ + if (sec->size > 0 && !(sec->flags & SEC_HAS_CONTENTS)) + hdr->sh_type = sh_type; + /* The generic elf_fake_sections will set up REL_HDR using the default kind of relocations. We used to set up a second header for the non-default kind of relocations here, but only NewABI would use @@ -5591,9 +5607,10 @@ _bfd_mips_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) if (bfd_get_section_by_name (abfd, MIPS_ELF_STUB_SECTION_NAME (abfd)) == NULL) { - s = bfd_make_section (abfd, MIPS_ELF_STUB_SECTION_NAME (abfd)); + s = bfd_make_section_with_flags (abfd, + MIPS_ELF_STUB_SECTION_NAME (abfd), + flags | SEC_CODE); if (s == NULL - || ! bfd_set_section_flags (abfd, s, flags | SEC_CODE) || ! bfd_set_section_alignment (abfd, s, MIPS_ELF_LOG_FILE_ALIGN (abfd))) return FALSE; @@ -5603,9 +5620,9 @@ _bfd_mips_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) && !info->shared && bfd_get_section_by_name (abfd, ".rld_map") == NULL) { - s = bfd_make_section (abfd, ".rld_map"); + s = bfd_make_section_with_flags (abfd, ".rld_map", + flags &~ (flagword) SEC_READONLY); if (s == NULL - || ! bfd_set_section_flags (abfd, s, flags &~ (flagword) SEC_READONLY) || ! bfd_set_section_alignment (abfd, s, MIPS_ELF_LOG_FILE_ALIGN (abfd))) return FALSE; @@ -6110,21 +6127,33 @@ _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. We make room for this reloc in the - .rel.dyn reloc section. */ - mips_elf_allocate_dynamic_relocations (dynobj, 1); + { + /* When creating a shared object, we must copy these + reloc types into the output file as R_MIPS_REL32 + relocs. We make room for this reloc in the + .rel.dyn reloc section. */ + mips_elf_allocate_dynamic_relocations (dynobj, 1); + if ((sec->flags & MIPS_READONLY_SECTION) + == MIPS_READONLY_SECTION) + /* We tell the dynamic linker that there are + relocations against the text segment. */ + info->flags |= DF_TEXTREL; + } else { struct mips_elf_link_hash_entry *hmips; - + /* We only need to copy this reloc if the symbol is 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) + /* We need it to tell the dynamic linker if there + are relocations against the text segment. */ + hmips->readonly_reloc = TRUE; } /* Even though we don't directly need a GOT entry for @@ -6420,12 +6449,9 @@ _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info, && (h->root.type == bfd_link_hash_defweak || !h->def_regular)) { - asection *sec; - sec = mips_elf_rel_dyn_section (dynobj, FALSE); mips_elf_allocate_dynamic_relocations (dynobj, hmips->possibly_dynamic_relocs); - - if (MIPS_ELF_READONLY_SECTION (sec)) + if (hmips->readonly_reloc) /* We tell the dynamic linker that there are relocations against the text segment. */ info->flags |= DF_TEXTREL; @@ -6790,7 +6816,7 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd, if (strip) { - _bfd_strip_section_from_output (info, s); + s->flags |= SEC_EXCLUDE; continue; } @@ -7670,18 +7696,6 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd, dyn.d_un.d_ptr = s->vma; break; - case DT_RELSZ: - /* Reduce DT_RELSZ to account for any relocations we - decided not to make. This is for the n64 irix rld, - which doesn't seem to apply any relocations if there - are trailing null entries. */ - s = mips_elf_rel_dyn_section (dynobj, FALSE); - dyn.d_un.d_val = (s->reloc_count - * (ABI_64_P (output_bfd) - ? sizeof (Elf64_Mips_External_Rel) - : sizeof (Elf32_External_Rel))); - break; - default: swap_out_p = FALSE; break; @@ -7743,6 +7757,55 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd, } } + /* The generation of dynamic relocations for the non-primary gots + adds more dynamic relocations. We cannot count them until + here. */ + + if (elf_hash_table (info)->dynamic_sections_created) + { + bfd_byte *b; + bfd_boolean swap_out_p; + + BFD_ASSERT (sdyn != NULL); + + for (b = sdyn->contents; + b < sdyn->contents + sdyn->size; + b += MIPS_ELF_DYN_SIZE (dynobj)) + { + Elf_Internal_Dyn dyn; + asection *s; + + /* Read in the current dynamic entry. */ + (*get_elf_backend_data (dynobj)->s->swap_dyn_in) (dynobj, b, &dyn); + + /* Assume that we're going to modify it and write it out. */ + swap_out_p = TRUE; + + switch (dyn.d_tag) + { + case DT_RELSZ: + /* Reduce DT_RELSZ to account for any relocations we + decided not to make. This is for the n64 irix rld, + which doesn't seem to apply any relocations if there + are trailing null entries. */ + s = mips_elf_rel_dyn_section (dynobj, FALSE); + dyn.d_un.d_val = (s->reloc_count + * (ABI_64_P (output_bfd) + ? sizeof (Elf64_Mips_External_Rel) + : sizeof (Elf32_External_Rel))); + break; + + default: + swap_out_p = FALSE; + break; + } + + if (swap_out_p) + (*get_elf_backend_data (dynobj)->s->swap_dyn_out) + (dynobj, &dyn, b); + } + } + { asection *s; Elf32_compact_rel cpt; @@ -8621,6 +8684,20 @@ _bfd_mips_elf_find_nearest_line (bfd *abfd, asection *section, filename_ptr, functionname_ptr, line_ptr); } + +bfd_boolean +_bfd_mips_elf_find_inliner_info (bfd *abfd, + const char **filename_ptr, + const char **functionname_ptr, + unsigned int *line_ptr) +{ + bfd_boolean found; + found = _bfd_dwarf2_find_inliner_info (abfd, filename_ptr, + functionname_ptr, line_ptr, + & elf_tdata (abfd)->dwarf2_find_line_info); + return found; +} + /* When are writing out the .options or .MIPS.options section, remember the bytes we are writing out, so that we can install the @@ -8631,7 +8708,7 @@ _bfd_mips_elf_set_section_contents (bfd *abfd, sec_ptr section, const void *location, file_ptr offset, bfd_size_type count) { - if (strcmp (section->name, MIPS_ELF_OPTIONS_SECTION_NAME (abfd)) == 0) + if (MIPS_ELF_OPTIONS_SECTION_NAME_P (section->name)) { bfd_byte *c; @@ -8754,30 +8831,21 @@ _bfd_elf_mips_get_relocated_section_contents /* Specific to MIPS: Deal with relocation types that require knowing the gp of the output bfd. */ asymbol *sym = *(*parent)->sym_ptr_ptr; - if (bfd_is_abs_section (sym->section) && abfd) - { - /* The special_function wouldn't get called anyway. */ - } - else if (!gp_found) - { - /* The gp isn't there; let the special function code - fall over on its own. */ - } - else if ((*parent)->howto->special_function - == _bfd_mips_elf32_gprel16_reloc) - { - /* bypass special_function call */ - r = _bfd_mips_elf_gprel16_with_gp (input_bfd, sym, *parent, - input_section, relocatable, - data, gp); - goto skip_bfd_perform_relocation; - } - /* end mips specific stuff */ - r = bfd_perform_relocation (input_bfd, *parent, data, input_section, - relocatable ? abfd : NULL, - &error_message); - skip_bfd_perform_relocation: + /* If we've managed to find the gp and have a special + function for the relocation then go ahead, else default + to the generic handling. */ + if (gp_found + && (*parent)->howto->special_function + == _bfd_mips_elf32_gprel16_reloc) + r = _bfd_mips_elf_gprel16_with_gp (input_bfd, sym, *parent, + input_section, relocatable, + data, gp); + else + r = bfd_perform_relocation (input_bfd, *parent, data, + input_section, + relocatable ? abfd : NULL, + &error_message); if (relocatable) { @@ -8873,7 +8941,6 @@ _bfd_mips_elf_link_hash_table_create (bfd *abfd) bfd_boolean _bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info) { - asection **secpp; asection *o; struct bfd_link_order *p; asection *reginfo_sec, *mdebug_sec, *gptab_data_sec, *gptab_bss_sec; @@ -8990,7 +9057,7 @@ _bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info) /* We have found the .reginfo section in the output file. Look through all the link_orders comprising it and merge the information together. */ - for (p = o->link_order_head; p != NULL; p = p->next) + for (p = o->map_head.link_order; p != NULL; p = p->next) { asection *input_section; bfd *input_bfd; @@ -9033,7 +9100,7 @@ _bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info) /* Skip this section later on (I don't think this currently matters, but someday it might). */ - o->link_order_head = NULL; + o->map_head.link_order = NULL; reginfo_sec = o; } @@ -9106,7 +9173,7 @@ _bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info) return FALSE; } - for (p = o->link_order_head; p != NULL; p = p->next) + for (p = o->map_head.link_order; p != NULL; p = p->next) { asection *input_section; bfd *input_bfd; @@ -9217,9 +9284,10 @@ _bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info) flagword flags = (SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED | SEC_READONLY); - rtproc_sec = bfd_make_section (abfd, ".rtproc"); + rtproc_sec = bfd_make_section_with_flags (abfd, + ".rtproc", + flags); if (rtproc_sec == NULL - || ! bfd_set_section_flags (abfd, rtproc_sec, flags) || ! bfd_set_section_alignment (abfd, rtproc_sec, 4)) return FALSE; } @@ -9246,7 +9314,7 @@ _bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info) /* Skip this section later on (I don't think this currently matters, but someday it might). */ - o->link_order_head = NULL; + o->map_head.link_order = NULL; mdebug_sec = o; } @@ -9265,7 +9333,7 @@ _bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info) not used in executables files. */ if (! info->relocatable) { - for (p = o->link_order_head; p != NULL; p = p->next) + for (p = o->map_head.link_order; p != NULL; p = p->next) { asection *input_section; @@ -9285,14 +9353,10 @@ _bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info) /* Skip this section later on (I don't think this currently matters, but someday it might). */ - o->link_order_head = NULL; + o->map_head.link_order = NULL; /* Really remove the section. */ - for (secpp = &abfd->sections; - *secpp != o; - secpp = &(*secpp)->next) - ; - bfd_section_list_remove (abfd, secpp); + bfd_section_list_remove (abfd, o); --abfd->section_count; continue; @@ -9339,7 +9403,7 @@ _bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info) tab[0].gt_header.gt_unused = 0; /* Combine the input sections. */ - for (p = o->link_order_head; p != NULL; p = p->next) + for (p = o->map_head.link_order; p != NULL; p = p->next) { asection *input_section; bfd *input_bfd; @@ -9462,7 +9526,7 @@ _bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info) /* Skip this section later on (I don't think this currently matters, but someday it might). */ - o->link_order_head = NULL; + o->map_head.link_order = NULL; } } @@ -9901,13 +9965,63 @@ _bfd_mips_elf_print_private_bfd_data (bfd *abfd, void *ptr) return TRUE; } -struct bfd_elf_special_section const _bfd_mips_elf_special_sections[]= +static struct bfd_elf_special_section const + mips_special_sections_l[]= { - { ".sdata", 6, -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_MIPS_GPREL }, - { ".sbss", 5, -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_MIPS_GPREL }, { ".lit4", 5, 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_MIPS_GPREL }, { ".lit8", 5, 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_MIPS_GPREL }, - { ".ucode", 6, 0, SHT_MIPS_UCODE, 0 }, + { NULL, 0, 0, 0, 0 } +}; + +static struct bfd_elf_special_section const + mips_special_sections_m[]= +{ { ".mdebug", 7, 0, SHT_MIPS_DEBUG, 0 }, { NULL, 0, 0, 0, 0 } }; + +static struct bfd_elf_special_section const + mips_special_sections_s[]= +{ + { ".sdata", 6, -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_MIPS_GPREL }, + { ".sbss", 5, -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_MIPS_GPREL }, +}; + +static struct bfd_elf_special_section const + mips_special_sections_u[]= +{ + { ".ucode", 6, 0, SHT_MIPS_UCODE, 0 }, + { NULL, 0, 0, 0, 0 } +}; + +struct bfd_elf_special_section const * + _bfd_mips_elf_special_sections[27] = +{ + NULL, /* 'a' */ + NULL, /* 'b' */ + NULL, /* 'c' */ + NULL, /* 'd' */ + NULL, /* 'e' */ + NULL, /* 'f' */ + NULL, /* 'g' */ + NULL, /* 'h' */ + NULL, /* 'i' */ + NULL, /* 'j' */ + NULL, /* 'k' */ + mips_special_sections_l, /* 'l' */ + mips_special_sections_m, /* 'm' */ + NULL, /* 'n' */ + NULL, /* 'o' */ + NULL, /* 'p' */ + NULL, /* 'q' */ + NULL, /* 'r' */ + mips_special_sections_s, /* 'm' */ + NULL, /* 't' */ + mips_special_sections_u, /* 'u' */ + NULL, /* 'v' */ + NULL, /* 'w' */ + NULL, /* 'x' */ + NULL, /* 'y' */ + NULL, /* 'z' */ + NULL /* other */ +};