diff options
Diffstat (limited to 'bfd/elf32-mips.c')
-rw-r--r-- | bfd/elf32-mips.c | 552 |
1 files changed, 329 insertions, 223 deletions
diff --git a/bfd/elf32-mips.c b/bfd/elf32-mips.c index c254ecf..b6c544a 100644 --- a/bfd/elf32-mips.c +++ b/bfd/elf32-mips.c @@ -80,6 +80,10 @@ static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup PARAMS ((bfd *, bfd_reloc_code_real_type)); static void mips_info_to_howto_rel PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *)); +static void bfd_mips_elf32_swap_gptab_in + PARAMS ((bfd *, const Elf32_External_gptab *, Elf32_gptab *)); +static void bfd_mips_elf32_swap_gptab_out + PARAMS ((bfd *, const Elf32_gptab *, Elf32_External_gptab *)); static boolean mips_elf_sym_is_global PARAMS ((bfd *, asymbol *)); static boolean mips_elf_object_p PARAMS ((bfd *)); static boolean mips_elf_create_procedure_table @@ -89,6 +93,9 @@ static int mips_elf_additional_program_headers PARAMS ((bfd *)); static boolean mips_elf_modify_segment_map PARAMS ((bfd *)); static void mips_elf_final_write_processing PARAMS ((bfd *, boolean)); +static boolean mips_elf_set_private_flags PARAMS ((bfd *, flagword)); +static boolean mips_elf_copy_private_bfd_data PARAMS ((bfd *, bfd *)); +static boolean mips_elf_merge_private_bfd_data PARAMS ((bfd *, bfd *)); static boolean mips_elf_section_from_shdr PARAMS ((bfd *, Elf32_Internal_Shdr *, char *)); static boolean mips_elf_fake_sections @@ -125,11 +132,32 @@ static boolean mips_elf_adjust_dynindx static boolean mips_elf_relocate_section PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, Elf_Internal_Rela *, Elf_Internal_Sym *, asection **)); +static boolean mips_elf_create_dynamic_sections + PARAMS ((bfd *, struct bfd_link_info *)); +static boolean mips_elf_create_compact_rel_section + PARAMS ((bfd *, struct bfd_link_info *)); +static boolean mips_elf_create_got_section + PARAMS ((bfd *, struct bfd_link_info *)); +static boolean mips_elf_check_relocs + PARAMS ((bfd *, struct bfd_link_info *, asection *, + const Elf_Internal_Rela *)); +static boolean mips_elf_adjust_dynamic_symbol + PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *)); +static boolean mips_elf_size_dynamic_sections + PARAMS ((bfd *, struct bfd_link_info *)); +static boolean mips_elf_finish_dynamic_symbol + PARAMS ((bfd *, struct bfd_link_info *, struct elf_link_hash_entry *, + Elf_Internal_Sym *)); +static boolean mips_elf_finish_dynamic_sections + PARAMS ((bfd *, struct bfd_link_info *)); static boolean mips_elf_add_symbol_hook PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Sym *, const char **, flagword *, asection **, bfd_vma *)); static bfd_reloc_status_type mips_elf_final_gp PARAMS ((bfd *, asymbol *, boolean, char **)); +static bfd_byte *elf32_mips_get_relocated_section_contents + PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_order *, + bfd_byte *, boolean, asymbol **)); /* This is true for Irix 5 executables, false for normal MIPS ELF ABI executables. FIXME: At the moment, we default to always generating @@ -289,6 +317,11 @@ typedef struct #define mips_elf_set_cr_dist2to(x,v) ((x).dist2to = (v)) #define mips_elf_set_cr_relvaddr(x,d) ((x).relvaddr = (d)<<2) +static void bfd_elf32_swap_compact_rel_out + PARAMS ((bfd *, const Elf32_compact_rel *, Elf32_External_compact_rel *)); +static void bfd_elf32_swap_crinfo_out + PARAMS ((bfd *, const Elf32_crinfo *, Elf32_External_crinfo *)); + #define USE_REL 1 /* MIPS uses REL relocations instead of RELA */ enum reloc_type @@ -1327,7 +1360,7 @@ bfd_mips_elf32_swap_gptab_out (abfd, in, ex) static void bfd_elf32_swap_compact_rel_out (abfd, in, ex) bfd *abfd; - Elf32_compact_rel *in; + const Elf32_compact_rel *in; Elf32_External_compact_rel *ex; { bfd_h_put_32 (abfd, (bfd_vma) in->id1, ex->id1); @@ -1341,7 +1374,7 @@ bfd_elf32_swap_compact_rel_out (abfd, in, ex) static void bfd_elf32_swap_crinfo_out (abfd, in, ex) bfd *abfd; - Elf32_crinfo *in; + const Elf32_crinfo *in; Elf32_External_crinfo *ex; { unsigned long l; @@ -1968,8 +2001,7 @@ mips_elf_additional_program_headers (abfd) ++ret; } - if (bfd_get_section_by_name (abfd, ".interp") == NULL - && bfd_get_section_by_name (abfd, ".dynamic") != NULL + if (bfd_get_section_by_name (abfd, ".dynamic") != NULL && bfd_get_section_by_name (abfd, ".mdebug") != NULL) { /* We need a PT_MIPS_RTPROC segment. */ @@ -2409,6 +2441,8 @@ struct mips_elf_link_hash_table bfd_size_type dynsym_sec_strindex[SIZEOF_MIPS_DYNSYM_SECNAMES]; /* The number of .rtproc entries. */ bfd_size_type procedure_count; + /* The size of the .compact_rel section (if SGI_COMPAT). */ + bfd_size_type compact_rel_size; }; /* Look up an entry in a MIPS ELF linker hash table. */ @@ -2494,6 +2528,7 @@ mips_elf_link_hash_table_create (abfd) for (i = 0; i < SIZEOF_MIPS_DYNSYM_SECNAMES; i++) ret->dynsym_sec_strindex[i] = (bfd_size_type) -1; ret->procedure_count = 0; + ret->compact_rel_size = 0; return &ret->root.root; } @@ -2512,6 +2547,15 @@ mips_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp) asection **secp; bfd_vma *valp; { + if (SGI_COMPAT (abfd) + && (abfd->flags & DYNAMIC) != 0 + && strcmp (*namep, "_rld_new_interface") == 0) + { + /* Skip Irix 5 rld entry name. */ + *namep = NULL; + return true; + } + switch (sym->st_shndx) { case SHN_COMMON: @@ -2549,6 +2593,8 @@ mips_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp) *secp = mips_elf_text_section_ptr; break; + case SHN_MIPS_ACOMMON: + /* Fall through. XXX Can we treat this as allocated data? */ case SHN_MIPS_DATA: /* This section is used in a shared object. */ if (mips_elf_data_section_ptr == NULL) @@ -3865,7 +3911,7 @@ mips_elf_relocate_section (output_bfd, info, input_bfd, input_section, /* If this is HI16 or GOT16 with an associated LO16, adjust the addend accordingly. Otherwise, just relocate. */ - if ((r_type != R_MIPS_HI16 || r_type == R_MIPS_GOT16) + if ((r_type != R_MIPS_HI16 && r_type != R_MIPS_GOT16) || (rel + 1) >= relend || ELF32_R_TYPE ((rel + 1)->r_info) != R_MIPS_LO16) r = _bfd_relocate_contents (howto, input_bfd, @@ -3953,6 +3999,19 @@ mips_elf_relocate_section (output_bfd, info, input_bfd, input_section, relocation = 0; else if (info->shared && ! info->symbolic) relocation = 0; + else if (strcmp (h->root.root.string, "_DYNAMIC_LINK") == 0) + { + /* If this is a dynamic link, we should have created + a _DYNAMIC_LINK symbol in + mips_elf_create_dynamic_sections. Otherwise, we + should define the symbol with a value of 0. + FIXME: It should probably get into the symbol + table somehow as well. */ + BFD_ASSERT (! info->shared); + BFD_ASSERT (bfd_get_section_by_name (output_bfd, + ".dynamic") == NULL); + relocation = 0; + } else { if (! ((*info->callbacks->undefined_symbol) @@ -4065,7 +4124,10 @@ mips_elf_relocate_section (output_bfd, info, input_bfd, input_section, addend = bfd_get_32 (input_bfd, contents + rel->r_offset); - if (h != NULL) + if (h != NULL + && (! info->symbolic + || (h->elf_link_hash_flags + & ELF_LINK_HASH_DEF_REGULAR) == 0)) { BFD_ASSERT (h->dynindx != -1); outrel.r_info = ELF32_R_INFO (h->dynindx, R_MIPS_REL32); @@ -4075,11 +4137,15 @@ mips_elf_relocate_section (output_bfd, info, input_bfd, input_section, { long indx; - sym = local_syms + r_symndx; - - BFD_ASSERT (ELF_ST_TYPE (sym->st_info) == STT_SECTION); - - sec = local_sections[r_symndx]; + if (h == NULL) + sec = local_sections[r_symndx]; + else + { + BFD_ASSERT (h->root.type == bfd_link_hash_defined + || (h->root.type + == bfd_link_hash_defweak)); + sec = h->root.u.def.section; + } if (sec != NULL && bfd_is_abs_section (sec)) indx = 0; else if (sec == NULL || sec->owner == NULL) @@ -4122,6 +4188,7 @@ mips_elf_relocate_section (output_bfd, info, input_bfd, input_section, mips_elf_set_cr_type (cptrel, CRT_MIPS_REL32); else mips_elf_set_cr_type (cptrel, CRT_MIPS_WORD); + mips_elf_set_cr_dist2to (cptrel, 0); cptrel.konst = addend; cr = (scpt->contents @@ -4163,7 +4230,9 @@ mips_elf_relocate_section (output_bfd, info, input_bfd, input_section, { case R_MIPS_26: mips_elf_set_cr_type (cptrel, CRT_MIPS_JMPAD); - cptrel.konst = addend; + /* XXX How should we set dist2to in this case. */ + mips_elf_set_cr_dist2to (cptrel, 8); + cptrel.konst = addend + relocation; cr = scpt->contents + sizeof (Elf32_External_compact_rel); bfd_elf32_swap_crinfo_out (output_bfd, &cptrel, ((Elf32_External_crinfo *) cr @@ -4176,6 +4245,7 @@ mips_elf_relocate_section (output_bfd, info, input_bfd, input_section, case R_MIPS_GPREL32: mips_elf_set_cr_type (cptrel, CRT_MIPS_GPHI_LO); cptrel.konst = elf_gp (output_bfd) - cptrel.vaddr; + mips_elf_set_cr_dist2to (cptrel, 4); cr = scpt->contents + sizeof (Elf32_External_compact_rel); bfd_elf32_swap_crinfo_out (output_bfd, &cptrel, ((Elf32_External_crinfo *) cr @@ -4233,7 +4303,6 @@ mips_elf_relocate_section (output_bfd, info, input_bfd, input_section, #define ELF_DYNAMIC_INTERPRETER "/usr/lib/libc.so.1" /* Create dynamic sections when linking against a dynamic object. */ -static boolean mips_elf_create_got_section (bfd *, struct bfd_link_info *); static boolean mips_elf_create_dynamic_sections (abfd, info) @@ -4284,24 +4353,13 @@ mips_elf_create_dynamic_sections (abfd, info) h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR; h->type = STT_SECTION; - if (info->shared - && ! bfd_elf32_link_record_dynamic_symbol (info, h)) - return false; - } - - /* Create .compact_rel section. */ - if (bfd_get_section_by_name (abfd, ".compact_rel") == NULL) - { - flags = SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_READONLY; - - s = bfd_make_section (abfd, ".compact_rel"); - if (s == NULL - || ! bfd_set_section_flags (abfd, s, flags) - || ! bfd_set_section_alignment (abfd, s, 2)) + if (! bfd_elf32_link_record_dynamic_symbol (info, h)) return false; } - s->_raw_size = sizeof (Elf32_compact_rel); + /* We need to create a .compact_rel section. */ + if (! mips_elf_create_compact_rel_section (abfd, info)) + return false; /* Change aligments of some sections. */ s = bfd_get_section_by_name (abfd, ".hash"); @@ -4321,9 +4379,51 @@ mips_elf_create_dynamic_sections (abfd, info) bfd_set_section_alignment (abfd, s, 4); } + if (!info->shared) + { + h = NULL; + if (! (_bfd_generic_link_add_one_symbol + (info, abfd, "_DYNAMIC_LINK", BSF_GLOBAL, bfd_abs_section_ptr, + (bfd_vma) 0, (const char *) NULL, false, + get_elf_backend_data (abfd)->collect, + (struct bfd_link_hash_entry **) &h))) + return false; + h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR; + h->type = STT_SECTION; + + if (! bfd_elf32_link_record_dynamic_symbol (info, h)) + return false; + } + return true; } +/* Create the .compact_rel section. */ + +static boolean +mips_elf_create_compact_rel_section (abfd, info) + bfd *abfd; + struct bfd_link_info *info; +{ + flagword flags; + register asection *s; + + if (bfd_get_section_by_name (abfd, ".compact_rel") == NULL) + { + flags = SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_READONLY; + + s = bfd_make_section (abfd, ".compact_rel"); + if (s == NULL + || ! bfd_set_section_flags (abfd, s, flags) + || ! bfd_set_section_alignment (abfd, s, 2)) + return false; + + s->_raw_size = sizeof (Elf32_External_compact_rel); + } + + return true; +} + /* Create the .got section to hold the global offset table. */ static boolean @@ -4350,9 +4450,7 @@ mips_elf_create_got_section (abfd, info) /* Define the symbol _GLOBAL_OFFSET_TABLE_. We don't do this in the linker script because we don't want to define the symbol if we - are not creating a global offset table. XXX Should this be - defined at the start of the .got section, even if .got section is - accessed by using 16 bit signed offset? */ + are not creating a global offset table. */ h = NULL; if (! (_bfd_generic_link_add_one_symbol (info, abfd, "_GLOBAL_OFFSET_TABLE_", BSF_GLOBAL, s, @@ -4407,7 +4505,6 @@ mips_elf_check_relocs (abfd, info, sec, relocs) const Elf_Internal_Rela *rel_end; asection *sgot; asection *sreloc; - asection *scpt; if (info->relocateable) return true; @@ -4419,10 +4516,6 @@ mips_elf_check_relocs (abfd, info, sec, relocs) sgot = NULL; sreloc = NULL; - if (SGI_COMPAT (abfd) && dynobj != NULL) - scpt = bfd_get_section_by_name (dynobj, ".compact_rel"); - else - scpt = NULL; rel_end = relocs + sec->reloc_count; for (rel = relocs; rel < rel_end; rel++) @@ -4577,19 +4670,21 @@ mips_elf_check_relocs (abfd, info, sec, relocs) } sreloc->_raw_size += sizeof (Elf32_External_Rel); - - if (scpt != NULL) - scpt->_raw_size += sizeof (Elf32_External_crinfo); } + if (SGI_COMPAT (abfd)) + mips_elf_hash_table (info)->compact_rel_size += + sizeof (Elf32_External_crinfo); + break; case R_MIPS_26: case R_MIPS_GPREL16: case R_MIPS_LITERAL: case R_MIPS_GPREL32: - if (scpt != NULL) - scpt->_raw_size += sizeof (Elf32_External_crinfo); + if (SGI_COMPAT (abfd)) + mips_elf_hash_table (info)->compact_rel_size += + sizeof (Elf32_External_crinfo); break; default: @@ -4800,9 +4895,10 @@ mips_elf_size_dynamic_sections (output_bfd, info) of .text section. So put a dummy. XXX */ s->_raw_size += MIPS_FUNCTION_STUB_SIZE; } - else if (strncmp (name, ".init", 5) != 0 - && (! SGI_COMPAT (output_bfd) - || strncmp (name, ".compact_rel", 12) != 0)) + else if (SGI_COMPAT (output_bfd) + && strncmp (name, ".compact_rel", 12) == 0) + s->_raw_size += mips_elf_hash_table (info)->compact_rel_size; + else if (strncmp (name, ".init", 5) != 0) { /* It's not one of our sections, so don't allocate space. */ continue; @@ -4872,7 +4968,7 @@ mips_elf_size_dynamic_sections (output_bfd, info) if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_LIBLISTNO, 0)) return false; - if (bfd_get_section_by_name (dynobj, ".conflict")) + if (bfd_get_section_by_name (dynobj, ".conflict") != NULL) { if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_CONFLICT, 0)) return false; @@ -4890,8 +4986,11 @@ mips_elf_size_dynamic_sections (output_bfd, info) if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_FLAGS, 0)) return false; +#if 0 + /* Time stamps in executable files are a bad idea. */ if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_TIME_STAMP, 0)) return false; +#endif #if 0 /* FIXME */ if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_ICHECKSUM, 0)) @@ -4932,74 +5031,76 @@ mips_elf_size_dynamic_sections (output_bfd, info) #endif } - /* If we are generating a shared library, we generate a section - symbol for each output section. These are local symbols, which - means that they must come first in the dynamic symbol table. + /* If we use dynamic linking, we generate a section symbol for each + output section. These are local symbols, which means that they + must come first in the dynamic symbol table. That means we must increment the dynamic symbol index of every other dynamic symbol. */ - if (info->shared) - { - const char * const *namep; - int c, i; - bfd_size_type strindex; - struct bfd_strtab_hash *dynstr; - struct mips_got_info *g; - - if (SGI_COMPAT (output_bfd)) - { - c = SIZEOF_MIPS_DYNSYM_SECNAMES - 1; - elf_link_hash_traverse (elf_hash_table (info), - mips_elf_adjust_dynindx, - (PTR) &c); - elf_hash_table (info)->dynsymcount += c; - - dynstr = elf_hash_table (info)->dynstr; - BFD_ASSERT (dynstr != NULL); - - for (i = 1, namep = mips_elf_dynsym_sec_names; - *namep != NULL; - i++, namep++) - { - s = bfd_get_section_by_name (output_bfd, *namep); - if (s != NULL) - elf_section_data (s)->dynindx = i; + { + const char * const *namep; + unsigned int c, i; + bfd_size_type strindex; + struct bfd_strtab_hash *dynstr; + struct mips_got_info *g; + + if (elf_hash_table (info)->dynamic_sections_created) + { + if (SGI_COMPAT (output_bfd)) + { + c = SIZEOF_MIPS_DYNSYM_SECNAMES - 1; + elf_link_hash_traverse (elf_hash_table (info), + mips_elf_adjust_dynindx, + (PTR) &c); + elf_hash_table (info)->dynsymcount += c; + + dynstr = elf_hash_table (info)->dynstr; + BFD_ASSERT (dynstr != NULL); + + for (i = 1, namep = mips_elf_dynsym_sec_names; + *namep != NULL; + i++, namep++) + { + s = bfd_get_section_by_name (output_bfd, *namep); + if (s != NULL) + elf_section_data (s)->dynindx = i; - strindex = _bfd_stringtab_add (dynstr, *namep, true, false); - if (strindex == (bfd_size_type) -1) - return false; + strindex = _bfd_stringtab_add (dynstr, *namep, true, false); + if (strindex == (bfd_size_type) -1) + return false; - mips_elf_hash_table (info)->dynsym_sec_strindex[i] = strindex; - } - } - else - { - c = bfd_count_sections (output_bfd); - elf_link_hash_traverse (elf_hash_table (info), - mips_elf_adjust_dynindx, - (PTR) &c); - elf_hash_table (info)->dynsymcount += c; + mips_elf_hash_table (info)->dynsym_sec_strindex[i] = strindex; + } + } + else + { + c = bfd_count_sections (output_bfd); + elf_link_hash_traverse (elf_hash_table (info), + mips_elf_adjust_dynindx, + (PTR) &c); + elf_hash_table (info)->dynsymcount += c; - for (i = 1, s = output_bfd->sections; s != NULL; s = s->next, i++) - { - elf_section_data (s)->dynindx = i; - /* These symbols will have no names, so we don't need to - fiddle with dynstr_index. */ - } - } + for (i = 1, s = output_bfd->sections; s != NULL; s = s->next, i++) + { + elf_section_data (s)->dynindx = i; + /* These symbols will have no names, so we don't need to + fiddle with dynstr_index. */ + } + } + } - s = bfd_get_section_by_name (dynobj, ".got"); - BFD_ASSERT (s != NULL); - BFD_ASSERT (elf_section_data (s) != NULL); - g = (struct mips_got_info *) elf_section_data (s)->tdata; - BFD_ASSERT (g != NULL); + s = bfd_get_section_by_name (dynobj, ".got"); + BFD_ASSERT (s != NULL); + BFD_ASSERT (elf_section_data (s) != NULL); + g = (struct mips_got_info *) elf_section_data (s)->tdata; + BFD_ASSERT (g != NULL); - /* If there are no global got symbols, fake the last symbol so for - safety. */ - if (g->global_gotsym) - g->global_gotsym += c; - else - g->global_gotsym = elf_hash_table (info)->dynsymcount - 1; - } + /* If there are no global got symbols, fake the last symbol so for + safety. */ + if (g->global_gotsym) + g->global_gotsym += c; + else + g->global_gotsym = elf_hash_table (info)->dynsymcount - 1; + } return true; } @@ -5012,7 +5113,7 @@ mips_elf_adjust_dynindx (h, cparg) struct elf_link_hash_entry *h; PTR cparg; { - int *cp = (int *) cparg; + unsigned int *cp = (unsigned int *) cparg; if (h->dynindx != -1) h->dynindx += *cp; @@ -5108,8 +5209,13 @@ mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym) if (strcmp (name, "_DYNAMIC") == 0 || strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0) sym->st_shndx = SHN_ABS; - - if (SGI_COMPAT (output_bfd)) + else if (strcmp (name, "_DYNAMIC_LINK") == 0) + { + sym->st_shndx = SHN_ABS; + sym->st_info = ELF_ST_INFO (STB_GLOBAL, STT_SECTION); + sym->st_value = 1; + } + else if (SGI_COMPAT (output_bfd)) { if (strcmp (name, "_gp_disp") == 0) { @@ -5132,8 +5238,7 @@ mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym) sym->st_value = mips_elf_hash_table (info)->procedure_count; sym->st_shndx = SHN_ABS; } - - if (sym->st_shndx != SHN_UNDEF) + else if (sym->st_shndx != SHN_UNDEF) { if (h->type == STT_FUNC) sym->st_shndx = SHN_MIPS_TEXT; @@ -5321,128 +5426,130 @@ mips_elf_finish_dynamic_sections (output_bfd, info) elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4; - if (info->shared) - { - asection *sdynsym; - asection *s; - unsigned int i; - bfd_vma last; - Elf_Internal_Sym sym; - long dindx; - const char *name; - const char * const * namep = mips_elf_dynsym_sec_names; - Elf32_compact_rel cpt; - - /* Set up the section symbols for the output sections. SGI set - STT_NOTYPE attribute for these symbols. Should we do so? */ - - sdynsym = bfd_get_section_by_name (dynobj, ".dynsym"); - BFD_ASSERT (sdynsym != NULL); - - if (SGI_COMPAT (output_bfd)) - { - sym.st_size = 0; - sym.st_name = 0; - sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_NOTYPE); - sym.st_other = 0; - - i = 0; - while ((name = *namep++) != NULL) - { - s = bfd_get_section_by_name (output_bfd, name); - if (s) - { - sym.st_value = s->vma; - dindx = elf_section_data (s)->dynindx; - last = s->vma + s->_raw_size; - } - else - { - sym.st_value = last; - dindx++; - } - - sym.st_shndx = (i < MIPS_TEXT_DYNSYM_SECNO - ? SHN_MIPS_TEXT - : SHN_MIPS_DATA); - ++i; - sym.st_name = - mips_elf_hash_table (info)->dynsym_sec_strindex[dindx]; + { + asection *sdynsym; + asection *s; + unsigned int i; + bfd_vma last; + Elf_Internal_Sym sym; + long dindx; + const char *name; + const char * const * namep = mips_elf_dynsym_sec_names; + Elf32_compact_rel cpt; + + /* Set up the section symbols for the output sections. SGI sets + the STT_NOTYPE attribute for these symbols. Should we do so? */ + + sdynsym = bfd_get_section_by_name (dynobj, ".dynsym"); + if (sdynsym != NULL) + { + if (SGI_COMPAT (output_bfd)) + { + sym.st_size = 0; + sym.st_name = 0; + sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_NOTYPE); + sym.st_other = 0; - bfd_elf32_swap_symbol_out (output_bfd, &sym, - (((Elf32_External_Sym *) - sdynsym->contents) - + dindx)); - } + i = 0; + while ((name = *namep++) != NULL) + { + s = bfd_get_section_by_name (output_bfd, name); + if (s != NULL) + { + sym.st_value = s->vma; + dindx = elf_section_data (s)->dynindx; + last = s->vma + s->_raw_size; + } + else + { + sym.st_value = last; + dindx++; + } - /* Set the sh_info field of the output .dynsym section to - the index of the first global symbol. */ - elf_section_data (sdynsym->output_section)->this_hdr.sh_info = - SIZEOF_MIPS_DYNSYM_SECNAMES; - } - else - { - sym.st_size = 0; - sym.st_name = 0; - sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION); - sym.st_other = 0; + sym.st_shndx = (i < MIPS_TEXT_DYNSYM_SECNO + ? SHN_MIPS_TEXT + : SHN_MIPS_DATA); + ++i; + sym.st_name = + mips_elf_hash_table (info)->dynsym_sec_strindex[dindx]; + + bfd_elf32_swap_symbol_out (output_bfd, &sym, + (((Elf32_External_Sym *) + sdynsym->contents) + + dindx)); + } - for (s = output_bfd->sections; s != NULL; s = s->next) - { - int indx; + /* Set the sh_info field of the output .dynsym section to + the index of the first global symbol. */ + elf_section_data (sdynsym->output_section)->this_hdr.sh_info = + SIZEOF_MIPS_DYNSYM_SECNAMES; + } + else + { + sym.st_size = 0; + sym.st_name = 0; + sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION); + sym.st_other = 0; - sym.st_value = s->vma; + for (s = output_bfd->sections; s != NULL; s = s->next) + { + int indx; - indx = elf_section_data (s)->this_idx; - BFD_ASSERT (indx > 0); - sym.st_shndx = indx; + sym.st_value = s->vma; - bfd_elf32_swap_symbol_out (output_bfd, &sym, - (((Elf32_External_Sym *) - sdynsym->contents) - + elf_section_data (s)->dynindx)); - } + indx = elf_section_data (s)->this_idx; + BFD_ASSERT (indx > 0); + sym.st_shndx = indx; - /* Set the sh_info field of the output .dynsym section to - the index of the first global symbol. */ - elf_section_data (sdynsym->output_section)->this_hdr.sh_info = - bfd_count_sections (output_bfd) + 1; - } + bfd_elf32_swap_symbol_out (output_bfd, &sym, + (((Elf32_External_Sym *) + sdynsym->contents) + + elf_section_data (s)->dynindx)); + } - if (SGI_COMPAT (output_bfd)) - { - /* Write .compact_rel section out. */ - s = bfd_get_section_by_name (dynobj, ".compact_rel"); - BFD_ASSERT (s != NULL); + /* Set the sh_info field of the output .dynsym section to + the index of the first global symbol. */ + elf_section_data (sdynsym->output_section)->this_hdr.sh_info = + bfd_count_sections (output_bfd) + 1; + } + } - cpt.id1 = 1; - cpt.num = s->reloc_count; - cpt.id2 = 2; - cpt.offset = (s->output_section->filepos - + sizeof (Elf32_External_compact_rel)); - cpt.reserved0 = 0; - cpt.reserved1 = 0; - bfd_elf32_swap_compact_rel_out (output_bfd, &cpt, - ((Elf32_External_compact_rel *) - s->contents)); - - /* Clean up a dummy stub function entry in .text. */ - s = bfd_get_section_by_name (dynobj, ".stub"); - if (s != NULL) - { - file_ptr dummy_offset; + if (SGI_COMPAT (output_bfd)) + { + /* Write .compact_rel section out. */ + s = bfd_get_section_by_name (dynobj, ".compact_rel"); + if (s != NULL) + { + cpt.id1 = 1; + cpt.num = s->reloc_count; + cpt.id2 = 2; + cpt.offset = (s->output_section->filepos + + sizeof (Elf32_External_compact_rel)); + cpt.reserved0 = 0; + cpt.reserved1 = 0; + bfd_elf32_swap_compact_rel_out (output_bfd, &cpt, + ((Elf32_External_compact_rel *) + s->contents)); + + /* Clean up a dummy stub function entry in .text. */ + s = bfd_get_section_by_name (dynobj, ".stub"); + if (s != NULL) + { + file_ptr dummy_offset; - BFD_ASSERT (s->_raw_size >= MIPS_FUNCTION_STUB_SIZE); - dummy_offset = s->_raw_size - MIPS_FUNCTION_STUB_SIZE; - memset (s->contents + dummy_offset, 0, MIPS_FUNCTION_STUB_SIZE); - } - } + BFD_ASSERT (s->_raw_size >= MIPS_FUNCTION_STUB_SIZE); + dummy_offset = s->_raw_size - MIPS_FUNCTION_STUB_SIZE; + memset (s->contents + dummy_offset, 0, + MIPS_FUNCTION_STUB_SIZE); + } + } + } - /* Clean up a first relocation in .rel.dyn. */ - s = bfd_get_section_by_name (dynobj, ".rel.dyn"); - if (s) - memset (s->contents, 0, sizeof (Elf32_External_Rel)); - } + /* Clean up a first relocation in .rel.dyn. */ + s = bfd_get_section_by_name (dynobj, ".rel.dyn"); + if (s != NULL) + memset (s->contents, 0, sizeof (Elf32_External_Rel)); + } return true; } @@ -5712,7 +5819,6 @@ static const struct ecoff_debug_swap mips_elf_ecoff_debug_swap = #define bfd_elf32_bfd_merge_private_bfd_data \ mips_elf_merge_private_bfd_data #define bfd_elf32_bfd_set_private_flags mips_elf_set_private_flags -#define elf_backend_relocate_section mips_elf_relocate_section #define elf_backend_add_symbol_hook mips_elf_add_symbol_hook #define elf_backend_create_dynamic_sections \ mips_elf_create_dynamic_sections |