* 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

@ -1,3 +1,51 @@
2003-06-11 Thiemo Seufer <seufer@csv.ica.uni-stuttgart.de>
* 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.
2003-06-11 Federico G. Schwindt <fgsch@lodoss.net>
* config.bfd (sparc-*-openbsd[0-2].* | sparc-*-openbsd3.[0-1]):

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. */

View File

@ -1447,15 +1447,17 @@ mips_elf64_hi16_reloc (abfd, reloc_entry, symbol, data, input_section,
want to change anything. */
if (output_bfd != (bfd *) NULL
&& (symbol->flags & BSF_SECTION_SYM) == 0
&& (! reloc_entry->howto->partial_inplace
|| reloc_entry->addend == 0))
&& (symbol->flags & BSF_LOCAL) != 0)
{
reloc_entry->address += input_section->output_offset;
return bfd_reloc_ok;
}
if (((reloc_entry->addend & 0xffff) + 0x8000) & ~0xffff)
reloc_entry->addend += 0x8000;
if (reloc_entry->howto->partial_inplace)
{
if (((reloc_entry->addend & 0xffff) + 0x8000) & ~0xffff)
reloc_entry->addend += 0x8000;
}
return bfd_reloc_continue;
}
@ -1488,7 +1490,8 @@ mips_elf64_got16_reloc (abfd, reloc_entry, symbol, data, input_section,
/* If we're relocating, and this is a local symbol, we can handle it
just like an R_MIPS_HI16. */
if (output_bfd != (bfd *) NULL
&& (symbol->flags & BSF_SECTION_SYM) != 0)
&& ((symbol->flags & BSF_SECTION_SYM) != 0
|| (symbol->flags & BSF_LOCAL) == 0))
return mips_elf64_hi16_reloc (abfd, reloc_entry, symbol, data,
input_section, output_bfd, error_message);
@ -1610,14 +1613,11 @@ mips_elf64_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->howto->partial_inplace
|| reloc_entry->addend == 0))
&& (symbol->flags & BSF_LOCAL) != 0)
{
reloc_entry->address += input_section->output_offset;
return bfd_reloc_ok;
@ -1662,8 +1662,7 @@ mips_elf64_literal_reloc (abfd, reloc_entry, symbol, data, input_section,
want to change anything. */
if (output_bfd != (bfd *) NULL
&& (symbol->flags & BSF_SECTION_SYM) == 0
&& (! reloc_entry->howto->partial_inplace
|| reloc_entry->addend == 0))
&& (symbol->flags & BSF_LOCAL) != 0)
{
reloc_entry->address += input_section->output_offset;
return bfd_reloc_ok;
@ -1706,15 +1705,13 @@ mips_elf64_gprel32_reloc (abfd, reloc_entry, symbol, data, input_section,
bfd_reloc_status_type ret;
bfd_vma gp;
bfd_vma relocation;
unsigned long val;
bfd_vma val;
/* 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");
@ -1722,21 +1719,18 @@ mips_elf64_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_elf64_final_gp (output_bfd, symbol, relocateable,
error_message, &gp);
if (ret != bfd_reloc_ok)
return ret;
}
ret = mips_elf64_final_gp (output_bfd, symbol, relocateable,
error_message, &gp);
if (ret != bfd_reloc_ok)
return ret;
if (bfd_is_com_section (symbol->section))
relocation = 0;
else
@ -1748,16 +1742,11 @@ mips_elf64_gprel32_reloc (abfd, reloc_entry, symbol, data, input_section,
if (reloc_entry->address > input_section->_cooked_size)
return bfd_reloc_outofrange;
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;
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
@ -1766,7 +1755,10 @@ mips_elf64_gprel32_reloc (abfd, reloc_entry, symbol, data, input_section,
|| (symbol->flags & BSF_SECTION_SYM) != 0)
val += relocation - gp;
bfd_put_32 (abfd, 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;
@ -1792,15 +1784,17 @@ mips_elf64_shift6_reloc (abfd, reloc_entry, symbol, data, input_section,
want to change anything. */
if (output_bfd != (bfd *) NULL
&& (symbol->flags & BSF_SECTION_SYM) == 0
&& (! reloc_entry->howto->partial_inplace
|| reloc_entry->addend == 0))
&& (symbol->flags & BSF_LOCAL) != 0)
{
reloc_entry->address += input_section->output_offset;
return bfd_reloc_ok;
}
reloc_entry->addend = (reloc_entry->addend & 0x00007c0)
| (reloc_entry->addend & 0x00000800) >> 9;
if (reloc_entry->howto->partial_inplace)
{
reloc_entry->addend = ((reloc_entry->addend & 0x00007c0)
| (reloc_entry->addend & 0x00000800) >> 9);
}
return bfd_reloc_continue;
}
@ -1857,16 +1851,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. */
addend, 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;
@ -1888,33 +1882,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. */

View File

@ -1453,9 +1453,10 @@ mips_elf_got16_reloc (abfd, reloc_entry, symbol, data, input_section,
char **error_message;
{
/* If we're relocating, and this is a local symbol, we can handle it
just like HI16. */
just like an R_MIPS_HI16. */
if (output_bfd != (bfd *) NULL
&& (symbol->flags & BSF_SECTION_SYM) != 0)
&& ((symbol->flags & BSF_SECTION_SYM) != 0
|| (symbol->flags & BSF_LOCAL) == 0))
return mips_elf_hi16_reloc (abfd, reloc_entry, symbol, data,
input_section, output_bfd, error_message);
@ -1654,12 +1655,10 @@ mips_elf_gprel32_reloc (abfd, reloc_entry, symbol, data, input_section,
GET_RELOC_ADDEND (output_bfd, symbol, reloc_entry, input_section)
/* R_MIPS_GPREL32 relocations are defined for local symbols only.
We will only have an addend if this is a newly created reloc,
not read from an ELF file. */
/* R_MIPS_GPREL32 relocations are defined for local symbols only. */
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");
@ -1750,8 +1749,11 @@ mips_elf_shift6_reloc (abfd, reloc_entry, symbol, data, input_section,
{
GET_RELOC_ADDEND (output_bfd, symbol, reloc_entry, input_section)
reloc_entry->addend = (reloc_entry->addend & 0x00007c0)
| (reloc_entry->addend & 0x00000800) >> 9;
if (reloc_entry->howto->partial_inplace)
{
reloc_entry->addend = ((reloc_entry->addend & 0x00007c0)
| (reloc_entry->addend & 0x00000800) >> 9);
}
SET_RELOC_ADDEND (reloc_entry)
@ -1801,8 +1803,10 @@ 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;
GET_RELOC_ADDEND (output_bfd, symbol, reloc_entry, input_section)
@ -1822,33 +1826,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;
}
#undef GET_RELOC_ADDEND

View File

@ -434,7 +434,6 @@ static const Elf_Internal_Rela *mips_elf_next_relocation
const Elf_Internal_Rela *));
static bfd_boolean mips_elf_local_relocation_p
PARAMS ((bfd *, const Elf_Internal_Rela *, asection **, bfd_boolean));
static bfd_vma mips_elf_sign_extend PARAMS ((bfd_vma, int));
static bfd_boolean mips_elf_overflow_p PARAMS ((bfd_vma, int));
static bfd_vma mips_elf_high PARAMS ((bfd_vma));
static bfd_vma mips_elf_higher PARAMS ((bfd_vma));
@ -1091,8 +1090,8 @@ _bfd_mips_elf_gprel16_with_gp (abfd, symbol, reloc_entry, input_section,
bfd_vma gp;
{
bfd_vma relocation;
unsigned long insn;
unsigned long val;
unsigned long insn = 0;
bfd_signed_vma val;
if (bfd_is_com_section (symbol->section))
relocation = 0;
@ -1105,21 +1104,17 @@ _bfd_mips_elf_gprel16_with_gp (abfd, symbol, reloc_entry, input_section,
if (reloc_entry->address > input_section->_cooked_size)
return bfd_reloc_outofrange;
insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
/* Set val to the offset into the section or symbol. */
if (reloc_entry->howto->src_mask == 0)
val = reloc_entry->addend;
if (reloc_entry->howto->partial_inplace)
{
/* 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;
insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
val += insn & 0xffff;
}
_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. */
@ -1127,13 +1122,18 @@ _bfd_mips_elf_gprel16_with_gp (abfd, symbol, reloc_entry, input_section,
|| (symbol->flags & BSF_SECTION_SYM) != 0)
val += relocation - gp;
insn = (insn & ~0xffff) | (val & 0xffff);
bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address);
if (reloc_entry->howto->partial_inplace)
{
insn = (insn & ~0xffff) | (val & 0xffff);
bfd_put_32 (abfd, (bfd_vma) insn,
(bfd_byte *) data + reloc_entry->address);
}
else
reloc_entry->addend = val;
if (relocateable)
reloc_entry->address += input_section->output_offset;
else if ((long) val >= 0x8000 || (long) val < -0x8000)
else if (((val & ~0xffff) != ~0xffff) && ((val & ~0xffff) != 0))
return bfd_reloc_overflow;
return bfd_reloc_ok;
@ -2741,8 +2741,8 @@ mips_elf_local_relocation_p (input_bfd, relocation, local_sections,
/* Sign-extend VALUE, which has the indicated number of BITS. */
static bfd_vma
mips_elf_sign_extend (value, bits)
bfd_vma
_bfd_mips_elf_sign_extend (value, bits)
bfd_vma value;
int bits;
{
@ -3305,7 +3305,7 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
return bfd_reloc_continue;
case R_MIPS_16:
value = symbol + mips_elf_sign_extend (addend, 16);
value = symbol + _bfd_mips_elf_sign_extend (addend, 16);
overflowed_p = mips_elf_overflow_p (value, 16);
break;
@ -3356,7 +3356,7 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
break;
case R_MIPS_GNU_REL16_S2:
value = symbol + mips_elf_sign_extend (addend << 2, 18) - p;
value = symbol + _bfd_mips_elf_sign_extend (addend << 2, 18) - p;
overflowed_p = mips_elf_overflow_p (value, 18);
value = (value >> 2) & howto->dst_mask;
break;
@ -3381,7 +3381,7 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
if (local_p)
value = (((addend << 2) | ((p + 4) & 0xf0000000)) + symbol) >> 2;
else
value = (mips_elf_sign_extend (addend << 2, 28) + symbol) >> 2;
value = (_bfd_mips_elf_sign_extend (addend << 2, 28) + symbol) >> 2;
value &= howto->dst_mask;
break;
@ -3441,7 +3441,7 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
instruction. If the addend was separate, leave it alone,
otherwise we may lose significant bits. */
if (howto->partial_inplace)
addend = mips_elf_sign_extend (addend, 16);
addend = _bfd_mips_elf_sign_extend (addend, 16);
value = symbol + addend - gp;
/* If the symbol was local, any earlier relocatable links will
have adjusted its addend with the gp offset, so compensate
@ -3490,7 +3490,7 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
break;
case R_MIPS_PC16:
value = mips_elf_sign_extend (addend, 16) + symbol - p;
value = _bfd_mips_elf_sign_extend (addend, 16) + symbol - p;
overflowed_p = mips_elf_overflow_p (value, 16);
break;
@ -3853,7 +3853,7 @@ mips_elf_create_dynamic_relocation (output_bfd, info, rel, h, sec,
/* We begin by assuming that the offset for the dynamic relocation
is the same as for the original relocation. We'll adjust this
later to reflect the correct output offsets. */
if (elf_section_data (input_section)->sec_info_type != ELF_INFO_TYPE_STABS)
if (input_section->sec_info_type != ELF_INFO_TYPE_STABS)
{
outrel[1].r_offset = rel[1].r_offset;
outrel[2].r_offset = rel[2].r_offset;
@ -6353,7 +6353,7 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
input_bfd, contents);
l &= lo16_howto->src_mask;
l <<= lo16_howto->rightshift;
l = mips_elf_sign_extend (l, 16);
l = _bfd_mips_elf_sign_extend (l, 16);
addend <<= 16;

View File

@ -108,6 +108,7 @@ extern bfd_reloc_status_type _bfd_mips_elf32_gprel16_reloc
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
extern unsigned long _bfd_elf_mips_mach
PARAMS ((flagword));
extern bfd_boolean _bfd_mips_relax_section (bfd *, asection *,
struct bfd_link_info *,
bfd_boolean *);
extern bfd_boolean _bfd_mips_relax_section
PARAMS ((bfd *, asection *, struct bfd_link_info *, bfd_boolean *));
extern bfd_vma _bfd_mips_elf_sign_extend
PARAMS ((bfd_vma, int));

View File

@ -1,3 +1,14 @@
2003-06-11 Thiemo Seufer <seufer@csv.ica.uni-stuttgart.de>
* 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.
2003-06-11 Thiemo Seufer <seufer@csv.ica.uni-stuttgart.de>
* write.c (write_relocs): Use xcalloc. Fix relocs initialization

View File

@ -11381,13 +11381,16 @@ long
md_pcrel_from (fixP)
fixS *fixP;
{
if (OUTPUT_FLAVOR != bfd_target_aout_flavour
&& fixP->fx_addsy != (symbolS *) NULL
&& ! S_IS_DEFINED (fixP->fx_addsy))
return 4;
/* Return the address of the delay slot. */
return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address;
valueT addr = fixP->fx_where + fixP->fx_frag->fr_address;
switch (fixP->fx_r_type)
{
case BFD_RELOC_16_PCREL_S2:
case BFD_RELOC_MIPS_JMP:
/* Return the address of the delay slot. */
return addr + 4;
default:
return addr;
}
}
/* This is called before the symbol table is processed. In order to
@ -11648,133 +11651,79 @@ md_apply_fix3 (fixP, valP, seg)
{
bfd_byte *buf;
long insn;
valueT value;
static int previous_fx_r_type = 0;
reloc_howto_type *howto;
/* FIXME: Maybe just return for all reloc types not listed below?
Eric Christopher says: "This is stupid, please rewrite md_apply_fix3. */
if (fixP->fx_r_type == BFD_RELOC_8)
return;
/* We ignore generic BFD relocations we don't know about. */
howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
if (! howto)
return;
assert (fixP->fx_size == 4
|| fixP->fx_r_type == BFD_RELOC_16
|| fixP->fx_r_type == BFD_RELOC_32
|| fixP->fx_r_type == BFD_RELOC_MIPS_JMP
|| fixP->fx_r_type == BFD_RELOC_HI16_S
|| fixP->fx_r_type == BFD_RELOC_LO16
|| fixP->fx_r_type == BFD_RELOC_GPREL16
|| fixP->fx_r_type == BFD_RELOC_MIPS_LITERAL
|| fixP->fx_r_type == BFD_RELOC_GPREL32
|| fixP->fx_r_type == BFD_RELOC_64
|| fixP->fx_r_type == BFD_RELOC_CTOR
|| fixP->fx_r_type == BFD_RELOC_MIPS_SUB
|| fixP->fx_r_type == BFD_RELOC_MIPS_HIGHEST
|| fixP->fx_r_type == BFD_RELOC_MIPS_HIGHER
|| fixP->fx_r_type == BFD_RELOC_MIPS_SCN_DISP
|| fixP->fx_r_type == BFD_RELOC_MIPS_REL16
|| fixP->fx_r_type == BFD_RELOC_MIPS_RELGOT
|| fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
|| fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY
|| fixP->fx_r_type == BFD_RELOC_MIPS_JALR);
|| fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY);
value = *valP;
buf = (bfd_byte *) (fixP->fx_frag->fr_literal + fixP->fx_where);
/* If we aren't adjusting this fixup to be against the section
symbol, we need to adjust the value. */
#ifdef OBJ_ELF
if (fixP->fx_addsy != NULL && OUTPUT_FLAVOR == bfd_target_elf_flavour)
{
if (mips_need_elf_addend_fixup (fixP))
if (mips_need_elf_addend_fixup (fixP)
&& howto->partial_inplace
&& fixP->fx_r_type != BFD_RELOC_GPREL16
&& fixP->fx_r_type != BFD_RELOC_GPREL32
&& fixP->fx_r_type != BFD_RELOC_MIPS16_GPREL)
{
reloc_howto_type *howto;
valueT symval = S_GET_VALUE (fixP->fx_addsy);
/* In this case, the bfd_install_relocation routine will
incorrectly add the symbol value back in. We just want
the addend to appear in the object file.
value -= symval;
The condition above used to include
"&& (! fixP->fx_pcrel || howto->pcrel_offset)".
howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
if (value != 0 && howto && howto->partial_inplace)
{
/* In this case, the bfd_install_relocation routine will
incorrectly add the symbol value back in. We just want
the addend to appear in the object file.
However, howto can't be trusted here, because we
might change the reloc type in tc_gen_reloc. We can
check howto->partial_inplace because that conversion
happens to preserve howto->partial_inplace; but it
does not preserve howto->pcrel_offset. I've just
eliminated the check, because all MIPS PC-relative
relocations are marked howto->pcrel_offset.
The condition above used to include
"&& (! fixP->fx_pcrel || howto->pcrel_offset)".
howto->pcrel_offset was originally added for
R_MIPS_PC16, which is generated for code like
However, howto can't be trusted here, because we
might change the reloc type in tc_gen_reloc. We can
check howto->partial_inplace because that conversion
happens to preserve howto->partial_inplace; but it
does not preserve howto->pcrel_offset. I've just
eliminated the check, because all MIPS PC-relative
relocations are marked howto->pcrel_offset.
howto->pcrel_offset was originally added for
R_MIPS_PC16, which is generated for code like
globl g1 .text
.text
.space 20
g1:
x:
bal g1
*/
value -= symval;
/* Make sure the addend is still non-zero. If it became zero
after the last operation, set it to a spurious value and
subtract the same value from the object file's contents. */
if (value == 0)
{
value = 8;
/* The in-place addends for LO16 relocations are signed;
leave the matching HI16 in-place addends as zero. */
if (fixP->fx_r_type != BFD_RELOC_HI16_S)
{
bfd_vma contents, mask, field;
contents = bfd_get_bits (fixP->fx_frag->fr_literal
+ fixP->fx_where,
fixP->fx_size * 8,
target_big_endian);
/* MASK has bits set where the relocation should go.
FIELD is -value, shifted into the appropriate place
for this relocation. */
mask = 1 << (howto->bitsize - 1);
mask = (((mask - 1) << 1) | 1) << howto->bitpos;
field = (-value >> howto->rightshift) << howto->bitpos;
bfd_put_bits ((field & mask) | (contents & ~mask),
fixP->fx_frag->fr_literal + fixP->fx_where,
fixP->fx_size * 8,
target_big_endian);
}
}
}
globl g1 .text
.text
.space 20
g1:
x:
bal g1
*/
*valP -= S_GET_VALUE (fixP->fx_addsy);
}
/* This code was generated using trial and error and so is
fragile and not trustworthy. If you change it, you should
rerun the elf-rel, elf-rel2, and empic testcases and ensure
they still pass. */
if (fixP->fx_pcrel || fixP->fx_subsy != NULL)
if (fixP->fx_pcrel)
{
value += fixP->fx_frag->fr_address + fixP->fx_where;
*valP += fixP->fx_frag->fr_address + fixP->fx_where;
/* BFD's REL handling, for MIPS, is _very_ weird.
This gives the right results, but it can't possibly
be the way things are supposed to work. */
if (fixP->fx_r_type != BFD_RELOC_16_PCREL_S2
|| S_GET_SEGMENT (fixP->fx_addsy) != undefined_section)
value += fixP->fx_frag->fr_address + fixP->fx_where;
*valP += fixP->fx_frag->fr_address + fixP->fx_where;
}
}
#endif
fixP->fx_addnumber = value; /* Remember value for tc_gen_reloc. */
/* We are not done if this is a composite relocation to set up gp. */
if (fixP->fx_addsy == NULL && ! fixP->fx_pcrel
&& !(fixP->fx_r_type == BFD_RELOC_MIPS_SUB
@ -11827,15 +11776,13 @@ md_apply_fix3 (fixP, valP, seg)
/* We currently always generate a reloc against a symbol, which
means that we don't want an addend even if the symbol is
defined. */
fixP->fx_addnumber = 0;
*valP = 0;
break;
case BFD_RELOC_PCREL_HI16_S:
/* The addend for this is tricky if it is internal, so we just
do everything here rather than in bfd_install_relocation. */
if (OUTPUT_FLAVOR == bfd_target_elf_flavour
&& !fixP->fx_done
&& value != 0)
if (OUTPUT_FLAVOR == bfd_target_elf_flavour && !fixP->fx_done)
break;
if (fixP->fx_addsy
&& (symbol_get_bfdsym (fixP->fx_addsy)->flags & BSF_SECTION_SYM) == 0)
@ -11843,30 +11790,26 @@ md_apply_fix3 (fixP, valP, seg)
/* For an external symbol adjust by the address to make it
pcrel_offset. We use the address of the RELLO reloc
which follows this one. */
value += (fixP->fx_next->fx_frag->fr_address
*valP += (fixP->fx_next->fx_frag->fr_address
+ fixP->fx_next->fx_where);
}
value = ((value + 0x8000) >> 16) & 0xffff;
buf = (bfd_byte *) fixP->fx_frag->fr_literal + fixP->fx_where;
*valP = ((*valP + 0x8000) >> 16) & 0xffff;
if (target_big_endian)
buf += 2;
md_number_to_chars ((char *) buf, value, 2);
md_number_to_chars ((char *) buf, *valP, 2);
break;
case BFD_RELOC_PCREL_LO16:
/* The addend for this is tricky if it is internal, so we just
do everything here rather than in bfd_install_relocation. */
if (OUTPUT_FLAVOR == bfd_target_elf_flavour
&& !fixP->fx_done
&& value != 0)
if (OUTPUT_FLAVOR == bfd_target_elf_flavour && !fixP->fx_done)
break;
if (fixP->fx_addsy
&& (symbol_get_bfdsym (fixP->fx_addsy)->flags & BSF_SECTION_SYM) == 0)
value += fixP->fx_frag->fr_address + fixP->fx_where;
buf = (bfd_byte *) fixP->fx_frag->fr_literal + fixP->fx_where;
*valP += fixP->fx_frag->fr_address + fixP->fx_where;
if (target_big_endian)
buf += 2;
md_number_to_chars ((char *) buf, value, 2);
md_number_to_chars ((char *) buf, *valP, 2);
break;
case BFD_RELOC_64:
@ -11876,24 +11819,19 @@ md_apply_fix3 (fixP, valP, seg)
|| (mips_pic == EMBEDDED_PIC && SWITCH_TABLE (fixP)))
{
if (8 <= sizeof (valueT))
md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
value, 8);
md_number_to_chars (buf, *valP, 8);
else
{
long w1, w2;
long hiv;
valueT hiv;
w1 = w2 = fixP->fx_where;
if (target_big_endian)
w1 += 4;
else
w2 += 4;
md_number_to_chars (fixP->fx_frag->fr_literal + w1, value, 4);
if ((value & 0x80000000) != 0)
if ((*valP & 0x80000000) != 0)
hiv = 0xffffffff;
else
hiv = 0;
md_number_to_chars (fixP->fx_frag->fr_literal + w2, hiv, 4);
md_number_to_chars ((char *)(buf + target_big_endian ? 4 : 0),
*valP, 4);
md_number_to_chars ((char *)(buf + target_big_endian ? 0 : 4),
hiv, 4);
}
}
break;
@ -11907,8 +11845,7 @@ md_apply_fix3 (fixP, valP, seg)
entry. */
if (fixP->fx_done
|| (mips_pic == EMBEDDED_PIC && SWITCH_TABLE (fixP)))
md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
value, 4);
md_number_to_chars (buf, *valP, 4);
break;
case BFD_RELOC_16:
@ -11916,8 +11853,7 @@ md_apply_fix3 (fixP, valP, seg)
value now. */
assert (fixP->fx_size == 2);
if (fixP->fx_done)
md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
value, 2);
md_number_to_chars (buf, *valP, 2);
break;
case BFD_RELOC_LO16:
@ -11925,82 +11861,69 @@ md_apply_fix3 (fixP, valP, seg)
up deleting a LO16 reloc. See the 'o' case in mips_ip. */
if (fixP->fx_done)
{
if (value + 0x8000 > 0xffff)
if (*valP + 0x8000 > 0xffff)
as_bad_where (fixP->fx_file, fixP->fx_line,
_("relocation overflow"));
buf = (bfd_byte *) fixP->fx_frag->fr_literal + fixP->fx_where;
if (target_big_endian)
buf += 2;
md_number_to_chars ((char *) buf, value, 2);
md_number_to_chars ((char *) buf, *valP, 2);
}
break;
case BFD_RELOC_16_PCREL_S2:
if ((value & 0x3) != 0)
if ((*valP & 0x3) != 0)
as_bad_where (fixP->fx_file, fixP->fx_line,
_("Branch to odd address (%lx)"), (long) value);
_("Branch to odd address (%lx)"), (long) *valP);
/*
* We need to save the bits in the instruction since fixup_segment()
* might be deleting the relocation entry (i.e., a branch within
* the current segment).
*/
if (!fixP->fx_done && (value != 0 || HAVE_NEWABI))
if (! fixP->fx_done)
break;
/* If 'value' is zero, the remaining reloc code won't actually
do the store, so it must be done here. This is probably
a bug somewhere. */
if (!fixP->fx_done
&& (fixP->fx_r_type != BFD_RELOC_16_PCREL_S2
|| fixP->fx_addsy == NULL /* ??? */
|| ! S_IS_DEFINED (fixP->fx_addsy)))
value -= fixP->fx_frag->fr_address + fixP->fx_where;
value = (offsetT) value >> 2;
/* update old instruction data */
buf = (bfd_byte *) (fixP->fx_where + fixP->fx_frag->fr_literal);
if (target_big_endian)
insn = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
else
insn = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
if (value + 0x8000 <= 0xffff)
insn |= value & 0xffff;
else
if (*valP + 0x20000 <= 0x3ffff)
{
insn |= (*valP >> 2) & 0xffff;
md_number_to_chars ((char *) buf, (valueT) insn, 4);
}
else if (mips_pic == NO_PIC
&& fixP->fx_done
&& fixP->fx_frag->fr_address >= text_section->vma
&& (fixP->fx_frag->fr_address
< text_section->vma + text_section->_raw_size)
&& ((insn & 0xffff0000) == 0x10000000 /* beq $0,$0 */
|| (insn & 0xffff0000) == 0x04010000 /* bgez $0 */
|| (insn & 0xffff0000) == 0x04110000)) /* bgezal $0 */
{
/* The branch offset is too large. If this is an
unconditional branch, and we are not generating PIC code,
we can convert it to an absolute jump instruction. */
if (mips_pic == NO_PIC
&& fixP->fx_done
&& fixP->fx_frag->fr_address >= text_section->vma
&& (fixP->fx_frag->fr_address
< text_section->vma + text_section->_raw_size)
&& ((insn & 0xffff0000) == 0x10000000 /* beq $0,$0 */
|| (insn & 0xffff0000) == 0x04010000 /* bgez $0 */
|| (insn & 0xffff0000) == 0x04110000)) /* bgezal $0 */
{
if ((insn & 0xffff0000) == 0x04110000) /* bgezal $0 */
insn = 0x0c000000; /* jal */
else
insn = 0x08000000; /* j */
fixP->fx_r_type = BFD_RELOC_MIPS_JMP;
fixP->fx_done = 0;
fixP->fx_addsy = section_symbol (text_section);
fixP->fx_addnumber = (value << 2) + md_pcrel_from (fixP);
}
if ((insn & 0xffff0000) == 0x04110000) /* bgezal $0 */
insn = 0x0c000000; /* jal */
else
{
/* If we got here, we have branch-relaxation disabled,
and there's nothing we can do to fix this instruction
without turning it into a longer sequence. */
as_bad_where (fixP->fx_file, fixP->fx_line,
_("Branch out of range"));
}
insn = 0x08000000; /* j */
fixP->fx_r_type = BFD_RELOC_MIPS_JMP;
fixP->fx_done = 0;
fixP->fx_addsy = section_symbol (text_section);
*valP += md_pcrel_from (fixP);
md_number_to_chars ((char *) buf, (valueT) insn, 4);
}
else
{
/* If we got here, we have branch-relaxation disabled,
and there's nothing we can do to fix this instruction
without turning it into a longer sequence. */
as_bad_where (fixP->fx_file, fixP->fx_line,
_("Branch out of range"));
}
md_number_to_chars ((char *) buf, (valueT) insn, 4);
break;
case BFD_RELOC_VTABLE_INHERIT:
@ -12018,6 +11941,9 @@ md_apply_fix3 (fixP, valP, seg)
default:
internalError ();
}
/* Remember value for tc_gen_reloc. */
fixP->fx_addnumber = *valP;
}
#if 0
@ -13864,7 +13790,7 @@ tc_gen_reloc (section, fixp)
reloc2->address = (reloc->address
+ (RELAX_RELOC2 (fixp->fx_frag->fr_subtype)
- RELAX_RELOC1 (fixp->fx_frag->fr_subtype)));
reloc2->addend = fixp->fx_addnumber
reloc2->addend = fixp->fx_addnumber - S_GET_VALUE (fixp->fx_addsy)
+ fixp->fx_frag->tc_frag_data.tc_fr_offset;
reloc2->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_LO16);
assert (reloc2->howto != NULL);
@ -13969,27 +13895,6 @@ tc_gen_reloc (section, fixp)
}
}
#ifdef OBJ_ELF
/* md_apply_fix3 has a double-subtraction hack to get
bfd_install_relocation to behave nicely. GPREL relocations are
handled correctly without this hack, so undo it here. We can't
stop md_apply_fix3 from subtracting twice in the first place since
the fake addend is required for variant frags above. */
if (fixp->fx_addsy != NULL && OUTPUT_FLAVOR == bfd_target_elf_flavour
&& (code == BFD_RELOC_GPREL16 || code == BFD_RELOC_MIPS16_GPREL)
&& reloc->addend != 0
&& mips_need_elf_addend_fixup (fixp))
{
/* If howto->partial_inplace is false, md_apply_fix3 will only
subtract it once. */
reloc_howto_type *howto;
howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
if (howto->partial_inplace)
reloc->addend += S_GET_VALUE (fixp->fx_addsy);
}
#endif
/* To support a PC relative reloc when generating embedded PIC code
for ECOFF, we use a Cygnus extension. We check for that here to
make sure that we don't let such a reloc escape normally. */

View File

@ -129,6 +129,9 @@ extern void mips_frob_file_after_relocs PARAMS ((void));
#define tc_fix_adjustable(fixp) mips_fix_adjustable (fixp)
extern int mips_fix_adjustable PARAMS ((struct fix *));
/* Values passed to md_apply_fix3 don't include symbol values. */
#define MD_APPLY_SYM_VALUE(FIX) 0
/* Global syms must not be resolved, to support ELF shared libraries.
When generating embedded code, we don't have shared libs. */
#define EXTERN_FORCE_RELOC \