* elf32-mips.c (mips_elf_generic_reloc): New Function.

(elf_mips_howto_table_rel): Use it.
	(gprel32_with_gp): Move prototype.
	(mips_elf_hi16_reloc): Check for ! BSF_LOCAL instead of zero addend.
	Use mips_elf_generic_reloc.
	(mips_elf_got16_reloc): Check for ! BSF_LOCAL instead of zero addend.
	Code cleanup.
	(_bfd_mips_elf32_gprel16_reloc): Check for ! BSF_LOCAL instead of
	zero addend.
	(mips_elf_gprel32_reloc): Likewise. Use the same GP assignment logic
	as in the other *_gprel*_reloc functions.
	(gprel32_with_gp): Handle partial_inplace properly.
	(mips32_64bit_reloc): Use mips_elf_generic_reloc.
	(mips16_gprel_reloc): Check for ! BSF_LOCAL instead of zero addend.
	Do addend handling directly instead of calling
	_bfd_mips_elf_gprel16_with_gp. Handle partial_inplace properly.
	* elf64-mips.c (mips_elf64_hi16_reloc): Check for ! BSF_LOCAL instead
	of zero addend. Handle partial_inplace properly.
	(mips_elf64_got16_reloc): Check for ! BSF_LOCAL instead of zero
	addend.
	(mips_elf64_gprel16_reloc): Likewise.
	(mips_elf64_literal_reloc): Likewise.
	(mips_elf64_gprel32_reloc): Likewise. Use the same GP assignment
	logic as in the other *_gprel*_reloc functions. Handle
	partial_inplace properly.
	(mips_elf64_shift6_reloc): Check for ! BSF_LOCAL instead of zero
	addend. Handle partial_inplace properly.
	(mips16_gprel_reloc): Likewise. Do addend handling directly instead
	of calling _bfd_mips_elf_gprel16_with_gp.
	* elfn32-mips.c (mips_elf_got16_reloc): Check for BSF_LOCAL.
	(mips_elf_gprel32_reloc): Check for ! BSF_LOCAL instead
	of zero addend.
	(mips_elf_shift6_reloc): Handle partial_inplace properly.
	(mips16_gprel_reloc): Likewise. Do addend handling directly instead
	of calling _bfd_mips_elf_gprel16_with_gp.
	* elfxx-mips.c (_bfd_mips_elf_gprel16_with_gp): Handle
	partial_inplace properly. Fix wrong addend handling. Fix overflow
	check.
	(_bfd_mips_elf_sign_extend): Renamed from mips_elf_sign_extend and
	exported.
	(mips_elf_calculate_relocation): Use _bfd_mips_elf_sign_extend.
	(_bfd_mips_elf_relocate_section): Likewise.
	(mips_elf_create_dynamic_relocation): Update sec_info_type access.
	* elfxx-mips.h (_bfd_mips_relax_section): Fix prototype declaration.
	(_bfd_mips_elf_sign_extend): New prototype.
	* config/tc-mips.c (md_pcrel_from): Return actual pcrel address.
	(md_apply_fix3): Ignore non-special relocations. Remove superfluous
	exceptions from size assert. Remove most of the addend fixup
	specialcasing. Remove value, use valP directly. simplify fx_addnumber
	handling. Remove zero addend specialcases.
	(tc_gen_reloc): Use appropriate value for reloc2 addend. Remove
	the addend fixup specialcase.
	* config/tc-mips.h (MD_APPLY_SYM_VALUE): Define as 0.
This commit is contained in:
Thiemo Seufer
2003-06-11 16:22:26 +00:00
parent cd90e54f8f
commit a7ebbfdf67
9 changed files with 478 additions and 427 deletions

View File

@@ -47,12 +47,17 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#define ECOFF_SIGNED_32
#include "ecoffswap.h"
static bfd_reloc_status_type mips_elf_generic_reloc
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
static bfd_reloc_status_type mips_elf_hi16_reloc
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
static bfd_reloc_status_type mips_elf_lo16_reloc
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
static bfd_reloc_status_type mips_elf_got16_reloc
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
static bfd_reloc_status_type gprel32_with_gp
PARAMS ((bfd *, asymbol *, arelent *, asection *, bfd_boolean, PTR,
bfd_vma));
static bfd_reloc_status_type mips_elf_gprel32_reloc
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
static bfd_reloc_status_type mips32_64bit_reloc
@@ -116,7 +121,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
mips_elf_generic_reloc, /* special_function */
"R_MIPS_NONE", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
@@ -131,7 +136,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
mips_elf_generic_reloc, /* special_function */
"R_MIPS_16", /* name */
TRUE, /* partial_inplace */
0x0000ffff, /* src_mask */
@@ -146,7 +151,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
mips_elf_generic_reloc, /* special_function */
"R_MIPS_32", /* name */
TRUE, /* partial_inplace */
0xffffffff, /* src_mask */
@@ -161,7 +166,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
mips_elf_generic_reloc, /* special_function */
"R_MIPS_REL32", /* name */
TRUE, /* partial_inplace */
0xffffffff, /* src_mask */
@@ -179,7 +184,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
/* This needs complex overflow
detection, because the upper four
bits must match the PC + 4. */
bfd_elf_generic_reloc, /* special_function */
mips_elf_generic_reloc, /* special_function */
"R_MIPS_26", /* name */
TRUE, /* partial_inplace */
0x03ffffff, /* src_mask */
@@ -269,7 +274,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
mips_elf_generic_reloc, /* special_function */
"R_MIPS_PC16", /* name */
TRUE, /* partial_inplace */
0x0000ffff, /* src_mask */
@@ -284,7 +289,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
mips_elf_generic_reloc, /* special_function */
"R_MIPS_CALL16", /* name */
TRUE, /* partial_inplace */
0x0000ffff, /* src_mask */
@@ -320,7 +325,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
FALSE, /* pc_relative */
6, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
mips_elf_generic_reloc, /* special_function */
"R_MIPS_SHIFT5", /* name */
TRUE, /* partial_inplace */
0x000007c0, /* src_mask */
@@ -337,7 +342,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
FALSE, /* pc_relative */
6, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
mips_elf_generic_reloc, /* special_function */
"R_MIPS_SHIFT6", /* name */
TRUE, /* partial_inplace */
0x000007c4, /* src_mask */
@@ -367,7 +372,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
mips_elf_generic_reloc, /* special_function */
"R_MIPS_GOT_DISP", /* name */
TRUE, /* partial_inplace */
0x0000ffff, /* src_mask */
@@ -382,7 +387,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
mips_elf_generic_reloc, /* special_function */
"R_MIPS_GOT_PAGE", /* name */
TRUE, /* partial_inplace */
0x0000ffff, /* src_mask */
@@ -397,7 +402,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
mips_elf_generic_reloc, /* special_function */
"R_MIPS_GOT_OFST", /* name */
TRUE, /* partial_inplace */
0x0000ffff, /* src_mask */
@@ -412,7 +417,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
mips_elf_generic_reloc, /* special_function */
"R_MIPS_GOT_HI16", /* name */
TRUE, /* partial_inplace */
0x0000ffff, /* src_mask */
@@ -427,7 +432,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
mips_elf_generic_reloc, /* special_function */
"R_MIPS_GOT_LO16", /* name */
TRUE, /* partial_inplace */
0x0000ffff, /* src_mask */
@@ -442,7 +447,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
mips_elf_generic_reloc, /* special_function */
"R_MIPS_SUB", /* name */
TRUE, /* partial_inplace */
MINUS_ONE, /* src_mask */
@@ -462,7 +467,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
mips_elf_generic_reloc, /* special_function */
"R_MIPS_HIGHER", /* name */
TRUE, /* partial_inplace */
0x0000ffff, /* src_mask */
@@ -477,7 +482,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
mips_elf_generic_reloc, /* special_function */
"R_MIPS_HIGHEST", /* name */
TRUE, /* partial_inplace */
0x0000ffff, /* src_mask */
@@ -492,7 +497,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
mips_elf_generic_reloc, /* special_function */
"R_MIPS_CALL_HI16", /* name */
TRUE, /* partial_inplace */
0x0000ffff, /* src_mask */
@@ -507,7 +512,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
mips_elf_generic_reloc, /* special_function */
"R_MIPS_CALL_LO16", /* name */
TRUE, /* partial_inplace */
0x0000ffff, /* src_mask */
@@ -522,7 +527,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
mips_elf_generic_reloc, /* special_function */
"R_MIPS_SCN_DISP", /* name */
TRUE, /* partial_inplace */
0xffffffff, /* src_mask */
@@ -543,7 +548,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
mips_elf_generic_reloc, /* special_function */
"R_MIPS_JALR", /* name */
FALSE, /* partial_inplace */
0x00000000, /* src_mask */
@@ -645,7 +650,7 @@ static reloc_howto_type elf_mips_gnu_rel16_s2 =
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
mips_elf_generic_reloc, /* special_function */
"R_MIPS_GNU_REL16_S2", /* name */
TRUE, /* partial_inplace */
0xffff, /* src_mask */
@@ -661,7 +666,7 @@ static reloc_howto_type elf_mips_gnu_pcrel64 =
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
mips_elf_generic_reloc, /* special_function */
"R_MIPS_PC64", /* name */
TRUE, /* partial_inplace */
MINUS_ONE, /* src_mask */
@@ -677,7 +682,7 @@ static reloc_howto_type elf_mips_gnu_pcrel32 =
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
mips_elf_generic_reloc, /* special_function */
"R_MIPS_PC32", /* name */
TRUE, /* partial_inplace */
0xffffffff, /* src_mask */
@@ -716,6 +721,33 @@ static reloc_howto_type elf_mips_gnu_vtentry_howto =
0, /* dst_mask */
FALSE); /* pcrel_offset */
/* We use this instead of bfd_elf_generic_reloc because the latter
gets the handling of zero addends wrong. */
static bfd_reloc_status_type
mips_elf_generic_reloc (abfd, reloc_entry, symbol, data, input_section,
output_bfd, error_message)
bfd *abfd ATTRIBUTE_UNUSED;
arelent *reloc_entry;
asymbol *symbol;
PTR data ATTRIBUTE_UNUSED;
asection *input_section;
bfd *output_bfd;
char **error_message ATTRIBUTE_UNUSED;
{
/* If we're relocating, and this is an external symbol, we don't want
to change anything. */
if (output_bfd != (bfd *) NULL
&& (symbol->flags & BSF_SECTION_SYM) == 0
&& (symbol->flags & BSF_LOCAL) != 0)
{
reloc_entry->address += input_section->output_offset;
return bfd_reloc_ok;
}
/* Just go on, nothing to see here. */
return bfd_reloc_continue;
}
/* Do a R_MIPS_HI16 relocation. This has to be done in combination
with a R_MIPS_LO16 reloc, because there is a carry from the LO16 to
the HI16. Here we just save the information we need; we do the
@@ -761,7 +793,7 @@ mips_elf_hi16_reloc (abfd, reloc_entry, symbol, data, input_section,
to change anything. */
if (output_bfd != (bfd *) NULL
&& (symbol->flags & BSF_SECTION_SYM) == 0
&& reloc_entry->addend == 0)
&& (symbol->flags & BSF_LOCAL) != 0)
{
reloc_entry->address += input_section->output_offset;
return bfd_reloc_ok;
@@ -923,8 +955,8 @@ mips_elf_lo16_reloc (abfd, reloc_entry, symbol, data, input_section,
}
/* Now do the LO16 reloc in the usual way. */
return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
input_section, output_bfd, error_message);
return mips_elf_generic_reloc (abfd, reloc_entry, symbol, data,
input_section, output_bfd, error_message);
}
/* Do a R_MIPS_GOT16 reloc. This is a reloc against the global offset
@@ -956,20 +988,14 @@ mips_elf_got16_reloc (abfd, reloc_entry, symbol, data, input_section,
to change anything. */
if (output_bfd != (bfd *) NULL
&& (symbol->flags & BSF_SECTION_SYM) == 0
&& reloc_entry->addend == 0)
&& (symbol->flags & BSF_LOCAL) != 0)
{
reloc_entry->address += input_section->output_offset;
return bfd_reloc_ok;
}
/* If we're relocating, and this is a local symbol, we can handle it
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);
abort ();
return mips_elf_hi16_reloc (abfd, reloc_entry, symbol, data,
input_section, output_bfd, error_message);
}
/* Set the GP value for OUTPUT_BFD. Returns FALSE if this is a
@@ -1087,13 +1113,11 @@ _bfd_mips_elf32_gprel16_reloc (abfd, reloc_entry, symbol, data, input_section,
bfd_reloc_status_type ret;
bfd_vma gp;
/* If we're relocating, and this is an external symbol with no
addend, we don't want to change anything. We will only have an
addend if this is a newly created reloc, not read from an ELF
file. */
/* If we're relocating, and this is an external symbol, we don't want
to change anything. */
if (output_bfd != (bfd *) NULL
&& (symbol->flags & BSF_SECTION_SYM) == 0
&& reloc_entry->addend == 0)
&& (symbol->flags & BSF_LOCAL) != 0)
{
reloc_entry->address += input_section->output_offset;
return bfd_reloc_ok;
@@ -1120,10 +1144,6 @@ _bfd_mips_elf32_gprel16_reloc (abfd, reloc_entry, symbol, data, input_section,
/* Do a R_MIPS_GPREL32 relocation. This is a 32 bit value which must
become the offset from the gp register. */
static bfd_reloc_status_type gprel32_with_gp
PARAMS ((bfd *, asymbol *, arelent *, asection *, bfd_boolean, PTR,
bfd_vma));
static bfd_reloc_status_type
mips_elf_gprel32_reloc (abfd, reloc_entry, symbol, data, input_section,
output_bfd, error_message)
@@ -1139,13 +1159,11 @@ mips_elf_gprel32_reloc (abfd, reloc_entry, symbol, data, input_section,
bfd_reloc_status_type ret;
bfd_vma gp;
/* If we're relocating, and this is an external symbol with no
addend, we don't want to change anything. We will only have an
addend if this is a newly created reloc, not read from an ELF
file. */
/* If we're relocating, and this is an external symbol, we don't want
to change anything. */
if (output_bfd != (bfd *) NULL
&& (symbol->flags & BSF_SECTION_SYM) == 0
&& reloc_entry->addend == 0)
&& (symbol->flags & BSF_LOCAL) != 0)
{
*error_message = (char *)
_("32bits gp relative relocation occurs for an external symbol");
@@ -1153,21 +1171,18 @@ mips_elf_gprel32_reloc (abfd, reloc_entry, symbol, data, input_section,
}
if (output_bfd != (bfd *) NULL)
{
relocateable = TRUE;
gp = _bfd_get_gp_value (output_bfd);
}
relocateable = TRUE;
else
{
relocateable = FALSE;
output_bfd = symbol->section->output_section->owner;
ret = mips_elf_final_gp (output_bfd, symbol, relocateable,
error_message, &gp);
if (ret != bfd_reloc_ok)
return ret;
}
ret = mips_elf_final_gp (output_bfd, symbol, relocateable,
error_message, &gp);
if (ret != bfd_reloc_ok)
return ret;
return gprel32_with_gp (abfd, symbol, reloc_entry, input_section,
relocateable, data, gp);
}
@@ -1184,7 +1199,7 @@ gprel32_with_gp (abfd, symbol, reloc_entry, input_section, relocateable, data,
bfd_vma gp;
{
bfd_vma relocation;
unsigned long val;
bfd_vma val;
if (bfd_is_com_section (symbol->section))
relocation = 0;
@@ -1197,10 +1212,11 @@ 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);
/* Set val to the offset into the section or symbol. */
val += reloc_entry->addend;
val = reloc_entry->addend;
if (reloc_entry->howto->partial_inplace)
val += bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
/* Adjust val for the final section location and GP value. If we
are producing relocateable output, we don't want to do this for
@@ -1209,7 +1225,10 @@ gprel32_with_gp (abfd, symbol, reloc_entry, input_section, relocateable, data,
|| (symbol->flags & BSF_SECTION_SYM) != 0)
val += relocation - gp;
bfd_put_32 (abfd, (bfd_vma) val, (bfd_byte *) data + reloc_entry->address);
if (reloc_entry->howto->partial_inplace)
bfd_put_32 (abfd, val, (bfd_byte *) data + reloc_entry->address);
else
reloc_entry->addend = val;
if (relocateable)
reloc_entry->address += input_section->output_offset;
@@ -1237,8 +1256,8 @@ mips32_64bit_reloc (abfd, reloc_entry, symbol, data, input_section,
unsigned long val;
bfd_size_type addr;
r = bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
input_section, output_bfd, error_message);
r = mips_elf_generic_reloc (abfd, reloc_entry, symbol, data,
input_section, output_bfd, error_message);
if (r != bfd_reloc_continue)
return r;
@@ -1315,16 +1334,16 @@ mips16_gprel_reloc (abfd, reloc_entry, symbol, data, input_section,
bfd_boolean relocateable;
bfd_reloc_status_type ret;
bfd_vma gp;
unsigned short extend, insn;
unsigned long final;
unsigned short extend = 0;
unsigned short insn = 0;
bfd_signed_vma val;
bfd_vma relocation;
/* If we're relocating, and this is an external symbol with no
addend, we don't want to change anything. We will only have an
addend if this is a newly created reloc, not read from an ELF
file. */
/* If we're relocating, and this is an external symbol, we don't want
to change anything. */
if (output_bfd != NULL
&& (symbol->flags & BSF_SECTION_SYM) == 0
&& reloc_entry->addend == 0)
&& (symbol->flags & BSF_LOCAL) != 0)
{
reloc_entry->address += input_section->output_offset;
return bfd_reloc_ok;
@@ -1346,33 +1365,55 @@ mips16_gprel_reloc (abfd, reloc_entry, symbol, data, input_section,
if (reloc_entry->address > input_section->_cooked_size)
return bfd_reloc_outofrange;
/* Pick up the mips16 extend instruction and the real instruction. */
extend = bfd_get_16 (abfd, (bfd_byte *) data + reloc_entry->address);
insn = bfd_get_16 (abfd, (bfd_byte *) data + reloc_entry->address + 2);
if (bfd_is_com_section (symbol->section))
relocation = 0;
else
relocation = symbol->value;
/* Stuff the current addend back as a 32 bit value, do the usual
relocation, and then clean up. */
bfd_put_32 (abfd,
(bfd_vma) (((extend & 0x1f) << 11)
| (extend & 0x7e0)
| (insn & 0x1f)),
(bfd_byte *) data + reloc_entry->address);
relocation += symbol->section->output_section->vma;
relocation += symbol->section->output_offset;
ret = _bfd_mips_elf_gprel16_with_gp (abfd, symbol, reloc_entry,
input_section, relocateable, data, gp);
/* Set val to the offset into the section or symbol. */
val = reloc_entry->addend;
final = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
bfd_put_16 (abfd,
(bfd_vma) ((extend & 0xf800)
| ((final >> 11) & 0x1f)
| (final & 0x7e0)),
(bfd_byte *) data + reloc_entry->address);
bfd_put_16 (abfd,
(bfd_vma) ((insn & 0xffe0)
| (final & 0x1f)),
(bfd_byte *) data + reloc_entry->address + 2);
if (reloc_entry->howto->partial_inplace)
{
/* Pick up the mips16 extend instruction and the real instruction. */
extend = bfd_get_16 (abfd, (bfd_byte *) data + reloc_entry->address);
insn = bfd_get_16 (abfd, (bfd_byte *) data + reloc_entry->address + 2);
val += ((extend & 0x1f) << 11) | (extend & 0x7e0) | (insn & 0x1f);
}
return ret;
_bfd_mips_elf_sign_extend(val, 16);
/* Adjust val for the final section location and GP value. If we
are producing relocateable output, we don't want to do this for
an external symbol. */
if (! relocateable
|| (symbol->flags & BSF_SECTION_SYM) != 0)
val += relocation - gp;
if (reloc_entry->howto->partial_inplace)
{
bfd_put_16 (abfd,
(bfd_vma) ((extend & 0xf800)
| ((val >> 11) & 0x1f)
| (val & 0x7e0)),
(bfd_byte *) data + reloc_entry->address);
bfd_put_16 (abfd,
(bfd_vma) ((insn & 0xffe0)
| (val & 0x1f)),
(bfd_byte *) data + reloc_entry->address + 2);
}
else
reloc_entry->addend = val;
if (relocateable)
reloc_entry->address += input_section->output_offset;
else if (((val & ~0xffff) != ~0xffff) && ((val & ~0xffff) != 0))
return bfd_reloc_overflow;
return bfd_reloc_ok;
}
/* A mapping from BFD reloc types to MIPS ELF reloc types. */