* elf64-mips.c: Improve reloc special_functions and handling of

SHT_MIPS_OPTIONS section.
	* elf32-mips.c (_bfd_mips_elf_hi16_reloc): Rename from
	mips_elf_hi16_reloc and make globally visible.
	(_bfd_mips_elf_lo16_reloc): Rename from mips_elf_lo16_reloc and
	make globally visible.
	(_bfd_mips_elf_got16_reloc): Rename from mips_elf_got16_reloc and
	make globally visible.
	(_bfd_mips_elf_gprel16_reloc): Rename from mips_elf_gprel16_reloc
	and make globally visible.
	(gprel16_with_gp): Check howto->src_mask before using value in
	insn.
	(_bfd_mips_elf_gprel32_reloc): Rename from mips_elf_gprel32_reloc
	and make globally visible.
	(gprel32_with_gp): Check howto->src_mask before fetching value.
	(bfd_mips_elf_swap_options_in): New function.
	(bfd_mips_elf_swap_options_out): New function.
	(_bfd_mips_elf_set_private_flags): Rename from
	mips_elf_set_private_flags and make globally visible.
	(_bfd_mips_elf_copy_private_bfd_data): Rename from
	mips_elf_copy_private_bfd_data and make globally visible.
	(_bfd_mips_elf_merge_private_bfd_data): Rename from
	mips_elf_merge_private_bfd_data and make globally visible.
	(_bfd_mips_elf_section_from_shdr): Accept .MIPS.options as a name
	for a SHT_MIPS_OPTIONS section.
	(mips_elf32_section_from_shdr): Handle SHT_MIPS_OPTIONS section.
	(_bfd_mips_elf_fake_sections): Consider .MIPS.options to be the
	name of a SHT_MIPS_OPTIONS section.
	(_bfd_mips_elf_set_section_contents): New function.
	(mips_elf32_section_processing): Set the GP value in a
	SHT_MIPS_OPTIONS section.
	(_bfd_mips_elf_find_nearest_line): Rename from
	mips_elf_find_nearest_line and make globally visible.
	(bfd_elf32_set_section_contents): Define.
	* elf-bfd.h (_bfd_mips_elf_hi16_reloc): Declare.
	(_bfd_mips_elf_lo16_reloc): Declare.
	(_bfd_mips_elf_gprel16_reloc): Declare.
	(_bfd_mips_elf_got16_reloc): Declare.
	(_bfd_mips_elf_gprel32_reloc): Declare.
	(_bfd_mips_elf_set_private_flags): Declare.
	(_bfd_mips_elf_copy_private_bfd_data): Declare.
	(_bfd_mips_elf_merge_private_bfd_data): Declare.
	(_bfd_mips_elf_find_nearest_line): Declare.
	(_bfd_mips_elf_set_section_contents): Declare.
This commit is contained in:
Ian Lance Taylor 1996-05-31 21:43:35 +00:00
parent 38893c8cb8
commit bc05732be6
3 changed files with 421 additions and 112 deletions

View File

@ -1,5 +1,50 @@
Fri May 31 13:51:28 1996 Ian Lance Taylor <ian@cygnus.com>
* elf64-mips.c: Improve reloc special_functions and handling of
SHT_MIPS_OPTIONS section.
* elf32-mips.c (_bfd_mips_elf_hi16_reloc): Rename from
mips_elf_hi16_reloc and make globally visible.
(_bfd_mips_elf_lo16_reloc): Rename from mips_elf_lo16_reloc and
make globally visible.
(_bfd_mips_elf_got16_reloc): Rename from mips_elf_got16_reloc and
make globally visible.
(_bfd_mips_elf_gprel16_reloc): Rename from mips_elf_gprel16_reloc
and make globally visible.
(gprel16_with_gp): Check howto->src_mask before using value in
insn.
(_bfd_mips_elf_gprel32_reloc): Rename from mips_elf_gprel32_reloc
and make globally visible.
(gprel32_with_gp): Check howto->src_mask before fetching value.
(bfd_mips_elf_swap_options_in): New function.
(bfd_mips_elf_swap_options_out): New function.
(_bfd_mips_elf_set_private_flags): Rename from
mips_elf_set_private_flags and make globally visible.
(_bfd_mips_elf_copy_private_bfd_data): Rename from
mips_elf_copy_private_bfd_data and make globally visible.
(_bfd_mips_elf_merge_private_bfd_data): Rename from
mips_elf_merge_private_bfd_data and make globally visible.
(_bfd_mips_elf_section_from_shdr): Accept .MIPS.options as a name
for a SHT_MIPS_OPTIONS section.
(mips_elf32_section_from_shdr): Handle SHT_MIPS_OPTIONS section.
(_bfd_mips_elf_fake_sections): Consider .MIPS.options to be the
name of a SHT_MIPS_OPTIONS section.
(_bfd_mips_elf_set_section_contents): New function.
(mips_elf32_section_processing): Set the GP value in a
SHT_MIPS_OPTIONS section.
(_bfd_mips_elf_find_nearest_line): Rename from
mips_elf_find_nearest_line and make globally visible.
(bfd_elf32_set_section_contents): Define.
* elf-bfd.h (_bfd_mips_elf_hi16_reloc): Declare.
(_bfd_mips_elf_lo16_reloc): Declare.
(_bfd_mips_elf_gprel16_reloc): Declare.
(_bfd_mips_elf_got16_reloc): Declare.
(_bfd_mips_elf_gprel32_reloc): Declare.
(_bfd_mips_elf_set_private_flags): Declare.
(_bfd_mips_elf_copy_private_bfd_data): Declare.
(_bfd_mips_elf_merge_private_bfd_data): Declare.
(_bfd_mips_elf_find_nearest_line): Declare.
(_bfd_mips_elf_set_section_contents): Declare.
* elf32-hppa.c (elf32_hppa_info_to_howto): Rename from
elf_info_to_howto.
(elf_info_to_howto): Define.

View File

@ -41,41 +41,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#define ECOFF_32
#include "ecoffswap.h"
static bfd_reloc_status_type mips_elf_hi16_reloc PARAMS ((bfd *abfd,
arelent *reloc,
asymbol *symbol,
PTR data,
asection *section,
bfd *output_bfd,
char **error));
static bfd_reloc_status_type mips_elf_got16_reloc PARAMS ((bfd *abfd,
arelent *reloc,
asymbol *symbol,
PTR data,
asection *section,
bfd *output_bfd,
char **error));
static bfd_reloc_status_type mips_elf_lo16_reloc PARAMS ((bfd *abfd,
arelent *reloc,
asymbol *symbol,
PTR data,
asection *section,
bfd *output_bfd,
char **error));
static bfd_reloc_status_type mips_elf_gprel16_reloc PARAMS ((bfd *abfd,
arelent *reloc,
asymbol *symbol,
PTR data,
asection *section,
bfd *output_bfd,
char **error));
static bfd_reloc_status_type mips_elf_gprel32_reloc PARAMS ((bfd *abfd,
arelent *reloc,
asymbol *symbol,
PTR data,
asection *section,
bfd *output_bfd,
char **error));
static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
PARAMS ((bfd *, bfd_reloc_code_real_type));
static void mips_info_to_howto_rel
@ -91,18 +56,12 @@ static boolean mips_elf_create_procedure_table
struct ecoff_debug_info *));
static int mips_elf_additional_program_headers PARAMS ((bfd *));
static boolean mips_elf_modify_segment_map PARAMS ((bfd *));
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_elf32_section_processing
PARAMS ((bfd *, Elf32_Internal_Shdr *));
static boolean mips_elf_is_local_label
PARAMS ((bfd *, asymbol *));
static boolean mips_elf_find_nearest_line
PARAMS ((bfd *, asection *, asymbol **, bfd_vma, const char **,
const char **, unsigned int *));
static struct bfd_hash_entry *mips_elf_link_hash_newfunc
PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
static struct bfd_link_hash_table *mips_elf_link_hash_table_create
@ -427,7 +386,7 @@ static reloc_howto_type elf_mips_howto_table[] =
false, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
mips_elf_hi16_reloc, /* special_function */
_bfd_mips_elf_hi16_reloc, /* special_function */
"R_MIPS_HI16", /* name */
true, /* partial_inplace */
0xffff, /* src_mask */
@ -442,7 +401,7 @@ static reloc_howto_type elf_mips_howto_table[] =
false, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
mips_elf_lo16_reloc, /* special_function */
_bfd_mips_elf_lo16_reloc, /* special_function */
"R_MIPS_LO16", /* name */
true, /* partial_inplace */
0xffff, /* src_mask */
@ -457,7 +416,7 @@ static reloc_howto_type elf_mips_howto_table[] =
false, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
mips_elf_gprel16_reloc, /* special_function */
_bfd_mips_elf_gprel16_reloc, /* special_function */
"R_MIPS_GPREL16", /* name */
true, /* partial_inplace */
0xffff, /* src_mask */
@ -472,7 +431,7 @@ static reloc_howto_type elf_mips_howto_table[] =
false, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
mips_elf_gprel16_reloc, /* special_function */
_bfd_mips_elf_gprel16_reloc, /* special_function */
"R_MIPS_LITERAL", /* name */
true, /* partial_inplace */
0xffff, /* src_mask */
@ -487,7 +446,7 @@ static reloc_howto_type elf_mips_howto_table[] =
false, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
mips_elf_got16_reloc, /* special_function */
_bfd_mips_elf_got16_reloc, /* special_function */
"R_MIPS_GOT16", /* name */
false, /* partial_inplace */
0, /* src_mask */
@ -533,7 +492,7 @@ static reloc_howto_type elf_mips_howto_table[] =
false, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
mips_elf_gprel32_reloc, /* special_function */
_bfd_mips_elf_gprel32_reloc, /* special_function */
"R_MIPS_GPREL32", /* name */
true, /* partial_inplace */
0xffffffff, /* src_mask */
@ -727,8 +686,8 @@ struct mips_hi16
static struct mips_hi16 *mips_hi16_list;
static bfd_reloc_status_type
mips_elf_hi16_reloc (abfd,
bfd_reloc_status_type
_bfd_mips_elf_hi16_reloc (abfd,
reloc_entry,
symbol,
data,
@ -820,8 +779,8 @@ mips_elf_hi16_reloc (abfd,
inplace relocation; this function exists in order to do the
R_MIPS_HI16 relocation described above. */
static bfd_reloc_status_type
mips_elf_lo16_reloc (abfd,
bfd_reloc_status_type
_bfd_mips_elf_lo16_reloc (abfd,
reloc_entry,
symbol,
data,
@ -930,8 +889,8 @@ mips_elf_lo16_reloc (abfd,
This implementation suffices for the assembler, but the linker does
not yet know how to create global offset tables. */
static bfd_reloc_status_type
mips_elf_got16_reloc (abfd,
bfd_reloc_status_type
_bfd_mips_elf_got16_reloc (abfd,
reloc_entry,
symbol,
data,
@ -960,8 +919,8 @@ mips_elf_got16_reloc (abfd,
just like HI16. */
if (output_bfd != (bfd *) NULL
&& (symbol->flags & BSF_SECTION_SYM) != 0)
return mips_elf_hi16_reloc (abfd, reloc_entry, symbol, data,
input_section, output_bfd, error_message);
return _bfd_mips_elf_hi16_reloc (abfd, reloc_entry, symbol, data,
input_section, output_bfd, error_message);
abort ();
}
@ -1050,14 +1009,9 @@ static bfd_reloc_status_type gprel16_with_gp PARAMS ((bfd *, asymbol *,
arelent *, asection *,
boolean, PTR, bfd_vma));
static bfd_reloc_status_type
mips_elf_gprel16_reloc (abfd,
reloc_entry,
symbol,
data,
input_section,
output_bfd,
error_message)
bfd_reloc_status_type
_bfd_mips_elf_gprel16_reloc (abfd, reloc_entry, symbol, data, input_section,
output_bfd, error_message)
bfd *abfd;
arelent *reloc_entry;
asymbol *symbol;
@ -1128,9 +1082,17 @@ gprel16_with_gp (abfd, symbol, reloc_entry, input_section, relocateable, data,
insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
/* Set val to the offset into the section or symbol. */
val = ((insn & 0xffff) + reloc_entry->addend) & 0xffff;
if (val & 0x8000)
val -= 0x10000;
if (reloc_entry->howto->src_mask == 0)
{
/* This case occurs with the 64-bit MIPS ELF ABI. */
val = reloc_entry->addend;
}
else
{
val = ((insn & 0xffff) + reloc_entry->addend) & 0xffff;
if (val & 0x8000)
val -= 0x10000;
}
/* Adjust val for the final section location and GP value. If we
are producing relocateable output, we don't want to do this for
@ -1159,8 +1121,8 @@ static bfd_reloc_status_type gprel32_with_gp PARAMS ((bfd *, asymbol *,
arelent *, asection *,
boolean, PTR, bfd_vma));
static bfd_reloc_status_type
mips_elf_gprel32_reloc (abfd,
bfd_reloc_status_type
_bfd_mips_elf_gprel32_reloc (abfd,
reloc_entry,
symbol,
data,
@ -1237,7 +1199,13 @@ gprel32_with_gp (abfd, symbol, reloc_entry, input_section, relocateable, data,
if (reloc_entry->address > input_section->_cooked_size)
return bfd_reloc_outofrange;
val = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
if (reloc_entry->howto->src_mask == 0)
{
/* This case arises with the 64-bit MIPS ELF ABI. */
val = 0;
}
else
val = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
/* Set val to the offset into the section or symbol. */
val += reloc_entry->addend;
@ -1420,6 +1388,34 @@ bfd_elf32_swap_crinfo_out (abfd, in, ex)
bfd_h_put_32 (abfd, (bfd_vma) in->konst, ex->konst);
bfd_h_put_32 (abfd, (bfd_vma) in->vaddr, ex->vaddr);
}
/* Swap in an options header. */
void
bfd_mips_elf_swap_options_in (abfd, ex, in)
bfd *abfd;
const Elf_External_Options *ex;
Elf_Internal_Options *in;
{
in->kind = bfd_h_get_8 (abfd, ex->kind);
in->size = bfd_h_get_8 (abfd, ex->size);
in->section = bfd_h_get_16 (abfd, ex->section);
in->info = bfd_h_get_32 (abfd, ex->info);
}
/* Swap out an options header. */
void
bfd_mips_elf_swap_options_out (abfd, in, ex)
bfd *abfd;
const Elf_Internal_Options *in;
Elf_External_Options *ex;
{
bfd_h_put_8 (abfd, in->kind, ex->kind);
bfd_h_put_8 (abfd, in->size, ex->size);
bfd_h_put_16 (abfd, in->section, ex->section);
bfd_h_put_32 (abfd, in->info, ex->info);
}
/* Determine whether a symbol is global for the purposes of splitting
the symbol table into global symbols and local symbols. At least
@ -1543,8 +1539,8 @@ _bfd_mips_elf_final_write_processing (abfd, linker)
/* Function to keep MIPS specific file flags like as EF_MIPS_PIC. */
static boolean
mips_elf_set_private_flags (abfd, flags)
boolean
_bfd_mips_elf_set_private_flags (abfd, flags)
bfd *abfd;
flagword flags;
{
@ -1558,8 +1554,8 @@ mips_elf_set_private_flags (abfd, flags)
/* Copy backend specific data from one object module to another */
static boolean
mips_elf_copy_private_bfd_data (ibfd, obfd)
boolean
_bfd_mips_elf_copy_private_bfd_data (ibfd, obfd)
bfd *ibfd;
bfd *obfd;
{
@ -1582,8 +1578,8 @@ mips_elf_copy_private_bfd_data (ibfd, obfd)
/* Merge backend specific data from an object file to the output
object file when linking. */
static boolean
mips_elf_merge_private_bfd_data (ibfd, obfd)
boolean
_bfd_mips_elf_merge_private_bfd_data (ibfd, obfd)
bfd *ibfd;
bfd *obfd;
{
@ -1705,7 +1701,8 @@ _bfd_mips_elf_section_from_shdr (abfd, hdr, name)
return false;
break;
case SHT_MIPS_OPTIONS:
if (strcmp (name, ".options") != 0)
if (strcmp (name, ".options") != 0
&& strcmp (name, ".MIPS.options") != 0)
return false;
break;
case SHT_MIPS_DWARF:
@ -1764,6 +1761,47 @@ mips_elf32_section_from_shdr (abfd, hdr, name)
elf_gp (abfd) = s.ri_gp_value;
}
/* For a SHT_MIPS_OPTIONS section, look for a ODK_REGINFO entry, and
set the gp value based on what we find. We may see both
SHT_MIPS_REGINFO and SHT_MIPS_OPTIONS/ODK_REGINFO; in that case,
they should agree. */
if (hdr->sh_type == SHT_MIPS_OPTIONS)
{
bfd_byte *contents, *l, *lend;
contents = (bfd_byte *) bfd_malloc (hdr->sh_size);
if (contents == NULL)
return false;
if (! bfd_get_section_contents (abfd, hdr->bfd_section, contents,
(file_ptr) 0, hdr->sh_size))
{
free (contents);
return false;
}
l = contents;
lend = contents + hdr->sh_size;
while (l + sizeof (Elf_External_Options) <= lend)
{
Elf_Internal_Options intopt;
bfd_mips_elf_swap_options_in (abfd, (Elf_External_Options *) l,
&intopt);
if (intopt.kind == ODK_REGINFO)
{
Elf32_RegInfo intreg;
bfd_mips_elf32_swap_reginfo_in
(abfd,
((Elf32_External_RegInfo *)
(l + sizeof (Elf_External_Options))),
&intreg);
elf_gp (abfd) = intreg.ri_gp_value;
}
l += intopt.size;
}
free (contents);
}
return true;
}
@ -1842,7 +1880,8 @@ _bfd_mips_elf_fake_sections (abfd, hdr, sec)
|| strcmp (name, ".lit4") == 0
|| strcmp (name, ".lit8") == 0)
hdr->sh_flags |= SHF_MIPS_GPREL;
else if (strcmp (name, ".options") == 0)
else if (strcmp (name, ".options") == 0
|| strcmp (name, ".MIPS.options") == 0)
{
hdr->sh_type = SHT_MIPS_OPTIONS;
hdr->sh_entsize = 1;
@ -1881,11 +1920,56 @@ _bfd_mips_elf_section_from_bfd_section (abfd, hdr, sec, retval)
return false;
}
/* 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.
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. */
/* When are writing out the .options or .MIPS.options section,
remember the bytes we are writing out, so that we can install the
GP value in the section_processing routine. */
boolean
_bfd_mips_elf_set_section_contents (abfd, section, location, offset, count)
bfd *abfd;
sec_ptr section;
PTR location;
file_ptr offset;
bfd_size_type count;
{
if (strcmp (section->name, ".options") == 0
|| strcmp (section->name, ".MIPS.options") == 0)
{
bfd_byte *c;
if (elf_section_data (section) == NULL)
{
section->used_by_bfd =
(PTR) bfd_zalloc (abfd, sizeof (struct bfd_elf_section_data));
if (elf_section_data (section) == NULL)
return false;
}
c = (bfd_byte *) elf_section_data (section)->tdata;
if (c == NULL)
{
bfd_size_type size;
if (section->_cooked_size != 0)
size = section->_cooked_size;
else
size = section->_raw_size;
c = (PTR) bfd_zalloc (abfd, size);
if (c == NULL)
return false;
elf_section_data (section)->tdata = (PTR) c;
}
memcpy (c + offset, location, count);
}
return _bfd_elf_set_section_contents (abfd, section, location, offset,
count);
}
/* Work over a section just before writing it out. 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. */
boolean
_bfd_mips_elf_section_processing (abfd, hdr)
@ -1934,8 +2018,8 @@ _bfd_mips_elf_section_processing (abfd, hdr)
}
/* 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. */
value in the SHT_MIPS_REGINFO and SHT_MIPS_OPTIONS sections based
on the value we are using. */
static boolean
mips_elf32_section_processing (abfd, hdr)
@ -1958,6 +2042,48 @@ mips_elf32_section_processing (abfd, hdr)
return false;
}
if (hdr->sh_type == SHT_MIPS_OPTIONS
&& hdr->bfd_section != NULL
&& elf_section_data (hdr->bfd_section) != NULL
&& elf_section_data (hdr->bfd_section)->tdata != NULL)
{
bfd_byte *contents, *l, *lend;
/* We stored the section contents in the elf_section_data tdata
field in the set_section_contents routine. We save the
section contents so that we don't have to read them again.
At this point we know that elf_gp is set, so we can look
through the section contents to see if there is an
ODK_REGINFO structure. */
contents = (bfd_byte *) elf_section_data (hdr->bfd_section)->tdata;
l = contents;
lend = contents + hdr->sh_size;
while (l + sizeof (Elf_External_Options) <= lend)
{
Elf_Internal_Options intopt;
bfd_mips_elf_swap_options_in (abfd, (Elf_External_Options *) l,
&intopt);
if (intopt.kind == ODK_REGINFO)
{
bfd_byte buf[4];
if (bfd_seek (abfd,
(hdr->sh_offset
+ (l - contents)
+ sizeof (Elf_External_Options)
+ (sizeof (Elf32_External_RegInfo) - 4)),
SEEK_SET) == -1)
return false;
bfd_h_put_32 (abfd, elf_gp (abfd), buf);
if (bfd_write (buf, 1, 4, abfd) != 4)
return false;
}
l += intopt.size;
}
}
return _bfd_mips_elf_section_processing (abfd, hdr);
}
@ -2408,9 +2534,9 @@ struct mips_elf_find_line
struct ecoff_find_line i;
};
static boolean
mips_elf_find_nearest_line (abfd, section, symbols, offset, filename_ptr,
functionname_ptr, line_ptr)
boolean
_bfd_mips_elf_find_nearest_line (abfd, section, symbols, offset, filename_ptr,
functionname_ptr, line_ptr)
bfd *abfd;
asection *section;
asymbol **symbols;
@ -5839,7 +5965,7 @@ elf32_mips_get_relocated_section_contents (abfd, link_info, link_order, data,
fall over on its own. */
}
else if ((*parent)->howto->special_function
== mips_elf_gprel16_reloc)
== _bfd_mips_elf_gprel16_reloc)
{
/* bypass special_function call */
r = gprel16_with_gp (input_bfd, sym, *parent, input_section,
@ -5980,16 +6106,16 @@ static const struct ecoff_debug_swap mips_elf32_ecoff_debug_swap =
#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
#define bfd_elf32_find_nearest_line _bfd_mips_elf_find_nearest_line
#define bfd_elf32_set_section_contents _bfd_mips_elf_set_section_contents
#define bfd_elf32_bfd_link_hash_table_create \
mips_elf_link_hash_table_create
#define bfd_elf32_bfd_final_link mips_elf_final_link
#define bfd_elf32_bfd_copy_private_bfd_data \
mips_elf_copy_private_bfd_data
_bfd_mips_elf_copy_private_bfd_data
#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
_bfd_mips_elf_merge_private_bfd_data
#define bfd_elf32_bfd_set_private_flags _bfd_mips_elf_set_private_flags
#define elf_backend_add_symbol_hook mips_elf_add_symbol_hook
#define elf_backend_create_dynamic_sections \
mips_elf_create_dynamic_sections

View File

@ -67,6 +67,8 @@ static boolean mips_elf64_slurp_reloc_table
static void mips_elf64_write_relocs PARAMS ((bfd *, asection *, PTR));
static boolean mips_elf64_section_from_shdr
PARAMS ((bfd *, Elf_Internal_Shdr *, char *));
static boolean mips_elf64_section_processing
PARAMS ((bfd *, Elf_Internal_Shdr *));
/* The relocation types. */
@ -117,14 +119,6 @@ enum mips_elf64_reloc_type
from smaller values. Start with zero, widen, *then* decrement. */
#define MINUS_ONE (((bfd_vma)0) - 1)
/* FIXME: These need to be rewritten, or we need to use the versions
in elf32-mips.c. */
#define mips_elf_hi16_reloc bfd_elf_generic_reloc
#define mips_elf_lo16_reloc bfd_elf_generic_reloc
#define mips_elf_gprel16_reloc bfd_elf_generic_reloc
#define mips_elf_got16_reloc bfd_elf_generic_reloc
#define mips_elf_gprel32_reloc bfd_elf_generic_reloc
/* The relocation table used for SHT_REL sections. */
static reloc_howto_type mips_elf64_howto_table_rel[] =
@ -215,7 +209,7 @@ static reloc_howto_type mips_elf64_howto_table_rel[] =
false, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
mips_elf_hi16_reloc, /* special_function */
_bfd_mips_elf_hi16_reloc, /* special_function */
"R_MIPS_HI16", /* name */
true, /* partial_inplace */
0xffff, /* src_mask */
@ -230,7 +224,7 @@ static reloc_howto_type mips_elf64_howto_table_rel[] =
false, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
mips_elf_lo16_reloc, /* special_function */
_bfd_mips_elf_lo16_reloc, /* special_function */
"R_MIPS_LO16", /* name */
true, /* partial_inplace */
0xffff, /* src_mask */
@ -245,7 +239,7 @@ static reloc_howto_type mips_elf64_howto_table_rel[] =
false, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
mips_elf_gprel16_reloc, /* special_function */
_bfd_mips_elf_gprel16_reloc, /* special_function */
"R_MIPS_GPREL16", /* name */
true, /* partial_inplace */
0xffff, /* src_mask */
@ -260,7 +254,7 @@ static reloc_howto_type mips_elf64_howto_table_rel[] =
false, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
mips_elf_gprel16_reloc, /* special_function */
_bfd_mips_elf_gprel16_reloc, /* special_function */
"R_MIPS_LITERAL", /* name */
true, /* partial_inplace */
0xffff, /* src_mask */
@ -275,7 +269,7 @@ static reloc_howto_type mips_elf64_howto_table_rel[] =
false, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
mips_elf_got16_reloc, /* special_function */
_bfd_mips_elf_got16_reloc, /* special_function */
"R_MIPS_GOT16", /* name */
false, /* partial_inplace */
0, /* src_mask */
@ -321,7 +315,7 @@ static reloc_howto_type mips_elf64_howto_table_rel[] =
false, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
mips_elf_gprel32_reloc, /* special_function */
_bfd_mips_elf_gprel32_reloc, /* special_function */
"R_MIPS_GPREL32", /* name */
true, /* partial_inplace */
0xffffffff, /* src_mask */
@ -782,7 +776,7 @@ static reloc_howto_type mips_elf64_howto_table_rela[] =
false, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
mips_elf_gprel16_reloc, /* special_function */
_bfd_mips_elf_gprel16_reloc, /* special_function */
"R_MIPS_GPREL16", /* name */
true, /* partial_inplace */
0, /* src_mask */
@ -797,7 +791,7 @@ static reloc_howto_type mips_elf64_howto_table_rela[] =
false, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
mips_elf_gprel16_reloc, /* special_function */
_bfd_mips_elf_gprel16_reloc, /* special_function */
"R_MIPS_LITERAL", /* name */
true, /* partial_inplace */
0, /* src_mask */
@ -805,6 +799,7 @@ static reloc_howto_type mips_elf64_howto_table_rela[] =
false), /* pcrel_offset */
/* Reference to global offset table. */
/* FIXME: This is not handled correctly. */
HOWTO (R_MIPS_GOT16, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
@ -812,7 +807,7 @@ static reloc_howto_type mips_elf64_howto_table_rela[] =
false, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
mips_elf_got16_reloc, /* special_function */
bfd_elf_generic_reloc, /* special_function */
"R_MIPS_GOT16", /* name */
false, /* partial_inplace */
0, /* src_mask */
@ -858,7 +853,7 @@ static reloc_howto_type mips_elf64_howto_table_rela[] =
false, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
mips_elf_gprel32_reloc, /* special_function */
_bfd_mips_elf_gprel32_reloc, /* special_function */
"R_MIPS_GPREL32", /* name */
true, /* partial_inplace */
0, /* src_mask */
@ -1725,6 +1720,47 @@ mips_elf64_write_relocs (abfd, sec, data)
== count);
}
/* The .MIPS.options section holds register information in an
Elf64_Reginfo structure. These routines swap them in and out.
They are globally visible because they are used outside of BFD. */
void
bfd_mips_elf64_swap_reginfo_in (abfd, ex, in)
bfd *abfd;
const Elf64_External_RegInfo *ex;
Elf64_Internal_RegInfo *in;
{
in->ri_gprmask = bfd_h_get_32 (abfd, (bfd_byte *) ex->ri_gprmask);
in->ri_pad = bfd_h_get_32 (abfd, (bfd_byte *) ex->ri_pad);
in->ri_cprmask[0] = bfd_h_get_32 (abfd, (bfd_byte *) ex->ri_cprmask[0]);
in->ri_cprmask[1] = bfd_h_get_32 (abfd, (bfd_byte *) ex->ri_cprmask[1]);
in->ri_cprmask[2] = bfd_h_get_32 (abfd, (bfd_byte *) ex->ri_cprmask[2]);
in->ri_cprmask[3] = bfd_h_get_32 (abfd, (bfd_byte *) ex->ri_cprmask[3]);
in->ri_gp_value = bfd_h_get_64 (abfd, (bfd_byte *) ex->ri_gp_value);
}
void
bfd_mips_elf64_swap_reginfo_out (abfd, in, ex)
bfd *abfd;
const Elf64_Internal_RegInfo *in;
Elf64_External_RegInfo *ex;
{
bfd_h_put_32 (abfd, (bfd_vma) in->ri_gprmask,
(bfd_byte *) ex->ri_gprmask);
bfd_h_put_32 (abfd, (bfd_vma) in->ri_pad,
(bfd_byte *) ex->ri_pad);
bfd_h_put_32 (abfd, (bfd_vma) in->ri_cprmask[0],
(bfd_byte *) ex->ri_cprmask[0]);
bfd_h_put_32 (abfd, (bfd_vma) in->ri_cprmask[1],
(bfd_byte *) ex->ri_cprmask[1]);
bfd_h_put_32 (abfd, (bfd_vma) in->ri_cprmask[2],
(bfd_byte *) ex->ri_cprmask[2]);
bfd_h_put_32 (abfd, (bfd_vma) in->ri_cprmask[3],
(bfd_byte *) ex->ri_cprmask[3]);
bfd_h_put_64 (abfd, (bfd_vma) in->ri_gp_value,
(bfd_byte *) ex->ri_gp_value);
}
/* Handle a 64-bit MIPS ELF specific section. */
static boolean
@ -1736,8 +1772,103 @@ mips_elf64_section_from_shdr (abfd, hdr, name)
if (! _bfd_mips_elf_section_from_shdr (abfd, hdr, name))
return false;
/* For a SHT_MIPS_OPTIONS section, look for a ODK_REGINFO entry, and
set the gp value based on what we find. We may see both
SHT_MIPS_REGINFO and SHT_MIPS_OPTIONS/ODK_REGINFO; in that case,
they should agree. */
if (hdr->sh_type == SHT_MIPS_OPTIONS)
{
bfd_byte *contents, *l, *lend;
contents = (bfd_byte *) bfd_malloc (hdr->sh_size);
if (contents == NULL)
return false;
if (! bfd_get_section_contents (abfd, hdr->bfd_section, contents,
(file_ptr) 0, hdr->sh_size))
{
free (contents);
return false;
}
l = contents;
lend = contents + hdr->sh_size;
while (l + sizeof (Elf_External_Options) <= lend)
{
Elf_Internal_Options intopt;
bfd_mips_elf_swap_options_in (abfd, (Elf_External_Options *) l,
&intopt);
if (intopt.kind == ODK_REGINFO)
{
Elf64_Internal_RegInfo intreg;
bfd_mips_elf64_swap_reginfo_in
(abfd,
((Elf64_External_RegInfo *)
(l + sizeof (Elf_External_Options))),
&intreg);
elf_gp (abfd) = intreg.ri_gp_value;
}
l += intopt.size;
}
free (contents);
}
return true;
}
/* Work over a section just before writing it out. We update the GP
value in the SHT_MIPS_OPTIONS section based on the value we are
using. */
static boolean
mips_elf64_section_processing (abfd, hdr)
bfd *abfd;
Elf_Internal_Shdr *hdr;
{
if (hdr->sh_type == SHT_MIPS_OPTIONS
&& hdr->bfd_section != NULL
&& elf_section_data (hdr->bfd_section) != NULL
&& elf_section_data (hdr->bfd_section)->tdata != NULL)
{
bfd_byte *contents, *l, *lend;
/* We stored the section contents in the elf_section_data tdata
field in the set_section_contents routine. We save the
section contents so that we don't have to read them again.
At this point we know that elf_gp is set, so we can look
through the section contents to see if there is an
ODK_REGINFO structure. */
contents = (bfd_byte *) elf_section_data (hdr->bfd_section)->tdata;
l = contents;
lend = contents + hdr->sh_size;
while (l + sizeof (Elf_External_Options) <= lend)
{
Elf_Internal_Options intopt;
bfd_mips_elf_swap_options_in (abfd, (Elf_External_Options *) l,
&intopt);
if (intopt.kind == ODK_REGINFO)
{
bfd_byte buf[8];
if (bfd_seek (abfd,
(hdr->sh_offset
+ (l - contents)
+ sizeof (Elf_External_Options)
+ (sizeof (Elf64_External_RegInfo) - 8)),
SEEK_SET) == -1)
return false;
bfd_h_put_64 (abfd, elf_gp (abfd), buf);
if (bfd_write (buf, 1, 8, abfd) != 8)
return false;
}
l += intopt.size;
}
}
return _bfd_mips_elf_section_processing (abfd, hdr);
}
/* ECOFF swapping routines. These are used when dealing with the
.mdebug section, which is in the ECOFF debugging format. */
@ -1822,13 +1953,20 @@ const struct elf_size_info mips_elf64_size_info =
#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_section_processing mips_elf64_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_find_nearest_line _bfd_mips_elf_find_nearest_line
#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
#define bfd_elf64_set_section_contents _bfd_mips_elf_set_section_contents
#define bfd_elf64_bfd_copy_private_bfd_data \
_bfd_mips_elf_copy_private_bfd_data
#define bfd_elf64_bfd_merge_private_bfd_data \
_bfd_mips_elf_merge_private_bfd_data
#define bfd_elf64_bfd_set_private_flags _bfd_mips_elf_set_private_flags
#include "elf64-target.h"