/* MIPS-specific support for ELF
- Copyright (C) 1993-2014 Free Software Foundation, Inc.
+ Copyright (C) 1993-2015 Free Software Foundation, Inc.
Most of the information added by Ian Lance Taylor, Cygnus Support,
<ian@cygnus.com>.
#include "elfxx-mips.h"
#include "elf/mips.h"
#include "elf-vxworks.h"
+#include "dwarf2.h"
/* Get the ECOFF swapping routines. */
#include "coff/sym.h"
to them before. */
if (was_local_p)
value += gp0;
- overflowed_p = mips_elf_overflow_p (value, 16);
+ if (was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+ overflowed_p = mips_elf_overflow_p (value, 16);
break;
case R_MIPS16_GOT16:
return bfd_reloc_outofrange;
value = symbol + addend - p;
- overflowed_p = mips_elf_overflow_p (value, 18);
+ if (was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+ overflowed_p = mips_elf_overflow_p (value, 18);
value >>= howto->rightshift;
value &= howto->dst_mask;
break;
return bfd_reloc_outofrange;
value = symbol + addend - p;
- overflowed_p = mips_elf_overflow_p (value, 23);
+ if (was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+ overflowed_p = mips_elf_overflow_p (value, 23);
value >>= howto->rightshift;
value &= howto->dst_mask;
break;
return bfd_reloc_outofrange;
value = symbol + addend - p;
- overflowed_p = mips_elf_overflow_p (value, 28);
+ if (was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+ overflowed_p = mips_elf_overflow_p (value, 28);
value >>= howto->rightshift;
value &= howto->dst_mask;
break;
return bfd_reloc_outofrange;
value = symbol + addend - ((p | 7) ^ 7);
- overflowed_p = mips_elf_overflow_p (value, 21);
+ if (was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+ overflowed_p = mips_elf_overflow_p (value, 21);
value >>= howto->rightshift;
value &= howto->dst_mask;
break;
return bfd_reloc_outofrange;
value = symbol + addend - p;
- overflowed_p = mips_elf_overflow_p (value, 21);
+ if (was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+ overflowed_p = mips_elf_overflow_p (value, 21);
value >>= howto->rightshift;
value &= howto->dst_mask;
break;
case R_MIPS_PCHI16:
value = mips_elf_high (symbol + addend - p);
- overflowed_p = mips_elf_overflow_p (value, 16);
+ if (was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+ overflowed_p = mips_elf_overflow_p (value, 16);
value &= howto->dst_mask;
break;
if (howto->partial_inplace)
addend = _bfd_mips_elf_sign_extend (addend, 8);
value = symbol + addend - p;
- overflowed_p = mips_elf_overflow_p (value, 8);
+ if (was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+ overflowed_p = mips_elf_overflow_p (value, 8);
value >>= howto->rightshift;
value &= howto->dst_mask;
break;
if (howto->partial_inplace)
addend = _bfd_mips_elf_sign_extend (addend, 11);
value = symbol + addend - p;
- overflowed_p = mips_elf_overflow_p (value, 11);
+ if (was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+ overflowed_p = mips_elf_overflow_p (value, 11);
value >>= howto->rightshift;
value &= howto->dst_mask;
break;
if (howto->partial_inplace)
addend = _bfd_mips_elf_sign_extend (addend, 17);
value = symbol + addend - p;
- overflowed_p = mips_elf_overflow_p (value, 17);
+ if (was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+ overflowed_p = mips_elf_overflow_p (value, 17);
value >>= howto->rightshift;
value &= howto->dst_mask;
break;
if (howto->partial_inplace)
addend = _bfd_mips_elf_sign_extend (addend, 25);
value = symbol + addend - ((p | 3) ^ 3);
- overflowed_p = mips_elf_overflow_p (value, 25);
+ if (was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+ overflowed_p = mips_elf_overflow_p (value, 25);
value >>= howto->rightshift;
value &= howto->dst_mask;
break;
const Elf_Internal_Rela *relocation,
bfd *input_bfd, bfd_byte *contents)
{
- bfd_vma x;
+ bfd_vma x = 0;
bfd_byte *location = contents + relocation->r_offset;
+ unsigned int size = bfd_get_reloc_size (howto);
/* Obtain the bytes. */
- x = bfd_get ((8 * bfd_get_reloc_size (howto)), input_bfd, location);
+ if (size != 0)
+ x = bfd_get (8 * size, input_bfd, location);
return x;
}
bfd_vma x;
bfd_byte *location;
int r_type = ELF_R_TYPE (input_bfd, relocation->r_info);
+ unsigned int size;
/* Figure out where the relocation is occurring. */
location = contents + relocation->r_offset;
}
/* Put the value into the output. */
- bfd_put (8 * bfd_get_reloc_size (howto), input_bfd, x, location);
+ size = bfd_get_reloc_size (howto);
+ if (size != 0)
+ bfd_put (8 * size, input_bfd, x, location);
_bfd_mips_elf_reloc_shuffle (input_bfd, r_type, !info->relocatable,
location);
htab->sstubs = s;
if (!mips_elf_hash_table (info)->use_rld_obj_head
- && !info->shared
+ && info->executable
&& bfd_get_linker_section (abfd, ".rld_map") == NULL)
{
s = bfd_make_section_anyway_with_flags (abfd, ".rld_map",
(void) bfd_set_section_alignment (abfd, s, MIPS_ELF_LOG_FILE_ALIGN (abfd));
}
- if (!info->shared)
+ if (info->executable)
{
const char *name;
dynamic will now refer to the local copy instead. */
hmips->possibly_dynamic_relocs = 0;
- return _bfd_elf_adjust_dynamic_copy (h, htab->sdynbss);
+ return _bfd_elf_adjust_dynamic_copy (info, h, htab->sdynbss);
}
\f
/* This function is called after all the input files have been read,
info->combreloc = 0;
}
}
- else if (! info->shared
+ else if (info->executable
&& ! mips_elf_hash_table (info)->use_rld_obj_head
&& CONST_STRNEQ (name, ".rld_map"))
{
&& !MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_RLD_MAP, 0))
return FALSE;
+ if (info->executable
+ && !MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_RLD_MAP_REL, 0))
+ return FALSE;
+
/* The DT_DEBUG entry may be filled in by the dynamic linker and
used by the debugger. */
if (info->executable
break;
}
s = h->root.u.def.section;
+
+ /* The MIPS_RLD_MAP tag stores the absolute address of the
+ debug pointer. */
dyn.d_un.d_ptr = (s->output_section->vma + s->output_offset
+ h->root.u.def.value);
}
break;
+ case DT_MIPS_RLD_MAP_REL:
+ {
+ struct elf_link_hash_entry *h;
+ bfd_vma dt_addr, rld_addr;
+ h = mips_elf_hash_table (info)->rld_symbol;
+ if (!h)
+ {
+ dyn_to_skip = MIPS_ELF_DYN_SIZE (dynobj);
+ swap_out_p = FALSE;
+ break;
+ }
+ s = h->root.u.def.section;
+
+ /* The MIPS_RLD_MAP_REL tag stores the offset to the debug
+ pointer, relative to the address of the tag. */
+ dt_addr = (sdyn->output_section->vma + sdyn->output_offset
+ + b - sdyn->contents);
+ rld_addr = (s->output_section->vma + s->output_offset
+ + h->root.u.def.value);
+ dyn.d_un.d_ptr = rld_addr - dt_addr;
+ }
+ break;
+
case DT_MIPS_OPTIONS:
s = (bfd_get_section_by_name
(output_bfd, MIPS_ELF_OPTIONS_SECTION_NAME (output_bfd)));
}
+/* Whether to sort relocs output by ld -r or ld --emit-relocs, by r_offset.
+ Don't do so for code sections. We want to keep ordering of HI16/LO16
+ as is. On the other hand, elf-eh-frame.c processing requires .eh_frame
+ relocs to be sorted. */
+
+bfd_boolean
+_bfd_mips_elf_sort_relocs_p (asection *sec)
+{
+ return (sec->flags & SEC_CODE) == 0;
+}
+
+
/* The final processing done just before writing out a MIPS ELF object
file. This gets the MIPS architecture right based on the machine
number. This is used by both the 32-bit and the 64-bit ABI. */
return "MIPS_HIPAGENO";
case DT_MIPS_RLD_MAP:
return "MIPS_RLD_MAP";
+ case DT_MIPS_RLD_MAP_REL:
+ return "MIPS_RLD_MAP_REL";
case DT_MIPS_DELTA_CLASS:
return "MIPS_DELTA_CLASS";
case DT_MIPS_DELTA_CLASS_NO:
|| mips_elf_tdata (abfd)->abiflags.fp_abi == Val_GNU_MIPS_ABI_FP_64A)
i_ehdrp->e_ident[EI_ABIVERSION] = 3;
}
+
+int
+_bfd_mips_elf_compact_eh_encoding (struct bfd_link_info *link_info ATTRIBUTE_UNUSED)
+{
+ return DW_EH_PE_pcrel | DW_EH_PE_sdata4;
+}
+
+/* Return the opcode for can't unwind. */
+
+int
+_bfd_mips_elf_cant_unwind_opcode (struct bfd_link_info *link_info ATTRIBUTE_UNUSED)
+{
+ return COMPACT_EH_CANT_UNWIND_OPCODE;
+}