diff options
-rw-r--r-- | bfd/ChangeLog | 42 | ||||
-rw-r--r-- | bfd/elf-bfd.h | 17 | ||||
-rw-r--r-- | bfd/elf32-mips.c | 147 | ||||
-rw-r--r-- | bfd/elf64-mips.c | 298 |
4 files changed, 431 insertions, 73 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 0a1bd29..d0bbf4b 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,5 +1,47 @@ Thu May 30 12:38:49 1996 Ian Lance Taylor <ian@cygnus.com> + * elf64-mips.c: Extensive additions to provide better support for + writing files and for gas. + * elf32-mips.c (_bfd_mips_elf_object_p): New function, broken out + of mips_elf_object_p. + (mips_elf32_object_p): Rename from mips_elf_object_p; call + _bfd_mips_elf_object_p. + (_bfd_mips_elf_final_write_processing): Rename from + mips_elf_final_write_processing and make globally visible. + (_bfd_mips_elf_fake_sections): Rename from + mips_elf_fake_sections and make globally visible. + (_bfd_mips_elf_section_from_bfd_section): Rename from + mips_elf_section_from_bfd_section and make globally visible. + (_bfd_mips_elf_section_processing): New function, broken out of + mips_elf_section_processing. + (mips_elf32_section_processing): Rename from + mips_elf_section_processing; call + _bfd_mips_elf_section_processing. + (_bfd_mips_elf_symbol_processing): Rename from + mips_elf_symbol_processing and make globally visible. + (_bfd_mips_elf_read_ecoff_info): Rename from + mips_elf_read_ecoff_info and make globally visible. + (mips_elf32_ecoff_debug_swap): Rename from + mips_elf_ecoff_debug_swap. + * elf.c (_bfd_elf_symbol_from_bfd_symbol): Use asymbol rather than + struct symbol_cache_entry. + (_bfd_elf_validate_reloc): New function, moved in from + elfcode.h:validate_reloc. + * elfcode.h (validate_reloc): Remove; moved into elf.c and renamed + to _bfd_elf_validate_reloc. Change all callers. + * elf-bfd.h (bfd_section_from_shdr): Declare. + (_bfd_elf_symbol_from_bfd_symbol): Declare. + (_bfd_elf_validate_reloc): Declare. + (_bfd_mips_elf_object_p): Declare. + (_bfd_mips_elf_fake_sections): Declare. + (_bfd_mips_elf_section_from_bfd_section): Declare. + (_bfd_mips_elf_section_processing): Declare. + (_bfd_mips_elf_symbol_processing): Declare. + (_bfd_mips_elf_read_ecoff_info): Declare. + (_bfd_mips_elf_final_write_processing): Declare. + * elfxx-target.h (bfd_elfNN_get_reloc_upper_bound): Don't define + if already defined. + * elf32-mips.c (mips_elf_object_p): Handle E_MIPS_ARCH_4. (mips_elf_final_write_processing): Likewise. diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index 7b9b243..4592386 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -718,6 +718,10 @@ extern boolean _bfd_elf_new_section_hook PARAMS ((bfd *, asection *)); extern void _bfd_elf_no_info_to_howto PARAMS ((bfd *, arelent *, Elf_Internal_Rela *)); +extern boolean bfd_section_from_shdr PARAMS ((bfd *, unsigned int shindex)); + +extern int _bfd_elf_symbol_from_bfd_symbol PARAMS ((bfd *, asymbol **)); + asection *bfd_section_from_elf_index PARAMS ((bfd *, unsigned int)); boolean _bfd_elf_create_dynamic_sections PARAMS ((bfd *, struct bfd_link_info *)); @@ -733,6 +737,8 @@ file_ptr _bfd_elf_assign_file_position_for_section PARAMS ((Elf_Internal_Shdr *, file_ptr, boolean)); +extern boolean _bfd_elf_validate_reloc PARAMS ((bfd *, arelent *)); + boolean _bfd_elf_create_dynamic_sections PARAMS ((bfd *, struct bfd_link_info *)); boolean _bfd_elf_create_got_section PARAMS ((bfd *, @@ -876,7 +882,18 @@ extern boolean bfd_elf64_link_create_dynamic_sections /* MIPS ELF specific routines. */ +extern boolean _bfd_mips_elf_object_p PARAMS ((bfd *)); extern boolean _bfd_mips_elf_section_from_shdr PARAMS ((bfd *, Elf_Internal_Shdr *, const char *)); +extern boolean _bfd_mips_elf_fake_sections + PARAMS ((bfd *, Elf_Internal_Shdr *, asection *)); +extern boolean _bfd_mips_elf_section_from_bfd_section + PARAMS ((bfd *, Elf_Internal_Shdr *, asection *, int *)); +extern boolean _bfd_mips_elf_section_processing + PARAMS ((bfd *, Elf_Internal_Shdr *)); +extern void _bfd_mips_elf_symbol_processing PARAMS ((bfd *, asymbol *)); +extern boolean _bfd_mips_elf_read_ecoff_info + PARAMS ((bfd *, asection *, struct ecoff_debug_info *)); +extern void _bfd_mips_elf_final_write_processing PARAMS ((bfd *, boolean)); #endif /* _LIBELF_H_ */ diff --git a/bfd/elf32-mips.c b/bfd/elf32-mips.c index 6f80f07..2beb720 100644 --- a/bfd/elf32-mips.c +++ b/bfd/elf32-mips.c @@ -85,28 +85,19 @@ static void bfd_mips_elf32_swap_gptab_in 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_elf32_object_p PARAMS ((bfd *)); static boolean mips_elf_create_procedure_table PARAMS ((PTR, bfd *, struct bfd_link_info *, asection *, struct ecoff_debug_info *)); 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_elf32_section_from_shdr PARAMS ((bfd *, Elf32_Internal_Shdr *, char *)); -static boolean mips_elf_fake_sections - PARAMS ((bfd *, Elf32_Internal_Shdr *, asection *)); -static boolean mips_elf_section_from_bfd_section - PARAMS ((bfd *, Elf32_Internal_Shdr *, asection *, int *)); -static boolean mips_elf_section_processing +static boolean mips_elf32_section_processing PARAMS ((bfd *, Elf32_Internal_Shdr *)); -static void mips_elf_symbol_processing PARAMS ((bfd *, asymbol *)); -static boolean mips_elf_read_ecoff_info - PARAMS ((bfd *, asection *, struct ecoff_debug_info *)); static boolean mips_elf_is_local_label PARAMS ((bfd *, asymbol *)); static boolean mips_elf_find_nearest_line @@ -1445,10 +1436,11 @@ mips_elf_sym_is_global (abfd, sym) return (sym->flags & BSF_SECTION_SYM) == 0 ? true : false; } -/* Set the right machine number for a MIPS ELF file. */ +/* Set the right machine number for a MIPS ELF file. This is used for + both the 32-bit and the 64-bit ABI. */ -static boolean -mips_elf_object_p (abfd) +boolean +_bfd_mips_elf_object_p (abfd) bfd *abfd; { switch (elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) @@ -1471,21 +1463,30 @@ mips_elf_object_p (abfd) break; } + return true; +} + +/* Set the right machine number for a 32-bit MIPS ELF file. */ + +static boolean +mips_elf32_object_p (abfd) + bfd *abfd; +{ /* Irix 5 is broken. Object file symbol tables are not always sorted correctly such that local symbols precede global symbols, and the sh_info field in the symbol table is not always right. */ elf_bad_symtab (abfd) = true; - return true; + return _bfd_mips_elf_object_p (abfd); } /* The final processing done just before writing out a MIPS ELF object file. This gets the MIPS architecture right based on the machine - number. */ + number. This is used by both the 32-bit and the 64-bit ABI. */ /*ARGSUSED*/ -static void -mips_elf_final_write_processing (abfd, linker) +void +_bfd_mips_elf_final_write_processing (abfd, linker) bfd *abfd; boolean linker; { @@ -1767,10 +1768,11 @@ mips_elf32_section_from_shdr (abfd, hdr, name) } /* Set the correct type for a MIPS ELF section. We do this by the - section name, which is a hack, but ought to work. */ + section name, which is a hack, but ought to work. This routine is + used by both the 32-bit and the 64-bit ABI. */ -static boolean -mips_elf_fake_sections (abfd, hdr, sec) +boolean +_bfd_mips_elf_fake_sections (abfd, hdr, sec) bfd *abfd; Elf32_Internal_Shdr *hdr; asection *sec; @@ -1797,7 +1799,7 @@ mips_elf_fake_sections (abfd, hdr, sec) { hdr->sh_type = SHT_MIPS_GPTAB; hdr->sh_entsize = sizeof (Elf32_External_gptab); - /* The sh_info field is set in mips_elf_final_write_processing. */ + /* The sh_info field is set in final_write_processing. */ } else if (strcmp (name, ".ucode") == 0) hdr->sh_type = SHT_MIPS_UCODE; @@ -1854,10 +1856,13 @@ mips_elf_fake_sections (abfd, hdr, sec) } /* Given a BFD section, try to locate the corresponding ELF section - index. */ + index. This is used by both the 32-bit and the 64-bit ABI. + Actually, it's not clear to me that the 64-bit ABI supports these, + but for non-PIC objects we will certainly want support for at least + the .scommon section. */ -static boolean -mips_elf_section_from_bfd_section (abfd, hdr, sec, retval) +boolean +_bfd_mips_elf_section_from_bfd_section (abfd, hdr, sec, retval) bfd *abfd; Elf32_Internal_Shdr *hdr; asection *sec; @@ -1878,30 +1883,15 @@ mips_elf_section_from_bfd_section (abfd, hdr, sec, retval) /* Work over a section just before writing it out. We update the GP value in the .reginfo section based on the value we are using. - FIXME: We recognize sections that need the SHF_MIPS_GPREL flag by - name; there has to be a better way. */ + This routine is used by both the 32-bit and the 64-bit ABI. FIXME: + We recognize sections that need the SHF_MIPS_GPREL flag by name; + there has to be a better way. */ -static boolean -mips_elf_section_processing (abfd, hdr) +boolean +_bfd_mips_elf_section_processing (abfd, hdr) bfd *abfd; - Elf32_Internal_Shdr *hdr; + Elf_Internal_Shdr *hdr; { - if (hdr->sh_type == SHT_MIPS_REGINFO) - { - bfd_byte buf[4]; - - BFD_ASSERT (hdr->sh_size == sizeof (Elf32_External_RegInfo)); - BFD_ASSERT (hdr->contents == NULL); - - if (bfd_seek (abfd, - hdr->sh_offset + sizeof (Elf32_External_RegInfo) - 4, - SEEK_SET) == -1) - return false; - bfd_h_put_32 (abfd, (bfd_vma) elf_gp (abfd), buf); - if (bfd_write (buf, (bfd_size_type) 1, (bfd_size_type) 4, abfd) != 4) - return false; - } - if (hdr->bfd_section != NULL) { const char *name = bfd_get_section_name (abfd, hdr->bfd_section); @@ -1942,6 +1932,34 @@ mips_elf_section_processing (abfd, hdr) return true; } + +/* Work over a section just before writing it out. We update the GP + value in the .reginfo section based on the value we are using. The + 64 bit ABI does not use the .reginfo section. */ + +static boolean +mips_elf32_section_processing (abfd, hdr) + bfd *abfd; + Elf32_Internal_Shdr *hdr; +{ + if (hdr->sh_type == SHT_MIPS_REGINFO) + { + bfd_byte buf[4]; + + BFD_ASSERT (hdr->sh_size == sizeof (Elf32_External_RegInfo)); + BFD_ASSERT (hdr->contents == NULL); + + if (bfd_seek (abfd, + hdr->sh_offset + sizeof (Elf32_External_RegInfo) - 4, + SEEK_SET) == -1) + return false; + bfd_h_put_32 (abfd, (bfd_vma) elf_gp (abfd), buf); + if (bfd_write (buf, (bfd_size_type) 1, (bfd_size_type) 4, abfd) != 4) + return false; + } + + return _bfd_mips_elf_section_processing (abfd, hdr); +} /* MIPS ELF uses two common sections. One is the usual one, and the other is for small objects. All the small objects are kept @@ -1971,10 +1989,11 @@ static asection *mips_elf_data_section_ptr; static asymbol mips_elf_data_symbol; static asymbol *mips_elf_data_symbol_ptr; -/* Handle the special MIPS section numbers that a symbol may use. */ +/* Handle the special MIPS section numbers that a symbol may use. + This is used for both the 32-bit and the 64-bit ABI. */ -static void -mips_elf_symbol_processing (abfd, asym) +void +_bfd_mips_elf_symbol_processing (abfd, asym) bfd *abfd; asymbol *asym; { @@ -2282,8 +2301,8 @@ ecoff_swap_rpdr_out (abfd, in, ex) /* Read ECOFF debugging information from a .mdebug section into a ecoff_debug_info structure. */ -static boolean -mips_elf_read_ecoff_info (abfd, section, debug) +boolean +_bfd_mips_elf_read_ecoff_info (abfd, section, debug) bfd *abfd; asection *section; struct ecoff_debug_info *debug; @@ -2433,7 +2452,7 @@ mips_elf_find_nearest_line (abfd, section, symbols, offset, filename_ptr, return false; } - if (! mips_elf_read_ecoff_info (abfd, msec, &fi->d)) + if (! _bfd_mips_elf_read_ecoff_info (abfd, msec, &fi->d)) { msec->flags = origflags; return false; @@ -3176,7 +3195,7 @@ mips_elf_final_link (abfd, info) reginfo.ri_cprmask[3] |= sub.ri_cprmask[3]; /* ri_gp_value is set by the function - mips_elf_section_processing when the section is + mips_elf32_section_processing when the section is finally written out. */ /* Hack: reset the SEC_HAS_CONTENTS flag so that @@ -3313,8 +3332,8 @@ mips_elf_final_link (abfd, info) /* The ECOFF linking code expects that we have already read in the debugging information and set up an ecoff_debug_info structure, so we do that now. */ - if (! mips_elf_read_ecoff_info (input_bfd, input_section, - &input_debug)) + if (! _bfd_mips_elf_read_ecoff_info (input_bfd, input_section, + &input_debug)) return false; if (! (bfd_ecoff_debug_accumulate @@ -5893,7 +5912,7 @@ error_return: /* ECOFF swapping routines. These are used when dealing with the .mdebug section, which is in the ECOFF debugging format. */ -static const struct ecoff_debug_swap mips_elf_ecoff_debug_swap = +static const struct ecoff_debug_swap mips_elf32_ecoff_debug_swap = { /* Symbol table magic number. */ magicSym, @@ -5931,7 +5950,7 @@ static const struct ecoff_debug_swap mips_elf_ecoff_debug_swap = _bfd_ecoff_swap_tir_out, _bfd_ecoff_swap_rndx_out, /* Function to read in symbolic data. */ - mips_elf_read_ecoff_info + _bfd_mips_elf_read_ecoff_info }; #define TARGET_LITTLE_SYM bfd_elf32_littlemips_vec @@ -5946,19 +5965,19 @@ static const struct ecoff_debug_swap mips_elf_ecoff_debug_swap = #define elf_info_to_howto 0 #define elf_info_to_howto_rel mips_info_to_howto_rel #define elf_backend_sym_is_global mips_elf_sym_is_global -#define elf_backend_object_p mips_elf_object_p +#define elf_backend_object_p mips_elf32_object_p #define elf_backend_section_from_shdr mips_elf32_section_from_shdr -#define elf_backend_fake_sections mips_elf_fake_sections +#define elf_backend_fake_sections _bfd_mips_elf_fake_sections #define elf_backend_section_from_bfd_section \ - mips_elf_section_from_bfd_section -#define elf_backend_section_processing mips_elf_section_processing -#define elf_backend_symbol_processing mips_elf_symbol_processing + _bfd_mips_elf_section_from_bfd_section +#define elf_backend_section_processing mips_elf32_section_processing +#define elf_backend_symbol_processing _bfd_mips_elf_symbol_processing #define elf_backend_additional_program_headers \ mips_elf_additional_program_headers #define elf_backend_modify_segment_map mips_elf_modify_segment_map #define elf_backend_final_write_processing \ - mips_elf_final_write_processing -#define elf_backend_ecoff_debug_swap &mips_elf_ecoff_debug_swap + _bfd_mips_elf_final_write_processing +#define elf_backend_ecoff_debug_swap &mips_elf32_ecoff_debug_swap #define bfd_elf32_bfd_is_local_label mips_elf_is_local_label #define bfd_elf32_find_nearest_line mips_elf_find_nearest_line diff --git a/bfd/elf64-mips.c b/bfd/elf64-mips.c index ae444aa..2f89b48 100644 --- a/bfd/elf64-mips.c +++ b/bfd/elf64-mips.c @@ -18,6 +18,12 @@ 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. */ +/* This file supports the 64-bit MIPS ELF ABI. + + The MIPS 64-bit ELF ABI uses an unusual reloc format. This file + overrides the usual ELF reloc handling, and handles reading and + writing the relocations here. */ + #include "bfd.h" #include "sysdep.h" #include "libbfd.h" @@ -26,11 +32,16 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "elf-bfd.h" #include "elf/mips.h" -/* This file supports the 64-bit MIPS ELF ABI. - - The MIPS 64-bit ELF ABI uses an unusual reloc format. This file - overrides the usual ELF reloc handling, and handles reading and - writing the relocations here. */ +/* Get the ECOFF swapping routines. The 64-bit ABI is not supposed to + use ECOFF. However, we support it anyhow for an easier changeover. */ +#include "coff/sym.h" +#include "coff/symconst.h" +#include "coff/internal.h" +#include "coff/ecoff.h" +/* The 64 bit versions of the mdebug data structures are in alpha.h. */ +#include "coff/alpha.h" +#define ECOFF_64 +#include "ecoffswap.h" static void mips_elf64_swap_reloc_in PARAMS ((bfd *, const Elf64_Mips_External_Rel *, @@ -38,14 +49,17 @@ static void mips_elf64_swap_reloc_in static void mips_elf64_swap_reloca_in PARAMS ((bfd *, const Elf64_Mips_External_Rela *, Elf64_Mips_Internal_Rela *)); +#if 0 static void mips_elf64_swap_reloc_out PARAMS ((bfd *, const Elf64_Mips_Internal_Rel *, Elf64_Mips_External_Rel *)); +#endif static void mips_elf64_swap_reloca_out PARAMS ((bfd *, const Elf64_Mips_Internal_Rela *, Elf64_Mips_External_Rela *)); static reloc_howto_type *mips_elf64_reloc_type_lookup PARAMS ((bfd *, bfd_reloc_code_real_type)); +static long mips_elf64_get_reloc_upper_bound PARAMS ((bfd *, asection *)); static boolean mips_elf64_slurp_one_reloc_table PARAMS ((bfd *, asection *, asymbol **, const Elf_Internal_Shdr *)); static boolean mips_elf64_slurp_reloc_table @@ -94,7 +108,9 @@ enum mips_elf64_reloc_type R_MIPS_CALL_LO16 = 31, R_MIPS_SCN_DISP = 32, R_MIPS_REL16 = 33, - R_MIPS_ADD_IMMEDIATE = 34 + R_MIPS_ADD_IMMEDIATE = 34, + R_MIPS_PJUMP = 35, + R_MIPS_RELGOT = 36 }; /* In case we're on a 32-bit machine, construct a 64-bit "-1" value @@ -615,6 +631,34 @@ static reloc_howto_type mips_elf64_howto_table_rel[] = false, /* partial_inplace */ 0, /* src_mask */ 0, /* dst_mask */ + false), /* pcrel_offset */ + + HOWTO (R_MIPS_PJUMP, /* type */ + 0, /* rightshift */ + 0, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_MIPS_PJUMP", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + false), /* pcrel_offset */ + + HOWTO (R_MIPS_RELGOT, /* type */ + 0, /* rightshift */ + 0, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_MIPS_RELGOT", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ false) /* pcrel_offset */ }; @@ -1124,6 +1168,34 @@ static reloc_howto_type mips_elf64_howto_table_rela[] = false, /* partial_inplace */ 0, /* src_mask */ 0, /* dst_mask */ + false), /* pcrel_offset */ + + HOWTO (R_MIPS_PJUMP, /* type */ + 0, /* rightshift */ + 0, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_MIPS_PJUMP", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + false), /* pcrel_offset */ + + HOWTO (R_MIPS_RELGOT, /* type */ + 0, /* rightshift */ + 0, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_MIPS_RELGOT", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ false) /* pcrel_offset */ }; @@ -1160,6 +1232,10 @@ mips_elf64_swap_reloca_in (abfd, src, dst) dst->r_addend = bfd_h_get_64 (abfd, (bfd_byte *) src->r_addend); } +#if 0 + +/* This is not currently used. */ + /* Swap out a MIPS 64-bit Rel reloc. */ static void @@ -1176,6 +1252,8 @@ mips_elf64_swap_reloc_out (abfd, src, dst) bfd_h_put_8 (abfd, src->r_type, (bfd_byte *) dst->r_type); } +#endif /* 0 */ + /* Swap out a MIPS 64-bit Rela reloc. */ static void @@ -1247,6 +1325,17 @@ mips_elf64_reloc_type_lookup (abfd, code) return NULL; } +/* Since each entry in an SHT_REL or SHT_RELA section can represent up + to three relocs, we must tell the user to allocate more space. */ + +static long +mips_elf64_get_reloc_upper_bound (abfd, sec) + bfd *abfd; + asection *sec; +{ + return (sec->reloc_count * 3 + 1) * sizeof (arelent *); +} + /* Read the relocations from one reloc section. */ static boolean @@ -1495,8 +1584,145 @@ mips_elf64_write_relocs (abfd, sec, data) asection *sec; PTR data; { - /* FIXME. */ - abort (); + boolean *failedp = (boolean *) data; + unsigned int count; + Elf_Internal_Shdr *rela_hdr; + Elf64_Mips_External_Rela *ext_rela; + unsigned int idx; + asymbol *last_sym = 0; + int last_sym_idx = 0; + + /* If we have already failed, don't do anything. */ + if (*failedp) + return; + + if ((sec->flags & SEC_RELOC) == 0) + return; + + /* The linker backend writes the relocs out itself, and sets the + reloc_count field to zero to inhibit writing them here. Also, + sometimes the SEC_RELOC flag gets set even when there aren't any + relocs. */ + if (sec->reloc_count == 0) + return; + + /* We can combine up to three relocs that refer to the same address + if the latter relocs have no associated symbol. */ + count = 0; + for (idx = 0; idx < sec->reloc_count; idx++) + { + bfd_vma addr; + unsigned int i; + + ++count; + + addr = sec->orelocation[idx]->address; + for (i = 0; i < 2; i++) + { + arelent *r; + + if (idx + 1 >= sec->reloc_count) + break; + r = sec->orelocation[idx + 1]; + if (r->address != addr + || ! bfd_is_abs_section ((*r->sym_ptr_ptr)->section) + || (*r->sym_ptr_ptr)->value != 0) + break; + + /* We can merge the reloc at IDX + 1 with the reloc at IDX. */ + + ++idx; + } + } + + rela_hdr = &elf_section_data (sec)->rel_hdr; + + rela_hdr->sh_size = rela_hdr->sh_entsize * count; + rela_hdr->contents = (PTR) bfd_alloc (abfd, rela_hdr->sh_size); + if (rela_hdr->contents == NULL) + { + *failedp = true; + return; + } + + ext_rela = (Elf64_Mips_External_Rela *) rela_hdr->contents; + for (idx = 0; idx < sec->reloc_count; idx++, ext_rela++) + { + arelent *ptr; + Elf64_Mips_Internal_Rela int_rela; + asymbol *sym; + int n; + unsigned int i; + + ptr = sec->orelocation[idx]; + + /* The address of an ELF reloc is section relative for an object + file, and absolute for an executable file or shared library. + The address of a BFD reloc is always section relative. */ + if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0) + int_rela.r_offset = ptr->address; + else + int_rela.r_offset = ptr->address + sec->vma; + + sym = *ptr->sym_ptr_ptr; + if (sym == last_sym) + n = last_sym_idx; + else + { + last_sym = sym; + n = _bfd_elf_symbol_from_bfd_symbol (abfd, &sym); + if (n < 0) + { + *failedp = true; + return; + } + last_sym_idx = n; + } + + int_rela.r_sym = n; + + int_rela.r_addend = ptr->addend; + + int_rela.r_ssym = RSS_UNDEF; + + if ((*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec + && ! _bfd_elf_validate_reloc (abfd, ptr)) + { + *failedp = true; + return; + } + + int_rela.r_type = ptr->howto->type; + int_rela.r_type2 = (int) R_MIPS_NONE; + int_rela.r_type3 = (int) R_MIPS_NONE; + + for (i = 0; i < 2; i++) + { + arelent *r; + + if (idx + 1 >= sec->reloc_count) + break; + r = sec->orelocation[idx + 1]; + if (r->address != ptr->address + || ! bfd_is_abs_section ((*r->sym_ptr_ptr)->section) + || (*r->sym_ptr_ptr)->value != 0) + break; + + /* We can merge the reloc at IDX + 1 with the reloc at IDX. */ + + if (i == 0) + int_rela.r_type2 = r->howto->type; + else + int_rela.r_type3 = r->howto->type; + + ++idx; + } + + mips_elf64_swap_reloca_out (abfd, &int_rela, ext_rela); + } + + BFD_ASSERT (ext_rela - (Elf64_Mips_External_Rela *) rela_hdr->contents + == count); } /* Handle a 64-bit MIPS ELF specific section. */ @@ -1512,7 +1738,50 @@ mips_elf64_section_from_shdr (abfd, hdr, name) return true; } - + +/* ECOFF swapping routines. These are used when dealing with the + .mdebug section, which is in the ECOFF debugging format. */ +static const struct ecoff_debug_swap mips_elf64_ecoff_debug_swap = +{ + /* Symbol table magic number. */ + magicSym2, + /* Alignment of debugging information. E.g., 4. */ + 8, + /* Sizes of external symbolic information. */ + sizeof (struct hdr_ext), + sizeof (struct dnr_ext), + sizeof (struct pdr_ext), + sizeof (struct sym_ext), + sizeof (struct opt_ext), + sizeof (struct fdr_ext), + sizeof (struct rfd_ext), + sizeof (struct ext_ext), + /* Functions to swap in external symbolic data. */ + ecoff_swap_hdr_in, + ecoff_swap_dnr_in, + ecoff_swap_pdr_in, + ecoff_swap_sym_in, + ecoff_swap_opt_in, + ecoff_swap_fdr_in, + ecoff_swap_rfd_in, + ecoff_swap_ext_in, + _bfd_ecoff_swap_tir_in, + _bfd_ecoff_swap_rndx_in, + /* Functions to swap out external symbolic data. */ + ecoff_swap_hdr_out, + ecoff_swap_dnr_out, + ecoff_swap_pdr_out, + ecoff_swap_sym_out, + ecoff_swap_opt_out, + ecoff_swap_fdr_out, + ecoff_swap_rfd_out, + ecoff_swap_ext_out, + _bfd_ecoff_swap_tir_out, + _bfd_ecoff_swap_rndx_out, + /* Function to read in symbolic data. */ + _bfd_mips_elf_read_ecoff_info +}; + /* Relocations in the 64 bit MIPS ELF ABI are more complex than in standard ELF. This structure is used to redirect the relocation handling routines. */ @@ -1548,7 +1817,18 @@ const struct elf_size_info mips_elf64_size_info = #define ELF_MACHINE_CODE EM_MIPS #define ELF_MAXPAGESIZE 0x1000 #define elf_backend_size_info mips_elf64_size_info +#define elf_backend_object_p _bfd_mips_elf_object_p #define elf_backend_section_from_shdr mips_elf64_section_from_shdr +#define elf_backend_fake_sections _bfd_mips_elf_fake_sections +#define elf_backend_section_from_bfd_section \ + _bfd_mips_elf_section_from_bfd_section +#define elf_backend_section_processing _bfd_mips_elf_section_processing +#define elf_backend_symbol_processing _bfd_mips_elf_symbol_processing +#define elf_backend_final_write_processing \ + _bfd_mips_elf_final_write_processing +#define elf_backend_ecoff_debug_swap &mips_elf64_ecoff_debug_swap + +#define bfd_elf64_get_reloc_upper_bound mips_elf64_get_reloc_upper_bound #define bfd_elf64_bfd_reloc_type_lookup mips_elf64_reloc_type_lookup #include "elf64-target.h" |