* 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,7 +955,7 @@ 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,
return mips_elf_generic_reloc (abfd, reloc_entry, symbol, data,
input_section, output_bfd, error_message);
}
@ -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 ();
}
/* 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,20 +1171,17 @@ 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);
}
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;
}
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,7 +1256,7 @@ 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,
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;
if (bfd_is_com_section (symbol->section))
relocation = 0;
else
relocation = symbol->value;
relocation += symbol->section->output_section->vma;
relocation += symbol->section->output_offset;
/* Set val to the offset into the section or symbol. */
val = reloc_entry->addend;
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);
}
/* 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);
_bfd_mips_elf_sign_extend(val, 16);
ret = _bfd_mips_elf_gprel16_with_gp (abfd, symbol, reloc_entry,
input_section, relocateable, data, gp);
/* 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;
final = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
if (reloc_entry->howto->partial_inplace)
{
bfd_put_16 (abfd,
(bfd_vma) ((extend & 0xf800)
| ((final >> 11) & 0x1f)
| (final & 0x7e0)),
| ((val >> 11) & 0x1f)
| (val & 0x7e0)),
(bfd_byte *) data + reloc_entry->address);
bfd_put_16 (abfd,
(bfd_vma) ((insn & 0xffe0)
| (final & 0x1f)),
| (val & 0x1f)),
(bfd_byte *) data + reloc_entry->address + 2);
}
else
reloc_entry->addend = val;
return ret;
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->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,20 +1719,17 @@ 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);
}
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;
}
if (bfd_is_com_section (symbol->section))
relocation = 0;
@ -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;
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;
if (bfd_is_com_section (symbol->section))
relocation = 0;
else
relocation = symbol->value;
relocation += symbol->section->output_section->vma;
relocation += symbol->section->output_offset;
/* Set val to the offset into the section or symbol. */
val = reloc_entry->addend;
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);
}
/* 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);
_bfd_mips_elf_sign_extend(val, 16);
ret = _bfd_mips_elf_gprel16_with_gp (abfd, symbol, reloc_entry,
input_section, relocateable, data, gp);
/* 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;
final = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
if (reloc_entry->howto->partial_inplace)
{
bfd_put_16 (abfd,
(bfd_vma) ((extend & 0xf800)
| ((final >> 11) & 0x1f)
| (final & 0x7e0)),
| ((val >> 11) & 0x1f)
| (val & 0x7e0)),
(bfd_byte *) data + reloc_entry->address);
bfd_put_16 (abfd,
(bfd_vma) ((insn & 0xffe0)
| (final & 0x1f)),
| (val & 0x1f)),
(bfd_byte *) data + reloc_entry->address + 2);
}
else
reloc_entry->addend = val;
return ret;
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;
if (bfd_is_com_section (symbol->section))
relocation = 0;
else
relocation = symbol->value;
relocation += symbol->section->output_section->vma;
relocation += symbol->section->output_offset;
/* Set val to the offset into the section or symbol. */
val = reloc_entry->addend;
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);
}
/* 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);
_bfd_mips_elf_sign_extend(val, 16);
ret = _bfd_mips_elf_gprel16_with_gp (abfd, symbol, reloc_entry,
input_section, relocateable, data, gp);
/* 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;
final = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
if (reloc_entry->howto->partial_inplace)
{
bfd_put_16 (abfd,
(bfd_vma) ((extend & 0xf800)
| ((final >> 11) & 0x1f)
| (final & 0x7e0)),
| ((val >> 11) & 0x1f)
| (val & 0x7e0)),
(bfd_byte *) data + reloc_entry->address);
bfd_put_16 (abfd,
(bfd_vma) ((insn & 0xffe0)
| (final & 0x1f)),
| (val & 0x1f)),
(bfd_byte *) data + reloc_entry->address + 2);
}
else
reloc_entry->addend = val;
return ret;
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)
{
/* This case occurs with the 64-bit MIPS ELF ABI. */
val = reloc_entry->addend;
}
else
if (reloc_entry->howto->partial_inplace)
{
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;
if (reloc_entry->howto->partial_inplace)
{
insn = (insn & ~0xffff) | (val & 0xffff);
bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address);
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;
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 fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address;
return addr + 4;
default:
return addr;
}
}
/* This is called before the symbol table is processed. In order to
@ -11648,51 +11651,34 @@ 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)
/* 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))
{
reloc_howto_type *howto;
valueT symval = S_GET_VALUE (fixP->fx_addsy);
value -= symval;
howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
if (value != 0 && howto && howto->partial_inplace)
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)
{
/* In this case, the bfd_install_relocation routine will
incorrectly add the symbol value back in. We just want
@ -11719,62 +11705,25 @@ md_apply_fix3 (fixP, valP, seg)
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);
}
}
}
*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,54 +11861,40 @@ 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)
{
/* 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
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
@ -11981,6 +11903,9 @@ md_apply_fix3 (fixP, valP, seg)
|| (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 ((insn & 0xffff0000) == 0x04110000) /* bgezal $0 */
insn = 0x0c000000; /* jal */
else
@ -11988,7 +11913,8 @@ md_apply_fix3 (fixP, valP, seg)
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);
*valP += md_pcrel_from (fixP);
md_number_to_chars ((char *) buf, (valueT) insn, 4);
}
else
{
@ -11998,9 +11924,6 @@ md_apply_fix3 (fixP, valP, seg)
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 \