mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2024-11-24 12:39:59 +00:00
* 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:
parent
cd90e54f8f
commit
a7ebbfdf67
@ -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]):
|
||||
|
233
bfd/elf32-mips.c
233
bfd/elf32-mips.c
@ -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. */
|
||||
|
158
bfd/elf64-mips.c
158
bfd/elf64-mips.c
@ -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. */
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
|
@ -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. */
|
||||
|
@ -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 \
|
||||
|
Loading…
Reference in New Issue
Block a user