/* MIPS-specific support for 64-bit ELF
- Copyright (C) 1996-2014 Free Software Foundation, Inc.
+ Copyright (C) 1996-2017 Free Software Foundation, Inc.
Ian Lance Taylor, Cygnus Support
Linker support added by Mark Mitchell, CodeSourcery, LLC.
<mark@codesourcery.com>
(bfd *, arelent *, Elf_Internal_Rela *);
static long mips_elf64_get_reloc_upper_bound
(bfd *, asection *);
-static long mips_elf64_canonicalize_reloc
- (bfd *, asection *, arelent **, asymbol **);
static long mips_elf64_get_dynamic_reloc_upper_bound
(bfd *);
-static long mips_elf64_canonicalize_dynamic_reloc
- (bfd *, arelent **, asymbol **);
static bfd_boolean mips_elf64_slurp_one_reloc_table
(bfd *, asection *, Elf_Internal_Shdr *, bfd_size_type, arelent *,
asymbol **, bfd_boolean);
/* No relocation. */
HOWTO (R_MIPS_NONE, /* type */
0, /* rightshift */
- 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 3, /* size (0 = byte, 1 = short, 2 = long) */
0, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
/* No relocation. */
HOWTO (R_MIPS_NONE, /* type */
0, /* rightshift */
- 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 3, /* size (0 = byte, 1 = short, 2 = long) */
0, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
0x0000ffff, /* src_mask */
0x0000ffff, /* dst_mask */
FALSE), /* pcrel_offset */
+
+ /* MIPS16 16-bit PC-relative branch offset. */
+ HOWTO (R_MIPS16_PC16_S1, /* type */
+ 1, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ TRUE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS16_PC16_S1", /* name */
+ TRUE, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ TRUE), /* pcrel_offset */
};
static reloc_howto_type mips16_elf64_howto_table_rela[] =
0, /* src_mask */
0x0000ffff, /* dst_mask */
FALSE), /* pcrel_offset */
+
+ /* MIPS16 16-bit PC-relative branch offset. */
+ HOWTO (R_MIPS16_PC16_S1, /* type */
+ 1, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ TRUE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS16_PC16_S1", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ TRUE), /* pcrel_offset */
};
static reloc_howto_type micromips_elf64_howto_table_rel[] =
R_MIPS16_TLS_DTPREL_LO16 - R_MIPS16_min },
{ BFD_RELOC_MIPS16_TLS_GOTTPREL, R_MIPS16_TLS_GOTTPREL - R_MIPS16_min },
{ BFD_RELOC_MIPS16_TLS_TPREL_HI16, R_MIPS16_TLS_TPREL_HI16 - R_MIPS16_min },
- { BFD_RELOC_MIPS16_TLS_TPREL_LO16, R_MIPS16_TLS_TPREL_LO16 - R_MIPS16_min }
+ { BFD_RELOC_MIPS16_TLS_TPREL_LO16, R_MIPS16_TLS_TPREL_LO16 - R_MIPS16_min },
+ { BFD_RELOC_MIPS16_16_PCREL_S1, R_MIPS16_PC16_S1 - R_MIPS16_min }
};
static const struct elf_reloc_map micromips_reloc_map[] =
else
return &mips16_elf64_howto_table_rel[r_type - R_MIPS16_min];
}
- BFD_ASSERT (r_type < (unsigned int) R_MIPS_max);
+ if (r_type >= R_MIPS_max)
+ {
+ _bfd_error_handler (_("unrecognised MIPS reloc number: %d"), r_type);
+ bfd_set_error (bfd_error_bad_value);
+ r_type = R_MIPS_NONE;
+ }
if (rela_p)
return &mips_elf64_howto_table_rela[r_type];
else
return _bfd_elf_get_dynamic_reloc_upper_bound (abfd) * 3;
}
-/* We must also copy more relocations than the corresponding functions
- in elf.c would, so the two following functions are slightly
- modified from elf.c, that multiply the external relocation count by
- 3 to obtain the internal relocation count. */
-
-static long
-mips_elf64_canonicalize_reloc (bfd *abfd, sec_ptr section,
- arelent **relptr, asymbol **symbols)
-{
- arelent *tblptr;
- unsigned int i;
- const struct elf_backend_data *bed = get_elf_backend_data (abfd);
-
- if (! bed->s->slurp_reloc_table (abfd, section, symbols, FALSE))
- return -1;
-
- tblptr = section->relocation;
- for (i = 0; i < section->reloc_count * 3; i++)
- *relptr++ = tblptr++;
-
- *relptr = NULL;
-
- return section->reloc_count * 3;
-}
-
-static long
-mips_elf64_canonicalize_dynamic_reloc (bfd *abfd, arelent **storage,
- asymbol **syms)
-{
- bfd_boolean (*slurp_relocs) (bfd *, asection *, asymbol **, bfd_boolean);
- asection *s;
- long ret;
-
- if (elf_dynsymtab (abfd) == 0)
- {
- bfd_set_error (bfd_error_invalid_operation);
- return -1;
- }
-
- slurp_relocs = get_elf_backend_data (abfd)->s->slurp_reloc_table;
- ret = 0;
- for (s = abfd->sections; s != NULL; s = s->next)
- {
- if (elf_section_data (s)->this_hdr.sh_link == elf_dynsymtab (abfd)
- && (elf_section_data (s)->this_hdr.sh_type == SHT_REL
- || elf_section_data (s)->this_hdr.sh_type == SHT_RELA))
- {
- arelent *p;
- long count, i;
-
- if (! (*slurp_relocs) (abfd, s, syms, TRUE))
- return -1;
- count = s->size / elf_section_data (s)->this_hdr.sh_entsize * 3;
- p = s->relocation;
- for (i = 0; i < count; i++)
- *storage++ = p++;
- ret += count;
- }
- }
-
- *storage = NULL;
-
- return ret;
-}
-
/* Read the relocations from one reloc section. This is mostly copied
from elfcode.h, except for the changes to expand one external
- relocation to 3 internal ones. We must unfortunately set
- reloc_count to the number of external relocations, because a lot of
- generic code seems to depend on this. */
+ relocation to 3 internal ones. To reduce processing effort we
+ could discard those R_MIPS_NONE relocations that occupy the second
+ and the third entry of a triplet, as `mips_elf64_write_rel' and
+ `mips_elf64_write_rela' recreate them in output automagically,
+ however that would also remove them from `objdump -r' output,
+ breaking a long-established tradition and likely confusing people. */
static bfd_boolean
mips_elf64_slurp_one_reloc_table (bfd *abfd, asection *asect,
}
}
- asect->reloc_count += (relent - relents) / 3;
+ asect->reloc_count += relent - relents;
if (allocated != NULL)
free (allocated);
#define elf_backend_grok_psinfo elf64_mips_grok_psinfo
#define elf_backend_got_header_size (8 * MIPS_RESERVED_GOTNO)
+#define elf_backend_want_dynrelro 1
/* MIPS ELF64 can use a mixture of REL and RELA, but some Relocations
work better/work only in RELA, so we default to this. */
_bfd_mips_elf_print_private_bfd_data
#define bfd_elf64_get_reloc_upper_bound mips_elf64_get_reloc_upper_bound
-#define bfd_elf64_canonicalize_reloc mips_elf64_canonicalize_reloc
#define bfd_elf64_get_dynamic_reloc_upper_bound mips_elf64_get_dynamic_reloc_upper_bound
-#define bfd_elf64_canonicalize_dynamic_reloc mips_elf64_canonicalize_dynamic_reloc
-#define bfd_elf64_bfd_relax_section _bfd_mips_relax_section
#define bfd_elf64_mkobject _bfd_mips_elf_mkobject
-/* MIPS ELF64 archive functions. */
-#define bfd_elf64_archive_functions
-extern bfd_boolean bfd_elf64_archive_slurp_armap
- (bfd *);
-extern bfd_boolean bfd_elf64_archive_write_armap
- (bfd *, unsigned int, struct orl *, unsigned int, int);
-#define bfd_elf64_archive_slurp_extended_name_table \
- _bfd_archive_coff_slurp_extended_name_table
-#define bfd_elf64_archive_construct_extended_name_table \
- _bfd_archive_coff_construct_extended_name_table
-#define bfd_elf64_archive_truncate_arname \
- _bfd_archive_coff_truncate_arname
-#define bfd_elf64_archive_read_ar_hdr _bfd_archive_coff_read_ar_hdr
-#define bfd_elf64_archive_write_ar_hdr _bfd_archive_coff_write_ar_hdr
-#define bfd_elf64_archive_openr_next_archived_file \
- _bfd_archive_coff_openr_next_archived_file
-#define bfd_elf64_archive_get_elt_at_index \
- _bfd_archive_coff_get_elt_at_index
-#define bfd_elf64_archive_generic_stat_arch_elt \
- _bfd_archive_coff_generic_stat_arch_elt
-#define bfd_elf64_archive_update_armap_timestamp \
- _bfd_archive_coff_update_armap_timestamp
-
/* The SGI style (n)64 NewABI. */
#define TARGET_LITTLE_SYM mips_elf64_le_vec
#define TARGET_LITTLE_NAME "elf64-littlemips"