/* MIPS-specific support for ELF
Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
- 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+ 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
Most of the information added by Ian Lance Taylor, Cygnus Support,
<ian@cygnus.com>.
/* Map an input bfd to a got in a multi-got link. */
-struct mips_elf_bfd2got_hash {
+struct mips_elf_bfd2got_hash
+{
bfd *bfd;
struct mips_got_info *g;
};
#define is_mips_elf(bfd) \
(bfd_get_flavour (bfd) == bfd_target_elf_flavour \
&& elf_tdata (bfd) != NULL \
- && elf_object_id (bfd) == MIPS_ELF_TDATA)
+ && elf_object_id (bfd) == MIPS_ELF_DATA)
/* The ABI says that every symbol used by dynamic relocations must have
a global GOT entry. Among other things, this provides the dynamic
asection *(*add_stub_section) (const char *, asection *, asection *);
};
+/* Get the MIPS ELF linker hash table from a link_info structure. */
+
+#define mips_elf_hash_table(p) \
+ (elf_hash_table_id ((struct elf_link_hash_table *) ((p)->hash)) \
+ == MIPS_ELF_DATA ? ((struct mips_elf_link_hash_table *) ((p)->hash)) : NULL)
+
/* A structure used to communicate with htab_traverse callbacks. */
-struct mips_htab_traverse_info {
+struct mips_htab_traverse_info
+{
/* The usual link-wide information. */
struct bfd_link_info *info;
bfd *output_bfd;
/* This will be used when we sort the dynamic relocation records. */
static bfd *reldyn_sorting_bfd;
+/* True if ABFD is for CPUs with load interlocking that include
+ non-MIPS1 CPUs and R3900. */
+#define LOAD_INTERLOCKS_P(abfd) \
+ ( ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) != E_MIPS_ARCH_1) \
+ || ((elf_elfheader (abfd)->e_flags & EF_MIPS_MACH) == E_MIPS_MACH_3900))
+
+/* True if ABFD is for CPUs that are faster if JAL is converted to BAL.
+ This should be safe for all architectures. We enable this predicate
+ for RM9000 for now. */
+#define JAL_TO_BAL_P(abfd) \
+ ((elf_elfheader (abfd)->e_flags & EF_MIPS_MACH) == E_MIPS_MACH_9000)
+
+/* True if ABFD is for CPUs that are faster if JALR is converted to BAL.
+ This should be safe for all architectures. We enable this predicate for
+ all CPUs. */
+#define JALR_TO_BAL_P(abfd) 1
+
+/* True if ABFD is for CPUs that are faster if JR is converted to B.
+ This should be safe for all architectures. We enable this predicate for
+ all CPUs. */
+#define JR_TO_B_P(abfd) 1
+
/* True if ABFD is a PIC object. */
#define PIC_OBJECT_P(abfd) \
((elf_elfheader (abfd)->e_flags & EF_MIPS_PIC) != 0)
#define CALL_FP_STUB_P(name) CONST_STRNEQ (name, CALL_FP_STUB)
\f
/* The format of the first PLT entry in an O32 executable. */
-static const bfd_vma mips_o32_exec_plt0_entry[] = {
+static const bfd_vma mips_o32_exec_plt0_entry[] =
+{
0x3c1c0000, /* lui $28, %hi(&GOTPLT[0]) */
0x8f990000, /* lw $25, %lo(&GOTPLT[0])($28) */
0x279c0000, /* addiu $28, $28, %lo(&GOTPLT[0]) */
/* The format of the first PLT entry in an N32 executable. Different
because gp ($28) is not available; we use t2 ($14) instead. */
-static const bfd_vma mips_n32_exec_plt0_entry[] = {
+static const bfd_vma mips_n32_exec_plt0_entry[] =
+{
0x3c0e0000, /* lui $14, %hi(&GOTPLT[0]) */
0x8dd90000, /* lw $25, %lo(&GOTPLT[0])($14) */
0x25ce0000, /* addiu $14, $14, %lo(&GOTPLT[0]) */
/* The format of the first PLT entry in an N64 executable. Different
from N32 because of the increased size of GOT entries. */
-static const bfd_vma mips_n64_exec_plt0_entry[] = {
+static const bfd_vma mips_n64_exec_plt0_entry[] =
+{
0x3c0e0000, /* lui $14, %hi(&GOTPLT[0]) */
0xddd90000, /* ld $25, %lo(&GOTPLT[0])($14) */
0x25ce0000, /* addiu $14, $14, %lo(&GOTPLT[0]) */
};
/* The format of subsequent PLT entries. */
-static const bfd_vma mips_exec_plt_entry[] = {
+static const bfd_vma mips_exec_plt_entry[] =
+{
0x3c0f0000, /* lui $15, %hi(.got.plt entry) */
0x01f90000, /* l[wd] $25, %lo(.got.plt entry)($15) */
0x25f80000, /* addiu $24, $15, %lo(.got.plt entry) */
};
/* The format of the first PLT entry in a VxWorks executable. */
-static const bfd_vma mips_vxworks_exec_plt0_entry[] = {
+static const bfd_vma mips_vxworks_exec_plt0_entry[] =
+{
0x3c190000, /* lui t9, %hi(_GLOBAL_OFFSET_TABLE_) */
0x27390000, /* addiu t9, t9, %lo(_GLOBAL_OFFSET_TABLE_) */
0x8f390008, /* lw t9, 8(t9) */
};
/* The format of subsequent PLT entries. */
-static const bfd_vma mips_vxworks_exec_plt_entry[] = {
+static const bfd_vma mips_vxworks_exec_plt_entry[] =
+{
0x10000000, /* b .PLT_resolver */
0x24180000, /* li t8, <pltindex> */
0x3c190000, /* lui t9, %hi(<.got.plt slot>) */
};
/* The format of the first PLT entry in a VxWorks shared object. */
-static const bfd_vma mips_vxworks_shared_plt0_entry[] = {
+static const bfd_vma mips_vxworks_shared_plt0_entry[] =
+{
0x8f990008, /* lw t9, 8(gp) */
0x00000000, /* nop */
0x03200008, /* jr t9 */
};
/* The format of subsequent PLT entries. */
-static const bfd_vma mips_vxworks_shared_plt_entry[] = {
+static const bfd_vma mips_vxworks_shared_plt_entry[] =
+{
0x10000000, /* b .PLT_resolver */
0x24180000 /* li t8, <pltindex> */
};
(bfd_boolean (*) (struct elf_link_hash_entry *, void *)) (func), \
(info)))
-/* Get the MIPS ELF linker hash table from a link_info structure. */
-
-#define mips_elf_hash_table(p) \
- ((struct mips_elf_link_hash_table *) ((p)->hash))
-
/* Find the base offsets for thread-local storage in this object,
for GD/LD and IE/LE respectively. */
function, or 0 if we can't decide which function that is. */
static unsigned long
-mips16_stub_symndx (asection *sec, const Elf_Internal_Rela *relocs,
+mips16_stub_symndx (asection *sec ATTRIBUTE_UNUSED,
+ const Elf_Internal_Rela *relocs,
const Elf_Internal_Rela *relend)
{
const Elf_Internal_Rela *rel;
struct mips_elf_link_hash_table *htab;
htab = mips_elf_hash_table (info);
+ if (htab == NULL)
+ return FALSE;
+
htab->add_stub_section = fn;
htab->la25_stubs = htab_try_create (1, mips_elf_la25_stub_hash,
mips_elf_la25_stub_eq, NULL);
unsigned int align;
htab = mips_elf_hash_table (info);
+ if (htab == NULL)
+ return FALSE;
/* Create a unique name for the new section. */
name = bfd_malloc (11 + sizeof (".text.stub."));
asection *s;
htab = mips_elf_hash_table (info);
+ if (htab == NULL)
+ return FALSE;
/* Create a trampoline section, if we haven't already. */
s = htab->strampoline;
/* See if we've already created an equivalent stub. */
htab = mips_elf_hash_table (info);
+ if (htab == NULL)
+ return FALSE;
+
slot = htab_find_slot (htab->la25_stubs, &search, INSERT);
if (slot == NULL)
return FALSE;
return r_type == R_MIPS16_26 || r_type == R_MIPS16_CALL16;
}
+static inline bfd_boolean
+jal_reloc_p (int r_type)
+{
+ return r_type == R_MIPS_26 || r_type == R_MIPS16_26;
+}
+
void
_bfd_mips16_elf_reloc_unshuffle (bfd *abfd, int r_type,
bfd_boolean jal_shuffle, bfd_byte *data)
bfd_boolean need_relocs = FALSE;
htab = mips_elf_hash_table (info);
+ if (htab == NULL)
+ return;
+
sgot = htab->sgot;
indx = 0;
struct mips_elf_link_hash_table *htab;
htab = mips_elf_hash_table (info);
+ BFD_ASSERT (htab != NULL);
+
BFD_ASSERT (h->plt.offset != (bfd_vma) -1);
/* This function only works for VxWorks, because a non-VxWorks .got.plt
struct mips_got_entry *entry;
htab = mips_elf_hash_table (info);
+ BFD_ASSERT (htab != NULL);
+
entry = mips_elf_create_local_got_entry (abfd, info, ibfd, value,
r_symndx, h, r_type);
if (!entry)
int r_type, struct bfd_link_info *info)
{
struct mips_elf_link_hash_table *htab;
- bfd_vma index;
+ bfd_vma got_index;
struct mips_got_info *g, *gg;
long global_got_dynindx = 0;
htab = mips_elf_hash_table (info);
+ BFD_ASSERT (htab != NULL);
+
gg = g = htab->got_info;
if (g->bfd2got && ibfd)
{
+ h->root.u.def.section->output_offset
+ h->root.u.def.section->output_section->vma);
- index = mips_tls_got_index (abfd, hm->tls_got_offset, &hm->tls_type,
- r_type, info, hm, value);
+ got_index = mips_tls_got_index (abfd, hm->tls_got_offset, &hm->tls_type,
+ r_type, info, hm, value);
}
else
{
indices into the GOT. That makes it easy to calculate the GOT
offset. */
BFD_ASSERT (h->dynindx >= global_got_dynindx);
- index = ((h->dynindx - global_got_dynindx + g->local_gotno)
- * MIPS_ELF_GOT_SIZE (abfd));
+ got_index = ((h->dynindx - global_got_dynindx + g->local_gotno)
+ * MIPS_ELF_GOT_SIZE (abfd));
}
- BFD_ASSERT (index < htab->sgot->size);
+ BFD_ASSERT (got_index < htab->sgot->size);
- return index;
+ return got_index;
}
/* Find a GOT page entry that points to within 32KB of VALUE. These
mips_elf_got_page (bfd *abfd, bfd *ibfd, struct bfd_link_info *info,
bfd_vma value, bfd_vma *offsetp)
{
- bfd_vma page, index;
+ bfd_vma page, got_index;
struct mips_got_entry *entry;
page = (value + 0x8000) & ~(bfd_vma) 0xffff;
if (!entry)
return MINUS_ONE;
- index = entry->gotidx;
+ got_index = entry->gotidx;
if (offsetp)
*offsetp = value - entry->d.address;
- return index;
+ return got_index;
}
/* Find a local GOT entry for an R_MIPS*_GOT16 relocation against VALUE.
static bfd_vma
mips_elf_got_offset_from_index (struct bfd_link_info *info, bfd *output_bfd,
- bfd *input_bfd, bfd_vma index)
+ bfd *input_bfd, bfd_vma got_index)
{
struct mips_elf_link_hash_table *htab;
asection *sgot;
bfd_vma gp;
htab = mips_elf_hash_table (info);
+ BFD_ASSERT (htab != NULL);
+
sgot = htab->sgot;
gp = _bfd_get_gp_value (output_bfd)
+ mips_elf_adjust_gp (output_bfd, htab->got_info, input_bfd);
- return sgot->output_section->vma + sgot->output_offset + index - gp;
+ return sgot->output_section->vma + sgot->output_offset + got_index - gp;
}
/* Create and return a local GOT entry for VALUE, which was calculated
struct mips_elf_link_hash_table *htab;
htab = mips_elf_hash_table (info);
+ BFD_ASSERT (htab != NULL);
entry.abfd = NULL;
entry.symndx = -1;
{
Elf_Internal_Rela outrel;
asection *s;
- bfd_byte *loc;
+ bfd_byte *rloc;
bfd_vma got_address;
s = mips_elf_rel_dyn_section (info, FALSE);
+ htab->sgot->output_offset
+ entry.gotidx);
- loc = s->contents + (s->reloc_count++ * sizeof (Elf32_External_Rela));
+ rloc = s->contents + (s->reloc_count++ * sizeof (Elf32_External_Rela));
outrel.r_offset = got_address;
outrel.r_info = ELF32_R_INFO (STN_UNDEF, R_MIPS_32);
outrel.r_addend = value;
- bfd_elf32_swap_reloca_out (abfd, &outrel, loc);
+ bfd_elf32_swap_reloca_out (abfd, &outrel, rloc);
}
return *loc;
return TRUE;
htab = mips_elf_hash_table (info);
+ BFD_ASSERT (htab != NULL);
+
g = htab->got_info;
if (g == NULL)
return TRUE;
struct mips_got_info *g;
htab = mips_elf_hash_table (info);
+ BFD_ASSERT (htab != NULL);
+
hmips = (struct mips_elf_link_hash_entry *) h;
/* A global symbol in the GOT must also be in the dynamic symbol
struct mips_got_entry entry, **loc;
htab = mips_elf_hash_table (info);
+ BFD_ASSERT (htab != NULL);
+
g = htab->got_info;
BFD_ASSERT (g != NULL);
void **loc;
htab = mips_elf_hash_table (info);
+ BFD_ASSERT (htab != NULL);
+
g = htab->got_info;
BFD_ASSERT (g != NULL);
struct mips_elf_link_hash_table *htab;
htab = mips_elf_hash_table (info);
+ BFD_ASSERT (htab != NULL);
+
s = mips_elf_rel_dyn_section (info, FALSE);
BFD_ASSERT (s != NULL);
entry = (struct mips_got_entry *) *entryp;
info = (struct bfd_link_info *) data;
htab = mips_elf_hash_table (info);
+ BFD_ASSERT (htab != NULL);
+
if (entry->abfd != NULL
&& entry->symndx == -1
&& entry->d.h->needs_lazy_stub)
dynobj = elf_hash_table (info)->dynobj;
htab = mips_elf_hash_table (info);
+ BFD_ASSERT (htab != NULL);
+
g = htab->got_info;
g->bfd2got = htab_try_create (1, mips_elf_bfd2got_entry_hash,
mips_elf_bfd2got_entry_eq, NULL);
struct mips_elf_link_hash_table *htab;
htab = mips_elf_hash_table (info);
+ BFD_ASSERT (htab != NULL);
/* This function may be called more than once. */
if (htab->sgot)
RELOCATION; RELOCATION->R_ADDEND is ignored.
The result of the relocation calculation is stored in VALUEP.
- REQUIRE_JALXP indicates whether or not the opcode used with this
- relocation must be JALX.
+ On exit, set *CROSS_MODE_JUMP_P to true if the relocation field
+ is a MIPS16 jump to non-MIPS16 code, or vice versa.
This function returns bfd_reloc_continue if the caller need take no
further action regarding this relocation, bfd_reloc_notsupported if
bfd_vma addend, reloc_howto_type *howto,
Elf_Internal_Sym *local_syms,
asection **local_sections, bfd_vma *valuep,
- const char **namep, bfd_boolean *require_jalxp,
+ const char **namep,
+ bfd_boolean *cross_mode_jump_p,
bfd_boolean save_addend)
{
/* The eventual value we will return. */
dynobj = elf_hash_table (info)->dynobj;
htab = mips_elf_hash_table (info);
+ BFD_ASSERT (htab != NULL);
/* Parse the relocation. */
r_symndx = ELF_R_SYM (input_bfd, relocation->r_info);
http://techpubs.sgi.com/library/manuals/4000/007-4658-001/pdf/007-4658-001.pdf */
symbol = 0;
}
+ else if ((*info->callbacks->undefined_symbol)
+ (info, h->root.root.root.string, input_bfd,
+ input_section, relocation->r_offset,
+ (info->unresolved_syms_in_objects == RM_GENERATE_ERROR)
+ || ELF_ST_VISIBILITY (h->root.other)))
+ {
+ return bfd_reloc_undefined;
+ }
else
{
- if (! ((*info->callbacks->undefined_symbol)
- (info, h->root.root.root.string, input_bfd,
- input_section, relocation->r_offset,
- (info->unresolved_syms_in_objects == RM_GENERATE_ERROR)
- || ELF_ST_VISIBILITY (h->root.other))))
- return bfd_reloc_undefined;
- symbol = 0;
+ return bfd_reloc_notsupported;
}
target_is_16_bit_code_p = ELF_ST_IS_MIPS16 (h->root.other);
+ h->la25_stub->offset);
/* Calls from 16-bit code to 32-bit code and vice versa require the
- special jalx instruction. */
- *require_jalxp = (!info->relocatable
- && (((r_type == R_MIPS16_26) && !target_is_16_bit_code_p)
- || ((r_type == R_MIPS_26) && target_is_16_bit_code_p)));
+ mode change. */
+ *cross_mode_jump_p = !info->relocatable
+ && ((r_type == R_MIPS16_26 && !target_is_16_bit_code_p)
+ || ((r_type == R_MIPS_26 || r_type == R_MIPS_JALR)
+ && target_is_16_bit_code_p));
local_p = mips_elf_local_relocation_p (input_bfd, relocation,
local_sections, TRUE);
case R_MIPS_JALR:
/* This relocation is only a hint. In some cases, we optimize
it into a bal instruction. But we don't try to optimize
- branches to the PLT; that will wind up wasting time. */
- if (h != NULL && h->root.plt.offset != (bfd_vma) -1)
+ when the symbol does not resolve locally. */
+ if (h != NULL && !SYMBOL_CALLS_LOCAL (info, &h->root))
return bfd_reloc_continue;
value = symbol + addend;
break;
/* It has been determined that the result of the RELOCATION is the
VALUE. Use HOWTO to place VALUE into the output file at the
appropriate position. The SECTION is the section to which the
- relocation applies. If REQUIRE_JALX is TRUE, then the opcode used
- for the relocation must be either JAL or JALX, and it is
- unconditionally converted to JALX.
+ relocation applies.
+ CROSS_MODE_JUMP_P is true if the relocation field
+ is a MIPS16 jump to non-MIPS16 code, or vice versa.
Returns FALSE if anything goes wrong. */
const Elf_Internal_Rela *relocation,
bfd_vma value, bfd *input_bfd,
asection *input_section, bfd_byte *contents,
- bfd_boolean require_jalx)
+ bfd_boolean cross_mode_jump_p)
{
bfd_vma x;
bfd_byte *location;
x |= (value & howto->dst_mask);
/* If required, turn JAL into JALX. */
- if (require_jalx)
+ if (cross_mode_jump_p && jal_reloc_p (r_type))
{
bfd_boolean ok;
bfd_vma opcode = x >> 26;
if (!ok)
{
(*_bfd_error_handler)
- (_("%B: %A+0x%lx: jump to stub routine which is not jal"),
+ (_("%B: %A+0x%lx: Direct jumps between ISA modes are not allowed; consider recompiling with interlinking enabled."),
input_bfd,
input_section,
(unsigned long) relocation->r_offset);
x = (x & ~(0x3f << 26)) | (jalx_opcode << 26);
}
- /* On the RM9000, bal is faster than jal, because bal uses branch
- prediction hardware. If we are linking for the RM9000, and we
- see jal, and bal fits, use it instead. Note that this
- transformation should be safe for all architectures. */
- if (bfd_get_mach (input_bfd) == bfd_mach_mips9000
- && !info->relocatable
- && !require_jalx
- && ((r_type == R_MIPS_26 && (x >> 26) == 0x3) /* jal addr */
- || (r_type == R_MIPS_JALR && x == 0x0320f809))) /* jalr t9 */
+ /* Try converting JAL to BAL and J(AL)R to B(AL), if the target is in
+ range. */
+ if (!info->relocatable
+ && !cross_mode_jump_p
+ && ((JAL_TO_BAL_P (input_bfd)
+ && r_type == R_MIPS_26
+ && (x >> 26) == 0x3) /* jal addr */
+ || (JALR_TO_BAL_P (input_bfd)
+ && r_type == R_MIPS_JALR
+ && x == 0x0320f809) /* jalr t9 */
+ || (JR_TO_B_P (input_bfd)
+ && r_type == R_MIPS_JALR
+ && x == 0x03200008))) /* jr t9 */
{
bfd_vma addr;
bfd_vma dest;
dest = value;
off = dest - addr;
if (off <= 0x1ffff && off >= -0x20000)
- x = 0x04110000 | (((bfd_vma) off >> 2) & 0xffff); /* bal addr */
+ {
+ if (x == 0x03200008) /* jr t9 */
+ x = 0x10000000 | (((bfd_vma) off >> 2) & 0xffff); /* b addr */
+ else
+ x = 0x04110000 | (((bfd_vma) off >> 2) & 0xffff); /* bal addr */
+ }
}
/* Put the value into the output. */
struct mips_elf_link_hash_table *htab;
htab = mips_elf_hash_table (info);
+ BFD_ASSERT (htab != NULL);
+
r_type = ELF_R_TYPE (output_bfd, rel->r_info);
dynobj = elf_hash_table (info)->dynobj;
sreloc = mips_elf_rel_dyn_section (info, FALSE);
/* We must now calculate the dynamic symbol table index to use
in the relocation. */
- if (h != NULL
- && (!h->root.def_regular
- || (info->shared && !info->symbolic && !h->root.forced_local)))
+ if (h != NULL && ! SYMBOL_REFERENCES_LOCAL (info, &h->root))
{
indx = h->root.dynindx;
if (SGI_COMPAT (output_bfd))
case E_MIPS_MACH_OCTEON:
return bfd_mach_mips_octeon;
+ case E_MIPS_MACH_XLR:
+ return bfd_mach_mips_xlr;
+
default:
switch (flags & EF_MIPS_ARCH)
{
{
const char *name = bfd_get_section_name (abfd, hdr->bfd_section);
+ /* .sbss is not handled specially here because the GNU/Linux
+ prelinker can convert .sbss from NOBITS to PROGBITS and
+ changing it back to NOBITS breaks the binary. The entry in
+ _bfd_mips_elf_special_sections will ensure the correct flags
+ are set on .sbss if BFD creates it without reading it from an
+ input file, and without special handling here the flags set
+ on it in an input file will be followed. */
if (strcmp (name, ".sdata") == 0
|| strcmp (name, ".lit8") == 0
|| strcmp (name, ".lit4") == 0)
hdr->sh_flags |= SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL;
hdr->sh_type = SHT_PROGBITS;
}
- else if (strcmp (name, ".sbss") == 0)
- {
- hdr->sh_flags |= SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL;
- hdr->sh_type = SHT_NOBITS;
- }
else if (strcmp (name, ".srdata") == 0)
{
hdr->sh_flags |= SHF_ALLOC | SHF_MIPS_GPREL;
symbol. We mark symbols as small common if appropriate. This is
also where we undo the increment of the value for a mips16 symbol. */
-bfd_boolean
+int
_bfd_mips_elf_link_output_symbol_hook
(struct bfd_link_info *info ATTRIBUTE_UNUSED,
const char *name ATTRIBUTE_UNUSED, Elf_Internal_Sym *sym,
if (ELF_ST_IS_MIPS16 (sym->st_other))
sym->st_value &= ~1;
- return TRUE;
+ return 1;
}
\f
/* Functions for the dynamic linker. */
struct mips_elf_link_hash_table *htab;
htab = mips_elf_hash_table (info);
+ BFD_ASSERT (htab != NULL);
+
flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
| SEC_LINKER_CREATED | SEC_READONLY);
return TRUE;
htab = mips_elf_hash_table (info);
+ BFD_ASSERT (htab != NULL);
+
dynobj = elf_hash_table (info)->dynobj;
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (abfd);
}
break;
+ /* This is just a hint; it can safely be ignored. Don't set
+ has_static_relocs for the corresponding symbol. */
+ case R_MIPS_JALR:
+ break;
+
case R_MIPS_32:
case R_MIPS_REL32:
case R_MIPS_64:
case R_MIPS_CALL_LO16:
if (h != NULL)
{
- /* VxWorks call relocations point the function's .got.plt
+ /* VxWorks call relocations point at the function's .got.plt
entry, which will be allocated by adjust_dynamic_symbol.
Otherwise, this symbol requires a global GOT entry. */
if ((!htab->is_vxworks || h->forced_local)
howto = MIPS_ELF_RTYPE_TO_HOWTO (abfd, r_type, FALSE);
addend = mips_elf_read_rel_addend (abfd, rel,
howto, contents);
- if (r_type == R_MIPS_GOT16)
+ if (got16_reloc_p (r_type))
mips_elf_add_lo16_rel_addend (abfd, rel, rel_end,
contents, &addend);
else
struct mips_elf_link_hash_table *htab;
htab = mips_elf_hash_table (info);
+ BFD_ASSERT (htab != NULL);
+
dynobj = elf_hash_table (info)->dynobj;
hmips = (struct mips_elf_link_hash_entry *) h;
struct mips_elf_link_hash_table *htab;
htab = mips_elf_hash_table (info);
+ BFD_ASSERT (htab != NULL);
+
dynobj = elf_hash_table (info)->dynobj;
hmips = (struct mips_elf_link_hash_entry *) h;
struct mips_htab_traverse_info hti;
htab = mips_elf_hash_table (info);
+ BFD_ASSERT (htab != NULL);
/* The .reginfo section has a fixed size. */
ri = bfd_get_section_by_name (output_bfd, ".reginfo");
struct mips_elf_link_hash_table *htab;
htab = mips_elf_hash_table (info);
+ BFD_ASSERT (htab != NULL);
+
s = htab->sgot;
if (s == NULL)
return TRUE;
bfd_size_type dynsymcount;
htab = mips_elf_hash_table (info);
+ BFD_ASSERT (htab != NULL);
+
if (htab->lazy_stub_count == 0)
return;
struct mips_elf_link_hash_table *htab;
htab = mips_elf_hash_table (info);
+ BFD_ASSERT (htab != NULL);
+
if (htab->lazy_stub_count == 0)
return;
htab->sstubs->size = 0;
- mips_elf_link_hash_traverse (mips_elf_hash_table (info),
- mips_elf_allocate_lazy_stub, htab);
+ mips_elf_link_hash_traverse (htab, mips_elf_allocate_lazy_stub, htab);
htab->sstubs->size += htab->function_stub_size;
BFD_ASSERT (htab->sstubs->size
== htab->lazy_stub_count * htab->function_stub_size);
struct mips_elf_link_hash_table *htab;
htab = mips_elf_hash_table (info);
+ BFD_ASSERT (htab != NULL);
dynobj = elf_hash_table (info)->dynobj;
BFD_ASSERT (dynobj != NULL);
else if (s == htab->splt)
{
/* If the last PLT entry has a branch delay slot, allocate
- room for an extra nop to fill the delay slot. */
- if (!htab->is_vxworks && s->size > 0)
+ room for an extra nop to fill the delay slot. This is
+ for CPUs without load interlocking. */
+ if (! LOAD_INTERLOCKS_P (output_bfd)
+ && ! htab->is_vxworks && s->size > 0)
s->size += 4;
}
else if (! CONST_STRNEQ (name, ".init")
const char *name;
bfd_vma value = 0;
reloc_howto_type *howto;
- bfd_boolean require_jalx;
+ bfd_boolean cross_mode_jump_p;
/* TRUE if the relocation is a RELA relocation, rather than a
REL relocation. */
bfd_boolean rela_relocation_p = TRUE;
if (!mips_elf_add_lo16_rel_addend (input_bfd, rel, relend,
contents, &addend))
{
- const char *name;
-
if (h)
name = h->root.root.string;
else
input_section, info, rel,
addend, howto, local_syms,
local_sections, &value,
- &name, &require_jalx,
+ &name, &cross_mode_jump_p,
use_saved_addend_p))
{
case bfd_reloc_continue:
struct mips_elf_link_hash_table *htab;
htab = mips_elf_hash_table (info);
+ BFD_ASSERT (htab != NULL);
BFD_ASSERT (name != NULL);
if (!htab->small_data_overflow_reported
- && (howto->type == R_MIPS_GPREL16
+ && (gprel16_reloc_p (howto->type)
|| howto->type == R_MIPS_LITERAL))
{
- const char *msg =
- _("small-data section exceeds 64KB;"
- " lower small-data size limit (see option -G)");
+ msg = _("small-data section exceeds 64KB;"
+ " lower small-data size limit (see option -G)");
htab->small_data_overflow_reported = TRUE;
(*info->callbacks->einfo) ("%P: %s\n", msg);
/* Actually perform the relocation. */
if (! mips_elf_perform_relocation (info, howto, rel, value,
input_bfd, input_section,
- contents, require_jalx))
+ contents, cross_mode_jump_p))
return FALSE;
}
stub = (struct mips_elf_la25_stub *) *slot;
hti = (struct mips_htab_traverse_info *) data;
htab = mips_elf_hash_table (hti->info);
+ BFD_ASSERT (htab != NULL);
/* Create the section contents, if we haven't already. */
s = stub->stub_section;
struct mips_elf_link_hash_entry *hmips;
htab = mips_elf_hash_table (info);
+ BFD_ASSERT (htab != NULL);
dynobj = elf_hash_table (info)->dynobj;
hmips = (struct mips_elf_link_hash_entry *) h;
plt_entry = mips_exec_plt_entry;
bfd_put_32 (output_bfd, plt_entry[0] | got_address_high, loc);
bfd_put_32 (output_bfd, plt_entry[1] | got_address_low | load, loc + 4);
- bfd_put_32 (output_bfd, plt_entry[2] | got_address_low, loc + 8);
- bfd_put_32 (output_bfd, plt_entry[3], loc + 12);
+
+ if (! LOAD_INTERLOCKS_P (output_bfd))
+ {
+ bfd_put_32 (output_bfd, plt_entry[2] | got_address_low, loc + 8);
+ bfd_put_32 (output_bfd, plt_entry[3], loc + 12);
+ }
+ else
+ {
+ bfd_put_32 (output_bfd, plt_entry[3], loc + 8);
+ bfd_put_32 (output_bfd, plt_entry[2] | got_address_low, loc + 12);
+ }
/* Emit an R_MIPS_JUMP_SLOT relocation against the .got.plt entry. */
mips_elf_output_dynamic_relocation (output_bfd, htab->srelplt,
struct mips_elf_link_hash_table *htab;
htab = mips_elf_hash_table (info);
+ BFD_ASSERT (htab != NULL);
dynobj = elf_hash_table (info)->dynobj;
if (h->plt.offset != (bfd_vma) -1)
struct mips_elf_link_hash_table *htab;
htab = mips_elf_hash_table (info);
+ BFD_ASSERT (htab != NULL);
+
if (ABI_64_P (output_bfd))
plt_entry = mips_n64_exec_plt0_entry;
else if (ABI_N32_P (output_bfd))
struct mips_elf_link_hash_table *htab;
htab = mips_elf_hash_table (info);
+ BFD_ASSERT (htab != NULL);
+
plt_entry = mips_vxworks_exec_plt0_entry;
/* Calculate the value of _GLOBAL_OFFSET_TABLE_. */
struct mips_elf_link_hash_table *htab;
htab = mips_elf_hash_table (info);
+ BFD_ASSERT (htab != NULL);
/* We just need to copy the entry byte-by-byte. */
for (i = 0; i < ARRAY_SIZE (mips_vxworks_shared_plt0_entry); i++)
struct mips_elf_link_hash_table *htab;
htab = mips_elf_hash_table (info);
+ BFD_ASSERT (htab != NULL);
+
dynobj = elf_hash_table (info)->dynobj;
sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
for (g = gg->next; g->next != gg; g = g->next)
{
- bfd_vma index = g->next->local_gotno + g->next->global_gotno
+ bfd_vma got_index = g->next->local_gotno + g->next->global_gotno
+ g->next->tls_gotno;
MIPS_ELF_PUT_WORD (output_bfd, 0, sgot->contents
- + index++ * MIPS_ELF_GOT_SIZE (output_bfd));
+ + got_index++ * MIPS_ELF_GOT_SIZE (output_bfd));
MIPS_ELF_PUT_WORD (output_bfd, MIPS_ELF_GNU_GOT1_MASK (output_bfd),
sgot->contents
- + index++ * MIPS_ELF_GOT_SIZE (output_bfd));
+ + got_index++ * MIPS_ELF_GOT_SIZE (output_bfd));
if (! info->shared)
continue;
- while (index < g->assigned_gotno)
+ while (got_index < g->assigned_gotno)
{
rel[0].r_offset = rel[1].r_offset = rel[2].r_offset
- = index++ * MIPS_ELF_GOT_SIZE (output_bfd);
+ = got_index++ * MIPS_ELF_GOT_SIZE (output_bfd);
if (!(mips_elf_create_dynamic_relocation
(output_bfd, info, rel, NULL,
bfd_abs_section_ptr,
case bfd_mach_mips8000:
case bfd_mach_mips10000:
case bfd_mach_mips12000:
+ case bfd_mach_mips14000:
+ case bfd_mach_mips16000:
val = E_MIPS_ARCH_4;
break;
val = E_MIPS_ARCH_64R2 | E_MIPS_MACH_OCTEON;
break;
+ case bfd_mach_mips_xlr:
+ val = E_MIPS_ARCH_64 | E_MIPS_MACH_XLR;
+ break;
+
case bfd_mach_mipsisa32:
val = E_MIPS_ARCH_32;
break;
return NULL;
}
\f
-/* Allocate ABFD's target-dependent data. */
-
-bfd_boolean
-_bfd_mips_elf_mkobject (bfd *abfd)
-{
- return bfd_elf_allocate_object (abfd, sizeof (struct elf_obj_tdata),
- MIPS_ELF_TDATA);
-}
-
/* Create a MIPS ELF linker hash table. */
struct bfd_link_hash_table *
if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
mips_elf_link_hash_newfunc,
- sizeof (struct mips_elf_link_hash_entry)))
+ sizeof (struct mips_elf_link_hash_entry),
+ MIPS_ELF_DATA))
{
free (ret);
return NULL;
/* Sort the dynamic symbols so that those with GOT entries come after
those without. */
htab = mips_elf_hash_table (info);
+ BFD_ASSERT (htab != NULL);
+
if (!mips_elf_sort_hash_table (abfd, info))
return FALSE;
/* MIPS64 extensions. */
{ bfd_mach_mipsisa64r2, bfd_mach_mipsisa64 },
{ bfd_mach_mips_sb1, bfd_mach_mipsisa64 },
+ { bfd_mach_mips_xlr, bfd_mach_mipsisa64 },
/* MIPS V extensions. */
{ bfd_mach_mipsisa64, bfd_mach_mips5 },
/* R10000 extensions. */
{ bfd_mach_mips12000, bfd_mach_mips10000 },
+ { bfd_mach_mips14000, bfd_mach_mips10000 },
+ { bfd_mach_mips16000, bfd_mach_mips10000 },
/* R5000 extensions. Note: the vr5500 ISA is an extension of the core
vr5400 ISA, but doesn't include the multimedia stuff. It seems
if (link_info)
{
htab = mips_elf_hash_table (link_info);
+ BFD_ASSERT (htab != NULL);
+
if (htab->use_plts_and_copy_relocs && !htab->is_vxworks)
i_ehdrp->e_ident[EI_ABIVERSION] = 1;
}