/* MIPS-specific support for 32-bit ELF
- Copyright (C) 1993-2014 Free Software Foundation, Inc.
+ Copyright (C) 1993-2018 Free Software Foundation, Inc.
Most of the information added by Ian Lance Taylor, Cygnus Support,
<ian@cygnus.com>.
(bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
(bfd *, bfd_reloc_code_real_type);
-static reloc_howto_type *mips_elf32_rtype_to_howto
- (unsigned int, bfd_boolean);
-static void mips_info_to_howto_rel
+static bfd_boolean mips_info_to_howto_rel
(bfd *, arelent *, Elf_Internal_Rela *);
-static void mips_info_to_howto_rela
+static bfd_boolean mips_info_to_howto_rela
(bfd *, arelent *, Elf_Internal_Rela *);
static bfd_boolean mips_elf_sym_is_global
(bfd *, asymbol *);
/* 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 */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- /* This needs complex overflow
+ /* This needs complex overflow
detection, because the upper four
bits must match the PC + 4. */
_bfd_mips_elf_generic_reloc, /* special_function */
/* Protected jump conversion. This is an optimization hint. No
relocation is required for correctness. */
- HOWTO (R_MIPS_JALR, /* type */
+ HOWTO (R_MIPS_JALR, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
_bfd_mips_elf_generic_reloc, /* special_function */
- "R_MIPS_JALR", /* name */
+ "R_MIPS_JALR", /* name */
FALSE, /* partial_inplace */
0x00000000, /* src_mask */
0x00000000, /* dst_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- /* This needs complex overflow
+ /* This needs complex overflow
detection, because the upper four
bits must match the PC. */
_bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS16_GPREL", /* name */
TRUE, /* partial_inplace */
0x0000ffff, /* src_mask */
- 0x0000ffff, /* dst_mask */
+ 0x0000ffff, /* dst_mask */
FALSE), /* pcrel_offset */
/* A MIPS16 reference to the global offset table. */
"R_MIPS16_GOT16", /* name */
TRUE, /* partial_inplace */
0x0000ffff, /* src_mask */
- 0x0000ffff, /* dst_mask */
+ 0x0000ffff, /* dst_mask */
FALSE), /* pcrel_offset */
/* A MIPS16 call through the global offset table. */
"R_MIPS16_CALL16", /* name */
TRUE, /* partial_inplace */
0x0000ffff, /* src_mask */
- 0x0000ffff, /* dst_mask */
+ 0x0000ffff, /* dst_mask */
FALSE), /* pcrel_offset */
/* MIPS16 high 16 bits of symbol value. */
"R_MIPS16_HI16", /* name */
TRUE, /* partial_inplace */
0x0000ffff, /* src_mask */
- 0x0000ffff, /* dst_mask */
+ 0x0000ffff, /* dst_mask */
FALSE), /* pcrel_offset */
/* MIPS16 low 16 bits of symbol value. */
"R_MIPS16_LO16", /* name */
TRUE, /* partial_inplace */
0x0000ffff, /* src_mask */
- 0x0000ffff, /* dst_mask */
+ 0x0000ffff, /* dst_mask */
FALSE), /* pcrel_offset */
/* MIPS16 TLS general dynamic variable reference. */
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 elf_micromips_howto_table_rel[] =
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- /* This needs complex overflow
+ /* This needs complex overflow
detection, because the upper four
bits must match the PC. */
_bfd_mips_elf_generic_reloc, /* special_function */
TRUE); /* pcrel_offset */
/* 32 bit pc-relative. This was a GNU extension used by embedded-PIC.
- It was co-opted by mips-linux for exception-handling data. It is no
- longer used, but should continue to be supported by the linker for
- backward compatibility. (GCC stopped using it in May, 2004.) */
+ It was co-opted by mips-linux for exception-handling data. GCC stopped
+ using it in May, 2004, then started using it again for compact unwind
+ tables. */
static reloc_howto_type elf_mips_gnu_pcrel32 =
HOWTO (R_MIPS_PC32, /* type */
0, /* rightshift */
_bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_COPY", /* name */
FALSE, /* partial_inplace */
- 0x0, /* src_mask */
- 0x0, /* dst_mask */
+ 0x0, /* src_mask */
+ 0x0, /* dst_mask */
FALSE); /* pcrel_offset */
/* Originally a VxWorks extension, but now used for other systems too. */
_bfd_mips_elf_generic_reloc, /* special_function */
"R_MIPS_JUMP_SLOT", /* name */
FALSE, /* partial_inplace */
- 0x0, /* src_mask */
- 0x0, /* dst_mask */
+ 0x0, /* src_mask */
+ 0x0, /* dst_mask */
FALSE); /* pcrel_offset */
/* Used in EH tables. */
"R_MIPS_EH", /* name */
TRUE, /* partial_inplace */
0xffffffff, /* src_mask */
- 0xffffffff, /* dst_mask */
+ 0xffffffff, /* dst_mask */
FALSE); /* pcrel_offset */
/* Set the GP value for OUTPUT_BFD. Returns FALSE if this is a
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[] =
/* Given a MIPS Elf_Internal_Rel, fill in an arelent structure. */
static reloc_howto_type *
-mips_elf32_rtype_to_howto (unsigned int r_type,
+mips_elf32_rtype_to_howto (bfd *abfd,
+ unsigned int r_type,
bfd_boolean rela_p ATTRIBUTE_UNUSED)
{
+ reloc_howto_type *howto = NULL;
+
switch (r_type)
{
case R_MIPS_GNU_VTINHERIT:
return &elf_mips_eh_howto;
default:
if (r_type >= R_MICROMIPS_min && r_type < R_MICROMIPS_max)
- return &elf_micromips_howto_table_rel[r_type - R_MICROMIPS_min];
+ howto = &elf_micromips_howto_table_rel[r_type - R_MICROMIPS_min];
if (r_type >= R_MIPS16_min && r_type < R_MIPS16_max)
- return &elf_mips16_howto_table_rel[r_type - R_MIPS16_min];
- BFD_ASSERT (r_type < (unsigned int) R_MIPS_max);
- return &elf_mips_howto_table_rel[r_type];
+ howto = &elf_mips16_howto_table_rel[r_type - R_MIPS16_min];
+ if (r_type < R_MIPS_max)
+ howto = &elf_mips_howto_table_rel[r_type];
+ if (howto != NULL && howto->name != NULL)
+ return howto;
+
+ _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
+ abfd, r_type);
+ bfd_set_error (bfd_error_bad_value);
+ return NULL;
}
}
/* Given a MIPS Elf_Internal_Rel, fill in an arelent structure. */
-static void
+static bfd_boolean
mips_info_to_howto_rel (bfd *abfd, arelent *cache_ptr, Elf_Internal_Rela *dst)
{
- const struct elf_backend_data *bed;
unsigned int r_type;
r_type = ELF32_R_TYPE (dst->r_info);
- bed = get_elf_backend_data (abfd);
- cache_ptr->howto = bed->elf_backend_mips_rtype_to_howto (r_type, FALSE);
+ cache_ptr->howto = mips_elf32_rtype_to_howto (abfd, r_type, FALSE);
+
+ if (cache_ptr->howto == NULL)
+ return FALSE;
/* The addend for a GPREL16 or LITERAL relocation comes from the GP
value for the object file. We get the addend now, rather than
if (((*cache_ptr->sym_ptr_ptr)->flags & BSF_SECTION_SYM) != 0
&& (gprel16_reloc_p (r_type) || literal_reloc_p (r_type)))
cache_ptr->addend = elf_gp (abfd);
+
+ return TRUE;
}
/* Given a MIPS Elf_Internal_Rela, fill in an arelent structure. */
-static void
+static bfd_boolean
mips_info_to_howto_rela (bfd *abfd, arelent *cache_ptr, Elf_Internal_Rela *dst)
{
- mips_info_to_howto_rel (abfd, cache_ptr, dst);
+ return mips_info_to_howto_rel (abfd, cache_ptr, dst);
/* If we ever need to do any extra processing with dst->r_addend
(the field omitted in an Elf_Internal_Rel) we can do it here. */
return FALSE;
case 128: /* Linux/MIPS elf_prpsinfo */
+ elf_tdata (abfd)->core->pid
+ = bfd_get_32 (abfd, note->descdata + 16);
elf_tdata (abfd)->core->program
= _bfd_elfcore_strndup (abfd, note->descdata + 32, 16);
elf_tdata (abfd)->core->command
return TRUE;
}
+
+/* Write Linux core PRSTATUS note into core file. */
+
+static char *
+elf32_mips_write_core_note (bfd *abfd, char *buf, int *bufsiz, int note_type,
+ ...)
+{
+ switch (note_type)
+ {
+ default:
+ return NULL;
+
+ case NT_PRPSINFO:
+ BFD_FAIL ();
+ return NULL;
+
+ case NT_PRSTATUS:
+ {
+ char data[256];
+ va_list ap;
+ long pid;
+ int cursig;
+ const void *greg;
+
+ va_start (ap, note_type);
+ memset (data, 0, 72);
+ pid = va_arg (ap, long);
+ bfd_put_32 (abfd, pid, data + 24);
+ cursig = va_arg (ap, int);
+ bfd_put_16 (abfd, cursig, data + 12);
+ greg = va_arg (ap, const void *);
+ memcpy (data + 72, greg, 180);
+ memset (data + 252, 0, 4);
+ va_end (ap);
+ return elfcore_write_note (abfd, buf, bufsiz,
+ "CORE", note_type, data, sizeof (data));
+ }
+ }
+}
+
+/* Remove the magic _gp_disp symbol from the symbol tables. */
+
+static bfd_boolean
+elf32_mips_fixup_symbol (struct bfd_link_info *info,
+ struct elf_link_hash_entry *h)
+{
+ if (strcmp (h->root.root.string, "_gp_disp") == 0)
+ _bfd_elf_link_hash_hide_symbol (info, h, TRUE);
+ return TRUE;
+}
\f
/* Depending on the target vector we generate some version of Irix
executables or "normal" MIPS ELF ABI executables. */
_bfd_mips_elf_additional_program_headers
#define elf_backend_modify_segment_map _bfd_mips_elf_modify_segment_map
#define elf_backend_gc_mark_hook _bfd_mips_elf_gc_mark_hook
-#define elf_backend_gc_sweep_hook _bfd_mips_elf_gc_sweep_hook
#define elf_backend_copy_indirect_symbol \
_bfd_mips_elf_copy_indirect_symbol
+#define elf_backend_hide_symbol _bfd_mips_elf_hide_symbol
+#define elf_backend_fixup_symbol elf32_mips_fixup_symbol
#define elf_backend_grok_prstatus elf32_mips_grok_prstatus
#define elf_backend_grok_psinfo elf32_mips_grok_psinfo
#define elf_backend_ecoff_debug_swap &mips_elf32_ecoff_debug_swap
#define elf_backend_got_header_size (4 * MIPS_RESERVED_GOTNO)
+#define elf_backend_want_dynrelro 1
#define elf_backend_may_use_rel_p 1
#define elf_backend_may_use_rela_p 0
#define elf_backend_default_use_rela_p 0
#define elf_backend_write_section _bfd_mips_elf_write_section
#define elf_backend_mips_irix_compat elf32_mips_irix_compat
#define elf_backend_mips_rtype_to_howto mips_elf32_rtype_to_howto
+#define elf_backend_sort_relocs_p _bfd_mips_elf_sort_relocs_p
+
#define bfd_elf32_bfd_is_local_label_name \
mips_elf_is_local_label_name
#define bfd_elf32_bfd_is_target_special_symbol \
#undef ELF_MAXPAGESIZE
#undef ELF_COMMONPAGESIZE
-#define TARGET_LITTLE_SYM mips_elf32_trad_le_vec
-#define TARGET_LITTLE_NAME "elf32-tradlittlemips"
-#define TARGET_BIG_SYM mips_elf32_trad_be_vec
-#define TARGET_BIG_NAME "elf32-tradbigmips"
+#define TARGET_LITTLE_SYM mips_elf32_trad_le_vec
+#define TARGET_LITTLE_NAME "elf32-tradlittlemips"
+#define TARGET_BIG_SYM mips_elf32_trad_be_vec
+#define TARGET_BIG_NAME "elf32-tradbigmips"
/* The MIPS ABI says at Page 5-1:
Virtual addresses and file offsets for MIPS segments are congruent
#define ELF_COMMONPAGESIZE 0x1000
#define elf32_bed elf32_tradbed
+#undef elf_backend_write_core_note
+#define elf_backend_write_core_note elf32_mips_write_core_note
+
/* Include the target file again for this target. */
#include "elf32-target.h"
#undef elf32_bed
#define elf32_bed elf32_fbsd_tradbed
+#undef elf_backend_write_core_note
+
#include "elf32-target.h"
/* Implement elf_backend_final_write_processing for VxWorks. */
#undef ELF_MAXPAGESIZE
#undef ELF_COMMONPAGESIZE
-#define TARGET_LITTLE_SYM mips_elf32_vxworks_le_vec
-#define TARGET_LITTLE_NAME "elf32-littlemips-vxworks"
-#define TARGET_BIG_SYM mips_elf32_vxworks_be_vec
-#define TARGET_BIG_NAME "elf32-bigmips-vxworks"
+#define TARGET_LITTLE_SYM mips_elf32_vxworks_le_vec
+#define TARGET_LITTLE_NAME "elf32-littlemips-vxworks"
+#define TARGET_BIG_SYM mips_elf32_vxworks_be_vec
+#define TARGET_BIG_NAME "elf32-bigmips-vxworks"
#undef ELF_OSABI
#undef elf32_bed
#define elf_backend_default_use_rela_p 1
#undef elf_backend_got_header_size
#define elf_backend_got_header_size (4 * 3)
+#undef elf_backend_dtrel_excludes_plt
+#define elf_backend_dtrel_excludes_plt 1
#undef elf_backend_finish_dynamic_symbol
#define elf_backend_finish_dynamic_symbol \