+2003-12-18 Richard Sandiford <rsandifo@redhat.com>
+
+ * elf32-mips.c (elf_mips_howto_table_rel): Replace all uses of
+ mips_elf_generic_reloc with _bfd_mips_elf_generic_reloc. Use
+ _bfd_mips_elf_hi16_reloc for R_MIPS_HI16 and R_MIPS_GNU_REL_HI16,
+ _bfd_mips_elf_lo16_reloc for R_MIPS_LO16 and R_MIPS_GNU_REL_LO16,
+ and _bfd_mips_elf_got16_reloc for R_MIPS_GOT16. Change rightshift
+ to 16 for R_MIPS_HI16 and R_MIPS_GNU_REL_HI16.
+ (mips_elf_generic_reloc, struct mips_hi16, mips_elf_hi16_reloc)
+ (mips_elf_lo16_reloc, mips_elf_got16_reloc): Delete.
+ (_bfd_mips_elf32_gprel16_reloc): Remove special case.
+ (mips_elf_gprel32_reloc, mips32_64bit_reloc): Likewise.
+
+ * elf64-mips.c (mips_elf64_howto_table_rel): Replace all uses of
+ mips_elf_generic_reloc with _bfd_mips_elf_generic_reloc. Use
+ _bfd_mips_elf_hi16_reloc for R_MIPS_HI16, _bfd_mips_elf_lo16_reloc
+ for R_MIPS_LO16 and _bfd_mips_elf_got16_reloc for R_MIPS_GOT16.
+ Change R_MIPS_HI16's rightshift to 16.
+ (mips_elf64_howto_table_rela): Replace all uses of
+ mips_elf_generic_reloc with _bfd_mips_elf_generic_reloc.
+ Use _bfd_mips_elf_generic_reloc for R_MIPS_GOT16 as well.
+ (mips_elf64_hi16_reloc, mips_elf64_got16_reloc): Delete.
+ (mips_elf64_shift6_reloc): Remove special case. Use
+ _bfd_mips_elf_generic_reloc instead of returning bfd_reloc_continue.
+
+ * elfn32-mips.c (prev_reloc_section): Delete.
+ (prev_reloc_address, prev_reloc_addend): Delete.
+ (elf_mips_howto_table_rel, elf_mips_howto_table_rela): As for
+ elf64-mips.c
+ (GET_RELOC_ADDEND, SET_RELOC_ADDEND): Delete.
+ (mips_elf_generic_reloc, struct mips_hi16, mips_elf_hi16_reloc)
+ (mips_elf_lo16_reloc, mips_elf_got16_reloc): Delete.
+ (mips_elf_gprel16_reloc): Delete use of GET_RELOC_ADDEND.
+ (mips_elf_literal_reloc, mips_elf_gprel32_reloc): Likewise.
+ (mips16_jump_reloc, mips16_gprel_reloc): Likewise.
+ (mips_elf_shift6_reloc): Likewise. Delete use of SET_RELOC_ADDEND.
+
+ * elfxx-mips.c (_bfd_mips_elf_gprel16_with_gp): Use
+ _bfd_relocate_contents to install an in-place addend.
+ (mips_hi16): New structure.
+ (mips_hi16_list): Moved from elf32-mips.c.
+ (_bfd_mips_elf_hi16_reloc, _bfd_mips_elf_got16_reloc): New functions.
+ (_bfd_mips_elf_lo16_reloc, _bfd_mips_elf_generic_reloc): New functions.
+ (mips_elf_calculate_relocation): Assume addend is unshifted.
+ (_bfd_mips_elf_relocate_section): Don't apply the howto rightshift
+ on top of the usual high-part shift. Don't shift the addend right
+ before calling mips_elf_calculate_relocation.
+
+ * elfxx-mips.h (_bfd_mips_elf_hi16_reloc): Declare.
+ (_bfd_mips_elf_got16_reloc, _bfd_mips_elf_lo16_reloc): Declare.
+ (_bfd_mips_elf_generic_reloc): Declare.
+
2003-12-16 Eric Youngdale <eric@mkssoftware.com>
Nick Clifton <nickc@redhat.com>
#define ECOFF_SIGNED_32
#include "ecoffswap.h"
-static bfd_reloc_status_type mips_elf_generic_reloc
- (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
-static bfd_reloc_status_type mips_elf_hi16_reloc
- (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
-static bfd_reloc_status_type mips_elf_lo16_reloc
- (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
-static bfd_reloc_status_type mips_elf_got16_reloc
- (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
static bfd_reloc_status_type gprel32_with_gp
(bfd *, asymbol *, arelent *, asection *, bfd_boolean, void *, bfd_vma);
static bfd_reloc_status_type mips_elf_gprel32_reloc
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_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 */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_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 */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_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 */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_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. */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_26", /* name */
TRUE, /* partial_inplace */
0x03ffffff, /* src_mask */
/* High 16 bits of symbol value. */
HOWTO (R_MIPS_HI16, /* type */
- 0, /* rightshift */
+ 16, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- mips_elf_hi16_reloc, /* special_function */
+ _bfd_mips_elf_hi16_reloc, /* special_function */
"R_MIPS_HI16", /* name */
TRUE, /* partial_inplace */
0x0000ffff, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- mips_elf_lo16_reloc, /* special_function */
+ _bfd_mips_elf_lo16_reloc, /* special_function */
"R_MIPS_LO16", /* name */
TRUE, /* partial_inplace */
0x0000ffff, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
- mips_elf_got16_reloc, /* special_function */
+ _bfd_mips_elf_got16_reloc, /* special_function */
"R_MIPS_GOT16", /* name */
TRUE, /* partial_inplace */
0x0000ffff, /* src_mask */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_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 */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_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 */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_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 */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_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 */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_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 */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_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 */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_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 */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_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 */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_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 */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_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 */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_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 */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_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 */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_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 */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_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 */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_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 */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_JALR", /* name */
FALSE, /* partial_inplace */
0x00000000, /* src_mask */
/* High 16 bits of symbol value, pc-relative. */
static reloc_howto_type elf_mips_gnu_rel_hi16 =
HOWTO (R_MIPS_GNU_REL_HI16, /* type */
- 0, /* rightshift */
+ 16, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- mips_elf_hi16_reloc, /* special_function */
+ _bfd_mips_elf_hi16_reloc, /* special_function */
"R_MIPS_GNU_REL_HI16", /* name */
TRUE, /* partial_inplace */
0xffff, /* src_mask */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- mips_elf_lo16_reloc, /* special_function */
+ _bfd_mips_elf_lo16_reloc, /* special_function */
"R_MIPS_GNU_REL_LO16", /* name */
TRUE, /* partial_inplace */
0xffff, /* src_mask */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_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 */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_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 */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_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 (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc_entry,
- asymbol *symbol, void *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 != 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
- actual relocation when we see the LO16.
-
- MIPS ELF requires that the LO16 immediately follow the HI16. As a
- GNU extension, for non-pc-relative relocations, we permit an
- arbitrary number of HI16 relocs to be associated with a single LO16
- reloc. This extension permits gcc to output the HI and LO relocs
- itself.
-
- This cannot be done for PC-relative relocations because both the HI16
- and LO16 parts of the relocations must be done relative to the LO16
- part, and there can be carry to or borrow from the HI16 part. */
-
-struct mips_hi16
-{
- struct mips_hi16 *next;
- bfd_byte *addr;
- bfd_vma addend;
-};
-
-/* FIXME: This should not be a static variable. */
-
-static struct mips_hi16 *mips_hi16_list;
-
-static bfd_reloc_status_type
-mips_elf_hi16_reloc (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc_entry,
- asymbol *symbol, void *data, asection *input_section,
- bfd *output_bfd, char **error_message)
-{
- bfd_reloc_status_type ret;
- bfd_vma relocation;
- struct mips_hi16 *n;
-
- /* 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
- && (symbol->flags & BSF_LOCAL) != 0)
- {
- reloc_entry->address += input_section->output_offset;
- return bfd_reloc_ok;
- }
-
- ret = bfd_reloc_ok;
-
- if (strcmp (bfd_asymbol_name (symbol), "_gp_disp") == 0)
- {
- bfd_boolean relocatable;
- bfd_vma gp;
-
- if (ret == bfd_reloc_undefined)
- abort ();
-
- if (output_bfd != NULL)
- relocatable = TRUE;
- else
- {
- relocatable = FALSE;
- output_bfd = symbol->section->output_section->owner;
- }
-
- ret = mips_elf_final_gp (output_bfd, symbol, relocatable,
- error_message, &gp);
- if (ret != bfd_reloc_ok)
- return ret;
-
- relocation = gp - reloc_entry->address;
- }
- else
- {
- if (bfd_is_und_section (symbol->section) && output_bfd == NULL)
- ret = bfd_reloc_undefined;
-
- if (bfd_is_com_section (symbol->section))
- relocation = 0;
- else
- relocation = symbol->value;
- }
-
- relocation += symbol->section->output_section->vma;
- relocation += symbol->section->output_offset;
- relocation += reloc_entry->addend;
-
- if (reloc_entry->address > input_section->_cooked_size)
- return bfd_reloc_outofrange;
-
- /* Save the information, and let LO16 do the actual relocation. */
- n = bfd_malloc (sizeof *n);
- if (n == NULL)
- return bfd_reloc_outofrange;
- n->addr = (bfd_byte *) data + reloc_entry->address;
- n->addend = relocation;
- n->next = mips_hi16_list;
- mips_hi16_list = n;
-
- if (output_bfd != NULL)
- reloc_entry->address += input_section->output_offset;
-
- return ret;
-}
-
-/* Do a R_MIPS_LO16 relocation. This is a straightforward 16 bit
- inplace relocation; this function exists in order to do the
- R_MIPS_HI16 relocation described above. */
-
-static bfd_reloc_status_type
-mips_elf_lo16_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
- void *data, asection *input_section, bfd *output_bfd,
- char **error_message)
-{
- arelent gp_disp_relent;
-
- if (mips_hi16_list != NULL)
- {
- struct mips_hi16 *l;
-
- l = mips_hi16_list;
- while (l != NULL)
- {
- unsigned long insn;
- unsigned long val;
- unsigned long vallo;
- struct mips_hi16 *next;
-
- if (strcmp (bfd_asymbol_name (symbol), "_gp_disp") == 0)
- {
- gp_disp_relent = *reloc_entry;
- reloc_entry = &gp_disp_relent;
- reloc_entry->addend = l->addend;
- }
- else
- {
- /* Do the HI16 relocation. Note that we actually don't need
- to know anything about the LO16 itself, except where to
- find the low 16 bits of the addend needed by the LO16. */
- insn = bfd_get_32 (abfd, l->addr);
- vallo = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
- /* The low order 16 bits are always treated as a signed
- value. */
- vallo = ((vallo & 0xffff) ^ 0x8000) - 0x8000;
- val = ((insn & 0xffff) << 16) + vallo;
- val += l->addend;
-
- /* If PC-relative, we need to subtract out the address of the LO
- half of the HI/LO. (The actual relocation is relative
- to that instruction.) */
- if (reloc_entry->howto->pc_relative)
- val -= reloc_entry->address;
-
- /* At this point, "val" has the value of the combined HI/LO
- pair. If the low order 16 bits (which will be used for
- the LO16 insn) are negative, then we will need an
- adjustment for the high order 16 bits. */
- val += 0x8000;
- val = (val >> 16) & 0xffff;
-
- insn &= ~ (bfd_vma) 0xffff;
- insn |= val;
- bfd_put_32 (abfd, insn, l->addr);
- }
-
- next = l->next;
- free (l);
- l = next;
- }
-
- mips_hi16_list = NULL;
- }
- else if (strcmp (bfd_asymbol_name (symbol), "_gp_disp") == 0)
- {
- bfd_reloc_status_type ret;
- bfd_vma gp, relocation;
-
- /* FIXME: Does this case ever occur? */
-
- ret = mips_elf_final_gp (output_bfd, symbol, TRUE, error_message, &gp);
- if (ret != bfd_reloc_ok)
- return ret;
-
- relocation = gp - reloc_entry->address;
- relocation += symbol->section->output_section->vma;
- relocation += symbol->section->output_offset;
- relocation += reloc_entry->addend;
-
- if (reloc_entry->address > input_section->_cooked_size)
- return bfd_reloc_outofrange;
-
- gp_disp_relent = *reloc_entry;
- reloc_entry = &gp_disp_relent;
- reloc_entry->addend = relocation - 4;
- }
-
- /* Now do the LO16 reloc in the usual way. */
- 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
- table used for PIC code. If the symbol is an external symbol, the
- instruction is modified to contain the offset of the appropriate
- entry in the global offset table. If the symbol is a section
- symbol, the next reloc is a R_MIPS_LO16 reloc. The two 16 bit
- addends are combined to form the real addend against the section
- symbol; the GOT16 is modified to contain the offset of an entry in
- the global offset table, and the LO16 is modified to offset it
- appropriately. Thus an offset larger than 16 bits requires a
- modified value in the global offset table.
-
- This implementation suffices for the assembler, but the linker does
- not yet know how to create global offset tables. */
-
-static bfd_reloc_status_type
-mips_elf_got16_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
- void *data, asection *input_section, bfd *output_bfd,
- char **error_message)
-{
- /* 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
- && (symbol->flags & BSF_LOCAL) != 0)
- {
- reloc_entry->address += input_section->output_offset;
- return bfd_reloc_ok;
- }
-
- 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
dangerous relocation. */
bfd_reloc_status_type ret;
bfd_vma gp;
- /* 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
- && (symbol->flags & BSF_LOCAL) != 0)
- {
- reloc_entry->address += input_section->output_offset;
- return bfd_reloc_ok;
- }
-
if (output_bfd != NULL)
relocatable = TRUE;
else
bfd_reloc_status_type ret;
bfd_vma gp;
- /* 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
- && (symbol->flags & BSF_LOCAL) != 0)
- {
- *error_message = (char *)
- _("32bits gp relative relocation occurs for an external symbol");
- return bfd_reloc_outofrange;
- }
-
if (output_bfd != NULL)
relocatable = TRUE;
else
sign extension. */
static bfd_reloc_status_type
-mips32_64bit_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
- void *data, asection *input_section, bfd *output_bfd,
- char **error_message)
+mips32_64bit_reloc (bfd *abfd, arelent *reloc_entry,
+ asymbol *symbol ATTRIBUTE_UNUSED,
+ void *data, asection *input_section,
+ bfd *output_bfd, char **error_message)
{
bfd_reloc_status_type r;
arelent reloc32;
unsigned long val;
bfd_size_type addr;
- r = mips_elf_generic_reloc (abfd, reloc_entry, symbol, data,
- input_section, output_bfd, error_message);
- if (r != bfd_reloc_continue)
- return r;
-
/* Do a normal 32 bit relocation on the lower 32 bits. */
reloc32 = *reloc_entry;
if (bfd_big_endian (abfd))
(bfd *, asection *, Elf_Internal_Shdr *, int *, void *);
static void mips_elf64_write_rela
(bfd *, asection *, Elf_Internal_Shdr *, int *, void *);
-static bfd_reloc_status_type mips_elf64_hi16_reloc
- (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
static bfd_reloc_status_type mips_elf64_gprel16_reloc
(bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
static bfd_reloc_status_type mips_elf64_literal_reloc
(bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
static bfd_reloc_status_type mips_elf64_shift6_reloc
(bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
-static bfd_reloc_status_type mips_elf64_got16_reloc
- (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
static bfd_reloc_status_type mips16_jump_reloc
(bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
static bfd_reloc_status_type mips16_gprel_reloc
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ _bfd_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 */
+ _bfd_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 */
+ _bfd_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 */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_REL32", /* name */
TRUE, /* partial_inplace */
0xffffffff, /* src_mask */
/* This needs complex overflow
detection, because the upper 36
bits must match the PC + 4. */
- bfd_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_26", /* name */
TRUE, /* partial_inplace */
0x03ffffff, /* src_mask */
/* High 16 bits of symbol value. */
HOWTO (R_MIPS_HI16, /* type */
- 0, /* rightshift */
+ 16, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- mips_elf64_hi16_reloc, /* special_function */
+ _bfd_mips_elf_hi16_reloc, /* special_function */
"R_MIPS_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 */
+ _bfd_mips_elf_lo16_reloc, /* special_function */
"R_MIPS_LO16", /* name */
TRUE, /* partial_inplace */
0x0000ffff, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
- mips_elf64_got16_reloc, /* special_function */
+ _bfd_mips_elf_got16_reloc, /* special_function */
"R_MIPS_GOT16", /* name */
TRUE, /* partial_inplace */
0x0000ffff, /* src_mask */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ _bfd_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 */
+ _bfd_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 */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_SHIFT5", /* name */
TRUE, /* partial_inplace */
0x000007c0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_64", /* name */
TRUE, /* partial_inplace */
MINUS_ONE, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ _bfd_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 */
+ _bfd_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 */
+ _bfd_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 */
+ _bfd_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 */
+ _bfd_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 */
+ _bfd_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 */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_INSERT_A", /* name */
TRUE, /* partial_inplace */
0xffffffff, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_INSERT_B", /* name */
TRUE, /* partial_inplace */
0xffffffff, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_DELETE", /* name */
TRUE, /* partial_inplace */
0xffffffff, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ _bfd_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 */
+ _bfd_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 */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_SCN_DISP", /* name */
TRUE, /* partial_inplace */
0xffffffff, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_REL16", /* name */
TRUE, /* partial_inplace */
0xffff, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_RELGOT", /* name */
TRUE, /* partial_inplace */
0xffffffff, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_JALR", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ _bfd_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 */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_16", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_32", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_REL32", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
/* This needs complex overflow
detection, because the upper 36
bits must match the PC + 4. */
- bfd_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_26", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_HI16", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_LO16", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
- mips_elf64_got16_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_GOT16", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_PC16", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_CALL16", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
6, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_SHIFT5", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_64", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_GOT_DISP", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_GOT_PAGE", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_GOT_OFST", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_GOT_HI16", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_GOT_LO16", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_SUB", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_INSERT_A", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_INSERT_B", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_DELETE", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_HIGHER", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_HIGHEST", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_CALL_HI16", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_CALL_LO16", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_SCN_DISP", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_REL16", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_RELGOT", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_JALR", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_GNU_REL16_S2", /* name */
TRUE, /* partial_inplace */
0x0000ffff, /* src_mask */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_GNU_REL16_S2", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
(Elf64_Mips_External_Rela *) dst);
}
\f
-/* Do a R_MIPS_HI16 relocation. */
-
-static bfd_reloc_status_type
-mips_elf64_hi16_reloc (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc_entry,
- asymbol *symbol, void *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 != NULL
- && (symbol->flags & BSF_SECTION_SYM) == 0
- && (symbol->flags & BSF_LOCAL) != 0)
- {
- reloc_entry->address += input_section->output_offset;
- return bfd_reloc_ok;
- }
-
- if (reloc_entry->howto->partial_inplace)
- {
- if (((reloc_entry->addend & 0xffff) + 0x8000) & ~0xffff)
- reloc_entry->addend += 0x8000;
- }
-
- return bfd_reloc_continue;
-}
-
-/* Do a R_MIPS_GOT16 reloc. This is a reloc against the global offset
- table used for PIC code. If the symbol is an external symbol, the
- instruction is modified to contain the offset of the appropriate
- entry in the global offset table. If the symbol is a section
- symbol, the next reloc is a R_MIPS_LO16 reloc. The two 16 bit
- addends are combined to form the real addend against the section
- symbol; the GOT16 is modified to contain the offset of an entry in
- the global offset table, and the LO16 is modified to offset it
- appropriately. Thus an offset larger than 16 bits requires a
- modified value in the global offset table.
-
- This implementation suffices for the assembler, but the linker does
- not yet know how to create global offset tables. */
-
-static bfd_reloc_status_type
-mips_elf64_got16_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
- void *data, asection *input_section, bfd *output_bfd,
- char **error_message)
-{
- /* If we're relocating, and this is a local symbol, we can handle it
- just like an R_MIPS_HI16. */
- if (output_bfd != NULL
- && ((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);
-
-
- /* Otherwise we try to handle it as R_MIPS_GOT_DISP. */
- return bfd_elf_generic_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
dangerous relocation. */
the rest is at bits 6-10. The bitpos already got right by the howto. */
static bfd_reloc_status_type
-mips_elf64_shift6_reloc (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc_entry,
- asymbol *symbol, void *data ATTRIBUTE_UNUSED,
- asection *input_section, bfd *output_bfd,
- char **error_message ATTRIBUTE_UNUSED)
+mips_elf64_shift6_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
+ void *data, asection *input_section, bfd *output_bfd,
+ char **error_message)
{
- /* 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
- && (symbol->flags & BSF_LOCAL) != 0)
- {
- reloc_entry->address += input_section->output_offset;
- return bfd_reloc_ok;
- }
-
if (reloc_entry->howto->partial_inplace)
{
reloc_entry->addend = ((reloc_entry->addend & 0x00007c0)
| (reloc_entry->addend & 0x00000800) >> 9);
}
- return bfd_reloc_continue;
+ return _bfd_mips_elf_generic_reloc (abfd, reloc_entry, symbol, data,
+ input_section, output_bfd,
+ error_message);
}
/* Handle a mips16 jump. */
#define ECOFF_SIGNED_32
#include "ecoffswap.h"
-static bfd_reloc_status_type mips_elf_generic_reloc
- (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
-static bfd_reloc_status_type mips_elf_hi16_reloc
- (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
-static bfd_reloc_status_type mips_elf_lo16_reloc
- (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
-static bfd_reloc_status_type mips_elf_got16_reloc
- (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
static bfd_boolean mips_elf_assign_gp
(bfd *, bfd_vma *);
static bfd_reloc_status_type mips_elf_final_gp
extern const bfd_target bfd_elf32_nbigmips_vec;
extern const bfd_target bfd_elf32_nlittlemips_vec;
-static asection *prev_reloc_section = NULL;
-static bfd_vma prev_reloc_address = -1;
-static bfd_vma prev_reloc_addend = 0;
-
/* Nonzero if ABFD is using the N32 ABI. */
#define ABI_N32_P(abfd) \
((elf_elfheader (abfd)->e_flags & EF_MIPS_ABI2) != 0)
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_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 */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_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 */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_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 */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_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. */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_26", /* name */
TRUE, /* partial_inplace */
0x03ffffff, /* src_mask */
/* High 16 bits of symbol value. */
HOWTO (R_MIPS_HI16, /* type */
- 0, /* rightshift */
+ 16, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- mips_elf_hi16_reloc, /* special_function */
+ _bfd_mips_elf_hi16_reloc, /* special_function */
"R_MIPS_HI16", /* name */
TRUE, /* partial_inplace */
0x0000ffff, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- mips_elf_lo16_reloc, /* special_function */
+ _bfd_mips_elf_lo16_reloc, /* special_function */
"R_MIPS_LO16", /* name */
TRUE, /* partial_inplace */
0x0000ffff, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
- mips_elf_got16_reloc, /* special_function */
+ _bfd_mips_elf_got16_reloc, /* special_function */
"R_MIPS_GOT16", /* name */
TRUE, /* partial_inplace */
0x0000ffff, /* src_mask */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_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 */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_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 */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_SHIFT5", /* name */
TRUE, /* partial_inplace */
0x000007c0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_64", /* name */
TRUE, /* partial_inplace */
MINUS_ONE, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_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 */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_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 */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_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 */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_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 */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_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 */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_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 */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_INSERT_A", /* name */
TRUE, /* partial_inplace */
0xffffffff, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_INSERT_B", /* name */
TRUE, /* partial_inplace */
0xffffffff, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_DELETE", /* name */
TRUE, /* partial_inplace */
0xffffffff, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_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 */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_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 */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_SCN_DISP", /* name */
TRUE, /* partial_inplace */
0xffffffff, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_REL16", /* name */
TRUE, /* partial_inplace */
0xffff, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_RELGOT", /* name */
TRUE, /* partial_inplace */
0xffffffff, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_JALR", /* name */
FALSE, /* partial_inplace */
0x00000000, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_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 */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_16", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_32", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_REL32", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
/* This needs complex overflow
detection, because the upper 36
bits must match the PC + 4. */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_26", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_HI16", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_LO16", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
- mips_elf_got16_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_GOT16", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_PC16", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_CALL16", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
6, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_SHIFT5", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_64", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_GOT_DISP", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_GOT_PAGE", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_GOT_OFST", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_GOT_HI16", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_GOT_LO16", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_SUB", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_INSERT_A", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_INSERT_B", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_DELETE", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_HIGHER", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_HIGHEST", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_CALL_HI16", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_CALL_LO16", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_SCN_DISP", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_REL16", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_RELGOT", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_JALR", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_GNU_REL16_S2", /* name */
TRUE, /* partial_inplace */
0x0000ffff, /* src_mask */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
- mips_elf_generic_reloc, /* special_function */
+ _bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_GNU_REL16_S2", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
0x0000ffff, /* dst_mask */
TRUE); /* pcrel_offset */
\f
-/* This is derived from bfd_elf_generic_reloc. NewABI allows us to have
- several relocations against the same address. The addend is derived
- from the addends of preceding relocations. If we don't need to
- do something special, we simply keep track of the addend. */
-
-#define GET_RELOC_ADDEND(obfd, sym, entry, sec) \
-{ \
- /* If we're relocating, and this is an external symbol, we don't \
- want to change anything. */ \
- if ((obfd) != NULL \
- && ((sym)->flags & BSF_SECTION_SYM) == 0 \
- && (! (entry)->howto->partial_inplace \
- || (entry)->addend == 0)) \
- { \
- (entry)->address += (sec)->output_offset; \
- return bfd_reloc_ok; \
- } \
- \
- /* The addend of combined relocs is remembered and left for \
- subsequent relocs. */ \
- if (prev_reloc_address != (entry)->address \
- || prev_reloc_section != (sec)) \
- { \
- prev_reloc_section = (sec); \
- prev_reloc_address = (entry)->address; \
- prev_reloc_addend = (entry)->addend; \
- } \
- else \
- (entry)->addend = prev_reloc_addend; \
-}
-
-#define SET_RELOC_ADDEND(entry) \
-{ \
- prev_reloc_addend = (entry)->addend; \
-}
-
-static bfd_reloc_status_type
-mips_elf_generic_reloc (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc_entry,
- asymbol *symbol, void *data ATTRIBUTE_UNUSED,
- asection *input_section, bfd *output_bfd,
- char **error_message ATTRIBUTE_UNUSED)
-{
- GET_RELOC_ADDEND (output_bfd, symbol, reloc_entry, input_section)
-
- return bfd_reloc_continue;
-}
-\f
-/* 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
- actual relocation when we see the LO16.
-
- MIPS ELF requires that the LO16 immediately follow the HI16. As a
- GNU extension, for non-pc-relative relocations, we permit an
- arbitrary number of HI16 relocs to be associated with a single LO16
- reloc. This extension permits gcc to output the HI and LO relocs
- itself.
-
- This cannot be done for PC-relative relocations because both the HI16
- and LO16 parts of the relocations must be done relative to the LO16
- part, and there can be carry to or borrow from the HI16 part. */
-
-struct mips_hi16
-{
- struct mips_hi16 *next;
- bfd_byte *addr;
- bfd_vma addend;
-};
-
-/* FIXME: This should not be a static variable. */
-
-static struct mips_hi16 *mips_hi16_list;
-
-static bfd_reloc_status_type
-mips_elf_hi16_reloc (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc_entry,
- asymbol *symbol, void *data, asection *input_section,
- bfd *output_bfd, char **error_message ATTRIBUTE_UNUSED)
-{
- bfd_reloc_status_type ret;
- bfd_vma relocation;
- struct mips_hi16 *n;
-
- GET_RELOC_ADDEND (output_bfd, symbol, reloc_entry, input_section)
-
- ret = bfd_reloc_ok;
-
- if (bfd_is_und_section (symbol->section) && output_bfd == NULL)
- ret = bfd_reloc_undefined;
-
- if (bfd_is_com_section (symbol->section))
- relocation = 0;
- else
- relocation = symbol->value;
-
- relocation += symbol->section->output_section->vma;
- relocation += symbol->section->output_offset;
- relocation += reloc_entry->addend;
-
- if (reloc_entry->address > input_section->_cooked_size)
- return bfd_reloc_outofrange;
-
- /* Save the information, and let LO16 do the actual relocation. */
- n = bfd_malloc (sizeof *n);
- if (n == NULL)
- return bfd_reloc_outofrange;
- n->addr = (bfd_byte *) data + reloc_entry->address;
- n->addend = relocation;
- n->next = mips_hi16_list;
- mips_hi16_list = n;
-
- if (output_bfd != NULL)
- reloc_entry->address += input_section->output_offset;
-
- return ret;
-}
-
-/* Do a R_MIPS_LO16 relocation. This is a straightforward 16 bit
- inplace relocation; this function exists in order to do the
- R_MIPS_HI16 relocation described above. */
-
-static bfd_reloc_status_type
-mips_elf_lo16_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
- void *data, asection *input_section, bfd *output_bfd,
- char **error_message)
-{
- if (mips_hi16_list != NULL)
- {
- struct mips_hi16 *l;
-
- l = mips_hi16_list;
- while (l != NULL)
- {
- unsigned long insn;
- unsigned long val;
- unsigned long vallo;
- struct mips_hi16 *next;
-
- /* Do the HI16 relocation. Note that we actually don't need
- to know anything about the LO16 itself, except where to
- find the low 16 bits of the addend needed by the LO16. */
- insn = bfd_get_32 (abfd, l->addr);
- vallo = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
-
- /* The low order 16 bits are always treated as a signed
- value. */
- vallo = ((vallo & 0xffff) ^ 0x8000) - 0x8000;
- val = ((insn & 0xffff) << 16) + vallo;
- val += l->addend;
-
- /* If PC-relative, we need to subtract out the address of the LO
- half of the HI/LO. (The actual relocation is relative
- to that instruction.) */
- if (reloc_entry->howto->pc_relative)
- val -= reloc_entry->address;
-
- /* At this point, "val" has the value of the combined HI/LO
- pair. If the low order 16 bits (which will be used for
- the LO16 insn) are negative, then we will need an
- adjustment for the high order 16 bits. */
- val += 0x8000;
- val = (val >> 16) & 0xffff;
-
- insn &= ~ (bfd_vma) 0xffff;
- insn |= val;
- bfd_put_32 (abfd, insn, l->addr);
-
- next = l->next;
- free (l);
- l = next;
- }
-
- mips_hi16_list = NULL;
- }
-
- /* Now do the LO16 reloc in the usual way. */
- 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
- table used for PIC code. If the symbol is an external symbol, the
- instruction is modified to contain the offset of the appropriate
- entry in the global offset table. If the symbol is a section
- symbol, the next reloc is a R_MIPS_LO16 reloc. The two 16 bit
- addends are combined to form the real addend against the section
- symbol; the GOT16 is modified to contain the offset of an entry in
- the global offset table, and the LO16 is modified to offset it
- appropriately. Thus an offset larger than 16 bits requires a
- modified value in the global offset table.
-
- This implementation suffices for the assembler, but the linker does
- not yet know how to create global offset tables. */
-
-static bfd_reloc_status_type
-mips_elf_got16_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
- void *data, asection *input_section, bfd *output_bfd,
- char **error_message)
-{
- /* If we're relocating, and this is a local symbol, we can handle it
- just like an R_MIPS_HI16. */
- if (output_bfd != NULL
- && ((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);
-
- /* Otherwise we try to handle it as R_MIPS_GOT_DISP. */
- return mips_elf_generic_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
dangerous relocation. */
bfd_reloc_status_type ret;
bfd_vma gp;
- GET_RELOC_ADDEND (output_bfd, symbol, reloc_entry, input_section)
-
if (output_bfd != NULL)
relocatable = TRUE;
else
bfd_reloc_status_type ret;
bfd_vma gp;
- GET_RELOC_ADDEND (output_bfd, symbol, reloc_entry, input_section)
-
/* FIXME: The entries in the .lit8 and .lit4 sections should be merged. */
if (output_bfd != NULL)
relocatable = TRUE;
bfd_reloc_status_type ret;
bfd_vma gp;
- GET_RELOC_ADDEND (output_bfd, symbol, reloc_entry, input_section)
-
/* R_MIPS_GPREL32 relocations are defined for local symbols only. */
if (output_bfd != NULL
&& (symbol->flags & BSF_SECTION_SYM) == 0
the rest is at bits 6-10. The bitpos already got right by the howto. */
static bfd_reloc_status_type
-mips_elf_shift6_reloc (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc_entry,
- asymbol *symbol, void *data ATTRIBUTE_UNUSED,
- asection *input_section, bfd *output_bfd,
- char **error_message ATTRIBUTE_UNUSED)
+mips_elf_shift6_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
+ void *data, asection *input_section, bfd *output_bfd,
+ char **error_message)
{
- GET_RELOC_ADDEND (output_bfd, symbol, reloc_entry, input_section)
-
if (reloc_entry->howto->partial_inplace)
{
reloc_entry->addend = ((reloc_entry->addend & 0x00007c0)
| (reloc_entry->addend & 0x00000800) >> 9);
}
- SET_RELOC_ADDEND (reloc_entry)
-
- return bfd_reloc_continue;
+ return _bfd_mips_elf_generic_reloc (abfd, reloc_entry, symbol, data,
+ input_section, output_bfd,
+ error_message);
}
\f
/* Handle a mips16 jump. */
static bfd_reloc_status_type
-mips16_jump_reloc (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc_entry,
- asymbol *symbol, void *data ATTRIBUTE_UNUSED,
- asection *input_section, bfd *output_bfd,
+mips16_jump_reloc (bfd *abfd ATTRIBUTE_UNUSED,
+ arelent *reloc_entry ATTRIBUTE_UNUSED,
+ asymbol *symbol ATTRIBUTE_UNUSED,
+ void *data ATTRIBUTE_UNUSED,
+ asection *input_section, bfd *output_bfd ATTRIBUTE_UNUSED,
char **error_message ATTRIBUTE_UNUSED)
{
static bfd_boolean warned = FALSE;
- GET_RELOC_ADDEND (output_bfd, symbol, reloc_entry, input_section)
-
/* FIXME. */
if (! warned)
(*_bfd_error_handler)
bfd_signed_vma val;
bfd_vma relocation;
- GET_RELOC_ADDEND (output_bfd, symbol, reloc_entry, input_section)
-
if (output_bfd != NULL)
relocatable = TRUE;
else
return bfd_reloc_ok;
}
-
-#undef GET_RELOC_ADDEND
-#undef SET_RELOC_ADDEND
\f
/* A mapping from BFD reloc types to MIPS ELF reloc types. */
bfd_boolean relocatable, void *data, bfd_vma gp)
{
bfd_vma relocation;
- unsigned long insn = 0;
bfd_signed_vma val;
+ bfd_reloc_status_type status;
if (bfd_is_com_section (symbol->section))
relocation = 0;
/* Set val to the offset into the section or symbol. */
val = reloc_entry->addend;
- if (reloc_entry->howto->partial_inplace)
- {
- insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
- val += insn & 0xffff;
- }
-
- _bfd_mips_elf_sign_extend(val, 16);
+ _bfd_mips_elf_sign_extend (val, 16);
/* Adjust val for the final section location and GP value. If we
are producing relocatable output, we don't want to do this for
if (reloc_entry->howto->partial_inplace)
{
- insn = (insn & ~0xffff) | (val & 0xffff);
- bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address);
+ status = _bfd_relocate_contents (reloc_entry->howto, abfd, val,
+ (bfd_byte *) data
+ + reloc_entry->address);
+ if (status != bfd_reloc_ok)
+ return status;
}
else
reloc_entry->addend = val;
if (relocatable)
reloc_entry->address += input_section->output_offset;
- else if (((val & ~0xffff) != ~0xffff) && ((val & ~0xffff) != 0))
- return bfd_reloc_overflow;
+
+ return bfd_reloc_ok;
+}
+
+/* Used to store a REL high-part relocation such as R_MIPS_HI16 or
+ R_MIPS_GOT16. REL is the relocation, INPUT_SECTION is the section
+ that contains the relocation field and DATA points to the start of
+ INPUT_SECTION. */
+
+struct mips_hi16
+{
+ struct mips_hi16 *next;
+ bfd_byte *data;
+ asection *input_section;
+ arelent rel;
+};
+
+/* FIXME: This should not be a static variable. */
+
+static struct mips_hi16 *mips_hi16_list;
+
+/* A howto special_function for REL *HI16 relocations. We can only
+ calculate the correct value once we've seen the partnering
+ *LO16 relocation, so just save the information for later.
+
+ The ABI requires that the *LO16 immediately follow the *HI16.
+ However, as a GNU extension, we permit an arbitrary number of
+ *HI16s to be associated with a single *LO16. This significantly
+ simplies the relocation handling in gcc. */
+
+bfd_reloc_status_type
+_bfd_mips_elf_hi16_reloc (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc_entry,
+ asymbol *symbol ATTRIBUTE_UNUSED, void *data,
+ asection *input_section, bfd *output_bfd,
+ char **error_message ATTRIBUTE_UNUSED)
+{
+ struct mips_hi16 *n;
+
+ if (reloc_entry->address > input_section->_cooked_size)
+ return bfd_reloc_outofrange;
+
+ n = bfd_malloc (sizeof *n);
+ if (n == NULL)
+ return bfd_reloc_outofrange;
+
+ n->next = mips_hi16_list;
+ n->data = data;
+ n->input_section = input_section;
+ n->rel = *reloc_entry;
+ mips_hi16_list = n;
+
+ if (output_bfd != NULL)
+ reloc_entry->address += input_section->output_offset;
+
+ return bfd_reloc_ok;
+}
+
+/* A howto special_function for REL R_MIPS_GOT16 relocations. This is just
+ like any other 16-bit relocation when applied to global symbols, but is
+ treated in the same as R_MIPS_HI16 when applied to local symbols. */
+
+bfd_reloc_status_type
+_bfd_mips_elf_got16_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
+ void *data, asection *input_section,
+ bfd *output_bfd, char **error_message)
+{
+ if ((symbol->flags & (BSF_GLOBAL | BSF_WEAK)) != 0
+ || bfd_is_und_section (bfd_get_section (symbol))
+ || bfd_is_com_section (bfd_get_section (symbol)))
+ /* The relocation is against a global symbol. */
+ return _bfd_mips_elf_generic_reloc (abfd, reloc_entry, symbol, data,
+ input_section, output_bfd,
+ error_message);
+
+ return _bfd_mips_elf_hi16_reloc (abfd, reloc_entry, symbol, data,
+ input_section, output_bfd, error_message);
+}
+
+/* A howto special_function for REL *LO16 relocations. The *LO16 itself
+ is a straightforward 16 bit inplace relocation, but we must deal with
+ any partnering high-part relocations as well. */
+
+bfd_reloc_status_type
+_bfd_mips_elf_lo16_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
+ void *data, asection *input_section,
+ bfd *output_bfd, char **error_message)
+{
+ bfd_vma vallo;
+
+ if (reloc_entry->address > input_section->_cooked_size)
+ return bfd_reloc_outofrange;
+
+ vallo = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
+ while (mips_hi16_list != NULL)
+ {
+ bfd_reloc_status_type ret;
+ struct mips_hi16 *hi;
+
+ hi = mips_hi16_list;
+
+ /* R_MIPS_GOT16 relocations are something of a special case. We
+ want to install the addend in the same way as for a R_MIPS_HI16
+ relocation (with a rightshift of 16). However, since GOT16
+ relocations can also be used with global symbols, their howto
+ has a rightshift of 0. */
+ if (hi->rel.howto->type == R_MIPS_GOT16)
+ hi->rel.howto = MIPS_ELF_RTYPE_TO_HOWTO (abfd, R_MIPS_HI16, FALSE);
+
+ /* VALLO is a signed 16-bit number. Bias it by 0x8000 so that any
+ carry or borrow will induce a change of +1 or -1 in the high part. */
+ hi->rel.addend += (vallo + 0x8000) & 0xffff;
+
+ /* R_MIPS_GNU_REL_HI16 relocations are relative to the address of the
+ lo16 relocation, not their own address. If we're calculating the
+ final value, and hence subtracting the "PC", subtract the offset
+ of the lo16 relocation from here. */
+ if (output_bfd == NULL && hi->rel.howto->type == R_MIPS_GNU_REL_HI16)
+ hi->rel.addend -= reloc_entry->address - hi->rel.address;
+
+ ret = _bfd_mips_elf_generic_reloc (abfd, &hi->rel, symbol, hi->data,
+ hi->input_section, output_bfd,
+ error_message);
+ if (ret != bfd_reloc_ok)
+ return ret;
+
+ mips_hi16_list = hi->next;
+ free (hi);
+ }
+
+ return _bfd_mips_elf_generic_reloc (abfd, reloc_entry, symbol, data,
+ input_section, output_bfd,
+ error_message);
+}
+
+/* A generic howto special_function. This calculates and installs the
+ relocation itself, thus avoiding the oft-discussed problems in
+ bfd_perform_relocation and bfd_install_relocation. */
+
+bfd_reloc_status_type
+_bfd_mips_elf_generic_reloc (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc_entry,
+ asymbol *symbol, void *data ATTRIBUTE_UNUSED,
+ asection *input_section, bfd *output_bfd,
+ char **error_message ATTRIBUTE_UNUSED)
+{
+ bfd_signed_vma val;
+ bfd_reloc_status_type status;
+ bfd_boolean relocatable;
+
+ relocatable = (output_bfd != NULL);
+
+ if (reloc_entry->address > input_section->_cooked_size)
+ return bfd_reloc_outofrange;
+
+ /* Build up the field adjustment in VAL. */
+ val = 0;
+ if (!relocatable || (symbol->flags & BSF_SECTION_SYM) != 0)
+ {
+ /* Either we're calculating the final field value or we have a
+ relocation against a section symbol. Add in the section's
+ offset or address. */
+ val += symbol->section->output_section->vma;
+ val += symbol->section->output_offset;
+ }
+
+ if (!relocatable)
+ {
+ /* We're calculating the final field value. Add in the symbol's value
+ and, if pc-relative, subtract the address of the field itself. */
+ val += symbol->value;
+ if (reloc_entry->howto->pc_relative)
+ {
+ val -= input_section->output_section->vma;
+ val -= input_section->output_offset;
+ val -= reloc_entry->address;
+ }
+ }
+
+ /* VAL is now the final adjustment. If we're keeping this relocation
+ in the output file, and if the relocation uses a separate addend,
+ we just need to add VAL to that addend. Otherwise we need to add
+ VAL to the relocation field itself. */
+ if (relocatable && !reloc_entry->howto->partial_inplace)
+ reloc_entry->addend += val;
+ else
+ {
+ /* Add in the separate addend, if any. */
+ val += reloc_entry->addend;
+
+ /* Add VAL to the relocation field. */
+ status = _bfd_relocate_contents (reloc_entry->howto, abfd, val,
+ (bfd_byte *) data
+ + reloc_entry->address);
+ if (status != bfd_reloc_ok)
+ return status;
+ }
+
+ if (relocatable)
+ reloc_entry->address += input_section->output_offset;
return bfd_reloc_ok;
}
break;
case R_MIPS_GNU_REL16_S2:
- value = symbol + _bfd_mips_elf_sign_extend (addend << 2, 18) - p;
+ value = symbol + _bfd_mips_elf_sign_extend (addend, 18) - p;
overflowed_p = mips_elf_overflow_p (value, 18);
value = (value >> 2) & howto->dst_mask;
break;
R_MIPS_26 case here. */
case R_MIPS_26:
if (local_p)
- value = (((addend << 2) | ((p + 4) & 0xf0000000)) + symbol) >> 2;
+ value = ((addend | ((p + 4) & 0xf0000000)) + symbol) >> 2;
else
- value = (_bfd_mips_elf_sign_extend (addend << 2, 28) + symbol) >> 2;
+ value = (_bfd_mips_elf_sign_extend (addend, 28) + symbol) >> 2;
value &= howto->dst_mask;
break;
addend = mips_elf_obtain_contents (howto, rel, input_bfd,
contents);
addend &= howto->src_mask;
- addend <<= howto->rightshift;
/* For some kinds of relocations, the ADDEND is a
combination of the addend stored in two different
| ((addend & 0x7e00000) >> 16)
| (addend & 0x1f));
}
+ else
+ addend <<= howto->rightshift;
}
else
addend = rel->r_addend;
/* Adjust the addend appropriately. */
addend += local_sections[r_symndx]->output_offset;
- if (howto->partial_inplace)
+ if (rela_relocation_p)
+ /* If this is a RELA relocation, just update the addend. */
+ rel->r_addend = addend;
+ else
{
- /* If the relocation is for a R_MIPS_HI16 or R_MIPS_GOT16,
- then we only want to write out the high-order 16 bits.
- The subsequent R_MIPS_LO16 will handle the low-order bits.
- */
- if (r_type == R_MIPS_HI16 || r_type == R_MIPS_GOT16
+ if (r_type == R_MIPS_HI16
+ || r_type == R_MIPS_GOT16
|| r_type == R_MIPS_GNU_REL_HI16)
addend = mips_elf_high (addend);
else if (r_type == R_MIPS_HIGHER)
addend = mips_elf_higher (addend);
else if (r_type == R_MIPS_HIGHEST)
addend = mips_elf_highest (addend);
- }
+ else
+ addend >>= howto->rightshift;
- if (rela_relocation_p)
- /* If this is a RELA relocation, just update the addend.
- We have to cast away constness for REL. */
- rel->r_addend = addend;
- else
- {
- /* Otherwise, we have to write the value back out. Note
- that we use the source mask, rather than the
- destination mask because the place to which we are
- writing will be source of the addend in the final
- link. */
- addend >>= howto->rightshift;
+ /* We use the source mask, rather than the destination
+ mask because the place to which we are writing will be
+ source of the addend in the final link. */
addend &= howto->src_mask;
if (r_type == R_MIPS_64 && ! NEWABI_P (output_bfd))
else
use_saved_addend_p = FALSE;
- addend >>= howto->rightshift;
-
/* Figure out what value we are supposed to relocate. */
switch (mips_elf_calculate_relocation (output_bfd, input_bfd,
input_section, info, rel,
(bfd *, asymbol *, arelent *, asection *, bfd_boolean, void *, bfd_vma);
extern bfd_reloc_status_type _bfd_mips_elf32_gprel16_reloc
(bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
+extern bfd_reloc_status_type _bfd_mips_elf_hi16_reloc
+ (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
+extern bfd_reloc_status_type _bfd_mips_elf_got16_reloc
+ (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
+extern bfd_reloc_status_type _bfd_mips_elf_lo16_reloc
+ (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
+extern bfd_reloc_status_type _bfd_mips_elf_generic_reloc
+ (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
extern unsigned long _bfd_elf_mips_mach
(flagword);
extern bfd_boolean _bfd_mips_relax_section
+2003-12-18 Richard Sandiford <rsandifo@redhat.com>
+
+ * config/tc-mips.c (mips_need_elf_addend_fixup): Delete.
+ (md_apply_fix3): Remove bfd_install_relocation workarounds.
+ (tc_gen_reloc): Likewise. Factor handling of pc-relative relocations
+ and treat fx_addnumber as relative to the relocation address.
+
2003-12-18 Richard Sandiford <rsandifo@redhat.com>
* config/tc-mips.c (s_change_section): When parsing the MIPS-specific
return 1;
}
-#ifdef OBJ_ELF
-static int
-mips_need_elf_addend_fixup (fixS *fixP)
-{
- if (S_GET_OTHER (fixP->fx_addsy) == STO_MIPS16)
- return 1;
- if (mips_pic == EMBEDDED_PIC
- && S_IS_WEAK (fixP->fx_addsy))
- return 1;
- if (mips_pic != EMBEDDED_PIC
- && (S_IS_WEAK (fixP->fx_addsy)
- || S_IS_EXTERNAL (fixP->fx_addsy))
- && !S_IS_COMMON (fixP->fx_addsy))
- return 1;
- if (((bfd_get_section_flags (stdoutput,
- S_GET_SEGMENT (fixP->fx_addsy))
- & (SEC_LINK_ONCE | SEC_MERGE)) != 0)
- || !strncmp (segment_name (S_GET_SEGMENT (fixP->fx_addsy)),
- ".gnu.linkonce",
- sizeof (".gnu.linkonce") - 1))
- return 1;
- return 0;
-}
-#endif
-
/* Apply a fixup to the object file. */
void
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)
- && 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)
- {
- *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. */
- *valP += fixP->fx_frag->fr_address + fixP->fx_where;
- }
- }
-#endif
-
/* 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
as_fatal (_("Double check fx_r_type in tc-mips.c:tc_gen_reloc"));
fixp->fx_r_type = BFD_RELOC_GPREL32;
}
- else if (fixp->fx_r_type == BFD_RELOC_PCREL_LO16)
+ else if (fixp->fx_pcrel)
{
- if (OUTPUT_FLAVOR == bfd_target_elf_flavour)
- reloc->addend = fixp->fx_addnumber;
+ bfd_vma pcrel_address;
+
+ /* Set PCREL_ADDRESS to this relocation's "PC". The PC for high
+ high-part relocs is the address of the low-part reloc. */
+ if (fixp->fx_r_type == BFD_RELOC_PCREL_HI16_S)
+ {
+ assert (fixp->fx_next != NULL
+ && fixp->fx_next->fx_r_type == BFD_RELOC_PCREL_LO16);
+ pcrel_address = (fixp->fx_next->fx_where
+ + fixp->fx_next->fx_frag->fr_address);
+ }
else
+ pcrel_address = reloc->address;
+
+ if (OUTPUT_FLAVOR == bfd_target_elf_flavour)
+ {
+ /* At this point, fx_addnumber is "symbol offset - pcrel_address".
+ Relocations want only the symbol offset. */
+ reloc->addend = fixp->fx_addnumber + pcrel_address;
+ }
+ else if (fixp->fx_r_type == BFD_RELOC_PCREL_LO16
+ || fixp->fx_r_type == BFD_RELOC_PCREL_HI16_S)
{
- /* We use a special addend for an internal RELLO reloc. */
+ /* We use a special addend for an internal RELLO or RELHI reloc. */
if (symbol_section_p (fixp->fx_addsy))
- reloc->addend = reloc->address - S_GET_VALUE (fixp->fx_subsy);
+ reloc->addend = pcrel_address - S_GET_VALUE (fixp->fx_subsy);
else
- reloc->addend = fixp->fx_addnumber + reloc->address;
+ reloc->addend = fixp->fx_addnumber + pcrel_address;
}
- }
- else if (fixp->fx_r_type == BFD_RELOC_PCREL_HI16_S)
- {
- assert (fixp->fx_next != NULL
- && fixp->fx_next->fx_r_type == BFD_RELOC_PCREL_LO16);
-
- /* The reloc is relative to the RELLO; adjust the addend
- accordingly. */
- if (OUTPUT_FLAVOR == bfd_target_elf_flavour)
- reloc->addend = fixp->fx_next->fx_addnumber;
else
{
- /* We use a special addend for an internal RELHI reloc. */
- if (symbol_section_p (fixp->fx_addsy))
- reloc->addend = (fixp->fx_next->fx_frag->fr_address
- + fixp->fx_next->fx_where
- - S_GET_VALUE (fixp->fx_subsy));
+ if (OUTPUT_FLAVOR != bfd_target_aout_flavour)
+ /* A gruesome hack which is a result of the gruesome gas reloc
+ handling. */
+ reloc->addend = pcrel_address;
else
- reloc->addend = (fixp->fx_addnumber
- + fixp->fx_next->fx_frag->fr_address
- + fixp->fx_next->fx_where);
+ reloc->addend = -pcrel_address;
}
}
- else if (fixp->fx_pcrel == 0 || OUTPUT_FLAVOR == bfd_target_elf_flavour)
- reloc->addend = fixp->fx_addnumber;
else
- {
- if (OUTPUT_FLAVOR != bfd_target_aout_flavour)
- /* A gruesome hack which is a result of the gruesome gas reloc
- handling. */
- reloc->addend = reloc->address;
- else
- reloc->addend = -reloc->address;
- }
+ reloc->addend = fixp->fx_addnumber;
/* If this is a variant frag, we may need to adjust the existing
reloc and generate a new one. */
reloc2->address = (reloc->address
+ (RELAX_RELOC2 (fixp->fx_frag->fr_subtype)
- RELAX_RELOC1 (fixp->fx_frag->fr_subtype)));
- reloc2->addend = fixp->fx_addnumber - S_GET_VALUE (fixp->fx_addsy)
- + fixp->fx_frag->tc_frag_data.tc_fr_offset;
+ reloc2->addend = reloc->addend;
reloc2->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_LO16);
assert (reloc2->howto != NULL);
+2003-12-18 Richard Sandiford <rsandifo@redhat.com>
+
+ * gas/mips/mips16-jalx.d: Use -mabi=o64.
+ * gas/mips/mips16.d: Likewise.
+ * gas/mips/elf-rel17.[sd]: New test.
+ * gas/mips/mips.exp: Run it.
+
2003-12-17 Nick Clifton <nickc@redhat.com>
* gas/m32r/error.exp: Add parallel.s
--- /dev/null
+#objdump: -dr
+#as: -mabi=32
+
+.*: file format .*
+
+Disassembly of section \.text:
+
+00000000 <.*>:
+.*: 3c040000 lui a0,0x0
+ .*: R_MIPS_HI16 x
+.*: 24840000 addiu a0,a0,0
+ .*: R_MIPS_LO16 x
+ \.\.\.
--- /dev/null
+ la $4,x
+ .space 16
+ .comm x,12
run_dump_test "elf-rel-got-n64"
run_dump_test "elf-rel-xgot-n64"
}
+ run_dump_test "elf-rel17"
run_dump_test "${tmips}${el}empic"
run_dump_test "empic2"
#objdump: -dr -mmips:4000 -mmips:16
-#as: -mips3 -mtune=r4000 -mips16
+#as: -mips3 -mtune=r4000 -mips16 -mabi=o64
#name: mips16 jalx
.*: file format .*
Disassembly of section .text:
#objdump: -dr -mmips:4000
-#as: -mips3 -mtune=r4000
+#as: -mips3 -mtune=r4000 -mabi=o64
#name: mips16
# Test the mips16 instruction set.