* 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.
This commit is contained in:
Ian Lance Taylor 1996-05-30 22:33:51 +00:00
parent d0e1c80348
commit 0017655509
4 changed files with 431 additions and 73 deletions

View file

@ -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.

View file

@ -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_ */

View file

@ -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

View file

@ -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"