(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.
+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]):
#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
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 */
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 */
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 */
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 */
/* 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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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
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;
}
/* 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
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
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;
/* 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)
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");
}
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);
}
bfd_vma gp;
{
bfd_vma relocation;
- unsigned long val;
+ bfd_vma val;
if (bfd_is_com_section (symbol->section))
relocation = 0;
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
|| (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;
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;
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;
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);
-
- /* 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);
-
- ret = _bfd_mips_elf_gprel16_with_gp (abfd, symbol, reloc_entry,
- input_section, relocateable, data, gp);
-
- 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 (bfd_is_com_section (symbol->section))
+ relocation = 0;
+ else
+ relocation = symbol->value;
- return ret;
+ 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);
+ }
+
+ _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. */
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;
}
/* 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);
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;
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;
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");
}
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
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
|| (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;
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;
}
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;
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);
-
- /* 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);
-
- ret = _bfd_mips_elf_gprel16_with_gp (abfd, symbol, reloc_entry,
- input_section, relocateable, data, gp);
-
- 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 (bfd_is_com_section (symbol->section))
+ relocation = 0;
+ else
+ relocation = symbol->value;
- return ret;
+ 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);
+ }
+
+ _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;
}
\f
/* A mapping from BFD reloc types to MIPS ELF reloc types. */
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);
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");
{
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)
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)
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);
-
- /* 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);
-
- ret = _bfd_mips_elf_gprel16_with_gp (abfd, symbol, reloc_entry,
- input_section, relocateable, data, gp);
-
- 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 (bfd_is_com_section (symbol->section))
+ relocation = 0;
+ else
+ relocation = symbol->value;
- return ret;
+ 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);
+ }
+
+ _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
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));
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;
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
+ val = reloc_entry->addend;
+
+ 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. */
|| (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;
\f
/* 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;
{
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;
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;
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;
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
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;
/* 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;
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;
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));
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
in the RELOC_EXPANSION_POSSIBLE case.
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
{
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))
- {
- 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)
- {
- /* 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.
-
- The condition above used to include
- "&& (! fixP->fx_pcrel || howto->pcrel_offset)".
-
- 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);
- }
- }
- }
+ 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
+ the addend to appear in the object file.
+
+ The condition above used to include
+ "&& (! fixP->fx_pcrel || howto->pcrel_offset)".
+
+ 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
+ */
+ *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
/* 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)
/* 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:
|| (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;
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:
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:
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:
default:
internalError ();
}
+
+ /* Remember value for tc_gen_reloc. */
+ fixP->fx_addnumber = *valP;
}
#if 0
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);
}
}
-#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. */
#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 \