PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
static bfd_reloc_status_type mips16_gprel_reloc
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
+/* start-sanitize-sky */
+static bfd_reloc_status_type dvp_u15_s3_reloc
+ PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
+/* end-sanitize-sky */
static boolean mips_elf_adjust_dynindx
PARAMS ((struct elf_link_hash_entry *, PTR));
static boolean mips_elf_relocate_section
#define USE_REL 1 /* MIPS uses REL relocations instead of RELA */
-enum reloc_type
-{
- R_MIPS_NONE = 0,
- R_MIPS_16, R_MIPS_32,
- R_MIPS_REL32, R_MIPS_26,
- R_MIPS_HI16, R_MIPS_LO16,
- R_MIPS_GPREL16, R_MIPS_LITERAL,
- R_MIPS_GOT16, R_MIPS_PC16,
- R_MIPS_CALL16, R_MIPS_GPREL32,
- /* The remaining relocs are defined on Irix, although they are not
- in the MIPS ELF ABI. */
- R_MIPS_UNUSED1, R_MIPS_UNUSED2,
- R_MIPS_UNUSED3,
- R_MIPS_SHIFT5, R_MIPS_SHIFT6,
- R_MIPS_64, R_MIPS_GOT_DISP,
- R_MIPS_GOT_PAGE, R_MIPS_GOT_OFST,
- R_MIPS_GOT_HI16, R_MIPS_GOT_LO16,
- R_MIPS_SUB, R_MIPS_INSERT_A,
- R_MIPS_INSERT_B, R_MIPS_DELETE,
- R_MIPS_HIGHER, R_MIPS_HIGHEST,
- R_MIPS_CALL_HI16, R_MIPS_CALL_LO16,
- /* start-sanitize-r5900 */
- /* This is used by a mips co-processor instruction. */
- R_MIPS15_S3,
- /* end-sanitize-r5900 */
- R_MIPS_max,
- /* These relocs are used for the mips16. */
- R_MIPS16_26 = 100,
- R_MIPS16_GPREL = 101
-/* start-sanitize-sky */
- /* These relocs are for the dvp. */
- , R_MIPS_DVP_11_PCREL = 120,
- R_MIPS_DVP_27_S4 = 121
-/* end-sanitize-sky */
-};
-
static reloc_howto_type elf_mips_howto_table[] =
{
/* No relocation. */
0x0000ffff, /* dst_mask */
false), /* pcrel_offset */
- /* start-sanitize-r5900 */
- HOWTO (R_MIPS15_S3, /* type */
- 3, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 15, /* bitsize */
- false, /* pc_relative */
- 6, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MIPS15_S3", /* name */
- true, /* partial_inplace */
- 0x001fffc0, /* src_mask */
- 0x001fffc0, /* dst_mask */
- false) /* pcrel_offset */
- /* end-sanitize-r5900 */
-
+ { R_MIPS_SCN_DISP },
+ { R_MIPS_REL16 },
+ { R_MIPS_ADD_IMMEDIATE },
+ { R_MIPS_PJUMP },
+ { R_MIPS_RELGOT }
};
/* The reloc used for BFD_RELOC_CTOR when doing a 64 bit link. This
0xffff, /* dst_mask */
false); /* pcrel_offset */
+/* start-sanitize-r5900 */
+static reloc_howto_type elf_mips15_s3_howto =
+ HOWTO (R_MIPS15_S3, /* type */
+ 3, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 15, /* bitsize */
+ false, /* pc_relative */
+ 6, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS15_S3", /* name */
+ true, /* partial_inplace */
+ 0x001fffc0, /* src_mask */
+ 0x001fffc0, /* dst_mask */
+ false); /* pcrel_offset */
+
+/* end-sanitize-r5900 */
/* start-sanitize-sky */
/* DVP relocations.
Note that partial_inplace and pcrel_offset are backwards from the
0x7ffffff0, /* src_mask */
0x7ffffff0, /* dst_mask */
false); /* pcrel_offset */
+static reloc_howto_type elf_mips_dvp_11_s4_howto =
+ HOWTO (R_MIPS_DVP_11_S4, /* type */
+ 4, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 11, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_DVP_11_S4", /* name */
+ false, /* partial_inplace */
+ 0x03ff, /* src_mask */
+ 0x03ff, /* dst_mask */
+ false); /* pcrel_offset */
+static reloc_howto_type elf_mips_dvp_u15_s3_howto =
+ HOWTO (R_MIPS_DVP_U15_S3, /* type */
+ 3, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 15, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_unsigned, /* complain_on_overflow */
+ dvp_u15_s3_reloc, /* special_function */
+ "R_MIPS_DVP_U15_S3", /* name */
+ false, /* partial_inplace */
+ 0xf03ff, /* src_mask */
+ 0xf03ff, /* dst_mask */
+ false); /* pcrel_offset */
/* end-sanitize-sky */
+/* GNU extension to record C++ vtable hierarchy */
+static reloc_howto_type elf_mips_gnu_vtinherit_howto =
+ HOWTO (R_MIPS_GNU_VTINHERIT, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ NULL, /* special_function */
+ "R_MIPS_GNU_VTINHERIT", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false); /* pcrel_offset */
+
+/* GNU extension to record C++ vtable member usage */
+static reloc_howto_type elf_mips_gnu_vtentry_howto =
+ HOWTO (R_MIPS_GNU_VTENTRY, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ NULL, /* special_function */
+ "R_MIPS_GNU_VTENTRY", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false); /* pcrel_offset */
+
/* 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
return ret;
}
+/* start-sanitize-sky */
+/* Handle a dvp R_MIPS_DVP_U15_S3 reloc.
+ This is needed because the bits aren't contiguous. */
+
+static bfd_reloc_status_type
+dvp_u15_s3_reloc (abfd, reloc_entry, symbol, data, input_section,
+ output_bfd, error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ boolean relocateable;
+ bfd_reloc_status_type ret;
+ bfd_vma relocation;
+ bfd_vma x;
+
+ /* If we're relocating, and this is an external symbol with no
+ addend, we don't want to change anything. We will only have an
+ addend if this is a newly created reloc, not read from an ELF
+ file. See bfd_elf_generic_reloc. */
+ if (output_bfd != NULL
+ && (symbol->flags & BSF_SECTION_SYM) == 0
+ /* partial_inplace is false, so this test always succeeds,
+ but for clarity and consistency with bfd_elf_generic_reloc
+ this is left as is. */
+ && (! reloc_entry->howto->partial_inplace
+ || reloc_entry->addend == 0))
+ {
+ reloc_entry->address += input_section->output_offset;
+ return bfd_reloc_ok;
+ }
+
+ if (reloc_entry->address > input_section->_cooked_size)
+ return bfd_reloc_outofrange;
+
+ relocation = (symbol->value
+ + symbol->section->output_section->vma
+ + symbol->section->output_offset);
+ relocation += reloc_entry->addend;
+ relocation >>= 3;
+
+ x = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
+ x |= (((relocation & 0x7800) << 10)
+ | (relocation & 0x7ff));
+ bfd_put_32 (abfd, x, (bfd_byte *) data + reloc_entry->address);
+
+ if (relocation & ~(bfd_vma) 0x7fff)
+ return bfd_reloc_overflow;
+ return bfd_reloc_ok;
+}
+
+/* end-sanitize-sky */
/* Return the ISA for a MIPS e_flags value. */
static INLINE int
{
case E_MIPS_MACH_3900:
return bfd_mach_mips3900;
-
+
case E_MIPS_MACH_4010:
return bfd_mach_mips4010;
-
+
case E_MIPS_MACH_4100:
return bfd_mach_mips4100;
/* start-sanitize-vr4320 */
case E_MIPS_MACH_4320:
return bfd_mach_mips4320;
/* end-sanitize-vr4320 */
-
+
case E_MIPS_MACH_4650:
return bfd_mach_mips4650;
/* start-sanitize-tx49 */
case E_MIPS_MACH_4900:
return bfd_mach_mips4900;
/* end-sanitize-tx49 */
- /* start-sanitize-vr5400 */
-
+ /* start-sanitize-cygnus */
+ /* CYGNUS LOCAL vr5400/raeburn */
+
case E_MIPS_MACH_5400:
return bfd_mach_mips5400;
- /* end-sanitize-vr5400 */
+ /* end-sanitize-cygnus */
/* start-sanitize-r5900 */
-
+
case E_MIPS_MACH_5900:
return bfd_mach_mips5900;
/* end-sanitize-r5900 */
-
+
default:
switch (flags & EF_MIPS_ARCH)
{
case E_MIPS_ARCH_1:
return bfd_mach_mips3000;
break;
-
+
case E_MIPS_ARCH_2:
return bfd_mach_mips6000;
break;
-
+
case E_MIPS_ARCH_3:
return bfd_mach_mips4000;
break;
-
+
case E_MIPS_ARCH_4:
return bfd_mach_mips8000;
break;
struct elf_reloc_map {
bfd_reloc_code_real_type bfd_reloc_val;
- enum reloc_type elf_reloc_val;
+ enum elf_mips_reloc_type elf_reloc_val;
};
static CONST struct elf_reloc_map mips_reloc_map[] =
{ BFD_RELOC_MIPS_GOT_HI16, R_MIPS_GOT_HI16 },
{ BFD_RELOC_MIPS_GOT_LO16, R_MIPS_GOT_LO16 },
{ BFD_RELOC_MIPS_CALL_HI16, R_MIPS_CALL_HI16 },
- { BFD_RELOC_MIPS_CALL_LO16, R_MIPS_CALL_LO16 },
- /* start-sanitize-r5900 */
- { BFD_RELOC_MIPS15_S3, R_MIPS15_S3 },
- /* end-sanitize-r5900 */
+ { BFD_RELOC_MIPS_CALL_LO16, R_MIPS_CALL_LO16 }
};
/* Given a BFD reloc type, return a howto structure. */
return &elf_mips_howto_table[(int) mips_reloc_map[i].elf_reloc_val];
}
- /* We need to handle BFD_RELOC_CTOR specially.
-
- Select the right relocation (R_MIPS_32 or R_MIPS_64) based on the
- size of addresses on this architecture. */
- if (code == BFD_RELOC_CTOR)
+ switch (code)
{
+ default:
+ bfd_set_error (bfd_error_bad_value);
+ return NULL;
+
+ case BFD_RELOC_CTOR:
+ /* We need to handle BFD_RELOC_CTOR specially.
+ Select the right relocation (R_MIPS_32 or R_MIPS_64) based on the
+ size of addresses on this architecture. */
if (bfd_arch_bits_per_address (abfd) == 32)
return &elf_mips_howto_table[(int) R_MIPS_32];
else
return &elf_mips_ctor64_howto;
- }
- /* Special handling for the MIPS16 relocs, since they are made up
- reloc types with a large value. */
- if (code == BFD_RELOC_MIPS16_JMP)
- return &elf_mips16_jump_howto;
- else if (code == BFD_RELOC_MIPS16_GPREL)
- return &elf_mips16_gprel_howto;
+ case BFD_RELOC_MIPS16_JMP:
+ return &elf_mips16_jump_howto;
+ case BFD_RELOC_MIPS16_GPREL:
+ return &elf_mips16_gprel_howto;
+/* start-sanitize-r5900 */
+ case BFD_RELOC_MIPS15_S3:
+ return &elf_mips15_s3_howto;
+/* end-sanitize-r5900 */
/* start-sanitize-sky */
- else if (code == BFD_RELOC_MIPS_DVP_11_PCREL)
- return &elf_mips_dvp_11_pcrel_howto;
- else if (code == BFD_RELOC_MIPS_DVP_27_S4)
- return &elf_mips_dvp_27_s4_howto;
+ case BFD_RELOC_MIPS_DVP_11_PCREL:
+ return &elf_mips_dvp_11_pcrel_howto;
+ case BFD_RELOC_MIPS_DVP_27_S4:
+ return &elf_mips_dvp_27_s4_howto;
+ case BFD_RELOC_MIPS_DVP_11_S4:
+ return &elf_mips_dvp_11_s4_howto;
+ case BFD_RELOC_MIPS_DVP_U15_S3:
+ return &elf_mips_dvp_u15_s3_howto;
/* end-sanitize-sky */
-
- return NULL;
+ case BFD_RELOC_VTABLE_INHERIT:
+ return &elf_mips_gnu_vtinherit_howto;
+ case BFD_RELOC_VTABLE_ENTRY:
+ return &elf_mips_gnu_vtentry_howto;
+ }
}
/* Given a MIPS reloc type, fill in an arelent structure. */
unsigned int r_type;
r_type = ELF32_R_TYPE (dst->r_info);
- if (r_type == R_MIPS16_26)
- cache_ptr->howto = &elf_mips16_jump_howto;
- else if (r_type == R_MIPS16_GPREL)
- cache_ptr->howto = &elf_mips16_gprel_howto;
+ switch (r_type)
+ {
+ case R_MIPS16_26:
+ cache_ptr->howto = &elf_mips16_jump_howto;
+ break;
+ case R_MIPS16_GPREL:
+ cache_ptr->howto = &elf_mips16_gprel_howto;
+ break;
+/* start-sanitize-r5900 */
+ case R_MIPS15_S3:
+ cache_ptr->howto = &elf_mips15_s3_howto;
+ break;
+/* end-sanitize-r5900 */
/* start-sanitize-sky */
- else if (r_type == R_MIPS_DVP_11_PCREL)
- cache_ptr->howto = &elf_mips_dvp_11_pcrel_howto;
- else if (r_type == R_MIPS_DVP_27_S4)
- cache_ptr->howto = &elf_mips_dvp_27_s4_howto;
+ case R_MIPS_DVP_11_PCREL:
+ cache_ptr->howto = &elf_mips_dvp_11_pcrel_howto;
+ break;
+ case R_MIPS_DVP_27_S4:
+ cache_ptr->howto = &elf_mips_dvp_27_s4_howto;
+ break;
+ case R_MIPS_DVP_11_S4:
+ cache_ptr->howto = &elf_mips_dvp_11_s4_howto;
+ break;
+ case R_MIPS_DVP_U15_S3:
+ cache_ptr->howto = &elf_mips_dvp_u15_s3_howto;
+ break;
/* end-sanitize-sky */
- else
- {
+ case R_MIPS_GNU_VTINHERIT:
+ cache_ptr->howto = &elf_mips_gnu_vtinherit_howto;
+ break;
+ case R_MIPS_GNU_VTENTRY:
+ cache_ptr->howto = &elf_mips_gnu_vtentry_howto;
+ break;
+
+ default:
BFD_ASSERT (r_type < (unsigned int) R_MIPS_max);
cache_ptr->howto = &elf_mips_howto_table[r_type];
+ break;
}
/* The addend for a GPREL16 or LITERAL relocation comes from the GP
_bfd_mips_elf_object_p (abfd)
bfd *abfd;
{
- bfd_default_set_arch_mach (abfd, bfd_arch_mips,
+ bfd_default_set_arch_mach (abfd, bfd_arch_mips,
elf_mips_mach (elf_elfheader (abfd)->e_flags));
return true;
}
case bfd_mach_mips3000:
val = E_MIPS_ARCH_1;
break;
-
+
case bfd_mach_mips3900:
val = E_MIPS_ARCH_1 | E_MIPS_MACH_3900;
break;
-
+
case bfd_mach_mips6000:
val = E_MIPS_ARCH_2;
break;
val = E_MIPS_ARCH_3 | E_MIPS_MACH_4900;
break;
/* end-sanitize-tx49 */
- /* start-sanitize-vr5400 */
+ /* start-sanitize-cygnus */
+ /* CYGNUS LOCAL vr5400/raeburn */
case bfd_mach_mips5400:
val = E_MIPS_ARCH_3 | E_MIPS_MACH_5400;
break;
- /* end-sanitize-vr5400 */
+ /* end-sanitize-cygnus */
/* start-sanitize-r5900 */
case bfd_mach_mips5900:
}
/* Compare the ISA's. */
- if ((new_flags & (EF_MIPS_ARCH | EF_MIPS_MACH))
+ if ((new_flags & (EF_MIPS_ARCH | EF_MIPS_MACH))
!= (old_flags & (EF_MIPS_ARCH | EF_MIPS_MACH)))
{
/* If either has no machine specified, just compare the general isa's. */
/* Don't warn about mixing -mips1 and -mips2 code, or mixing -mips3
and -mips4 code. They will normally use the same data sizes and
calling conventions. */
-
+
new_isa = elf_mips_isa (new_flags);
old_isa = elf_mips_isa (old_flags);
if ((new_isa == 1 || new_isa == 2)
{
(*_bfd_error_handler)
(_("%s: ISA mismatch (%d) with previous modules (%d)"),
- bfd_get_filename (ibfd),
- elf_mips_mach (new_flags),
+ bfd_get_filename (ibfd),
+ elf_mips_mach (new_flags),
elf_mips_mach (old_flags));
ok = false;
}
-
+
new_flags &= ~ (EF_MIPS_ARCH | EF_MIPS_MACH);
old_flags &= ~ (EF_MIPS_ARCH | EF_MIPS_MACH);
}
switch (hdr->sh_type)
{
case SHT_MIPS_LIBLIST:
- if (strcmp (name, _(".liblist")) != 0)
+ if (strcmp (name, ".liblist") != 0)
return false;
break;
case SHT_MIPS_MSYM:
else if (strcmp (name, SHNAME_DVP_OVERLAY_TABLE) == 0)
{
hdr->sh_type = SHT_DVP_OVERLAY_TABLE;
- hdr->sh_entsize = sizeof (Elf64_Dvp_External_Overlay);
+ hdr->sh_entsize = sizeof (Elf32_Dvp_External_Overlay);
/* The sh_link field is set in final_write_processing. */
}
else if (strcmp (name, SHNAME_DVP_OVERLAY_STRTAB) == 0)
asection *msec;
if (_bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
- filename_ptr, functionname_ptr,
+ filename_ptr, functionname_ptr,
line_ptr))
return true;
{
output_section = sec->output_section;
if (output_section != NULL)
- h->esym.asym.value = (h->root.plt_offset
+ h->esym.asym.value = (h->root.plt.offset
+ sec->output_offset
+ output_section->vma);
else
bfd_reloc_status_type r;
r_type = ELF32_R_TYPE (rel->r_info);
+ if (r_type == R_MIPS_GNU_VTINHERIT
+ || r_type == R_MIPS_GNU_VTENTRY)
+ continue;
if ((r_type < 0 || r_type >= (int) R_MIPS_max)
+/* start-sanitize-r5900 */
+ && r_type != R_MIPS15_S3
+/* end-sanitize-r5900 */
/* start-sanitize-sky */
&& r_type != R_MIPS_DVP_11_PCREL
&& r_type != R_MIPS_DVP_27_S4
+ && r_type != R_MIPS_DVP_11_S4
+ && r_type != R_MIPS_DVP_U15_S3
/* end-sanitize-sky */
&& r_type != R_MIPS16_26
&& r_type != R_MIPS16_GPREL)
howto = &elf_mips16_jump_howto;
else if (r_type == R_MIPS16_GPREL)
howto = &elf_mips16_gprel_howto;
+/* start-sanitize-r5900 */
+ else if (r_type == R_MIPS15_S3)
+ howto = &elf_mips15_s3_howto;
+/* end-sanitize-r5900 */
/* start-sanitize-sky */
else if (r_type == R_MIPS_DVP_11_PCREL)
howto = &elf_mips_dvp_11_pcrel_howto;
else if (r_type == R_MIPS_DVP_27_S4)
howto = &elf_mips_dvp_27_s4_howto;
+ else if (r_type == R_MIPS_DVP_11_S4)
+ howto = &elf_mips_dvp_11_s4_howto;
+ else if (r_type == R_MIPS_DVP_U15_S3)
+ howto = &elf_mips_dvp_u15_s3_howto;
/* end-sanitize-sky */
else
howto = elf_mips_howto_table + r_type;
/* This symbol must be registered as a global symbol
having the corresponding got entry. */
- BFD_ASSERT (h->got_offset != (bfd_vma) -1);
+ BFD_ASSERT (h->got.offset != (bfd_vma) -1);
offset = (h->dynindx - g->global_gotsym + g->local_gotno) * 4;
BFD_ASSERT (g->local_gotno <= offset
/* This must be a global symbol with a got entry. The
next reloc must be the corresponding LO16 reloc. */
- BFD_ASSERT (h != NULL && h->got_offset != (bfd_vma) -1);
+ BFD_ASSERT (h != NULL && h->got.offset != (bfd_vma) -1);
BFD_ASSERT ((rel + 1) < relend);
BFD_ASSERT ((int) ELF32_R_TYPE ((rel + 1)->r_info)
== (r_type == R_MIPS_CALL_HI16
contents + rel->r_offset + 2);
}
}
+ /* start-sanitize-sky */
+ else if (r_type == R_MIPS_DVP_U15_S3)
+ {
+ if (rel->r_offset > input_section->_raw_size)
+ r = bfd_reloc_outofrange;
+ else
+ {
+ bfd_vma x;
+
+ relocation += rel->r_addend;
+ relocation >>= 3;
+
+ x = bfd_get_32 (input_bfd, contents + rel->r_offset);
+ relocation += ((x & (0xf << 21)) >> 10) + (x & 0x7ff);
+ x &= ~ ((0xf << 21) | 0x7ff);
+ x |= (((relocation & 0x7800) << 10)
+ | (relocation & 0x7ff));
+ bfd_put_32 (input_bfd, x, contents + rel->r_offset);
+
+ if (relocation & ~ (bfd_vma) 0x7fff)
+ r = bfd_reloc_overflow;
+ else
+ r = bfd_reloc_ok;
+ }
+ }
+ /* end-sanitize-sky */
else
r = _bfd_final_link_relocate (howto, input_bfd, input_section,
contents, rel->r_offset,
return false;
}
- if (h->got_offset != (bfd_vma) -1)
+ if (h->got.offset != (bfd_vma) -1)
{
/* We have already allocated space in the .got. */
break;
g->global_gotsym = h->dynindx;
/* Make this symbol to have the corresponding got entry. */
- h->got_offset = 0;
+ h->got.offset = 0;
/* We need a stub, not a plt entry for the undefined
function. But we record it as if it needs plt. See
return false;
}
- if (h->got_offset != (bfd_vma) -1)
+ if (h->got.offset != (bfd_vma) -1)
{
/* We have already allocated space in the .got. */
break;
g->global_gotsym = h->dynindx;
/* Make this symbol to be the global got symbol. */
- h->got_offset = 0;
+ h->got.offset = 0;
}
break;
sizeof (Elf32_External_crinfo);
break;
+ /* This relocation describes the C++ object vtable hierarchy.
+ Reconstruct it for later use during GC. */
+ case R_MIPS_GNU_VTINHERIT:
+ if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+ return false;
+ break;
+
+ /* This relocation describes which C++ vtable entries are actually
+ used. Record for later use during GC. */
+ case R_MIPS_GNU_VTENTRY:
+ if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_offset))
+ return false;
+ break;
+
default:
break;
}
return true;
}
+/* Return the section that should be marked against GC for a given
+ relocation. */
+
+static asection *
+mips_elf_gc_mark_hook (abfd, info, rel, h, sym)
+ bfd *abfd;
+ struct bfd_link_info *info;
+ Elf_Internal_Rela *rel;
+ struct elf_link_hash_entry *h;
+ Elf_Internal_Sym *sym;
+{
+ /* ??? Do mips16 stub sections need to be handled special? */
+
+ if (h != NULL)
+ {
+ switch (ELF32_R_TYPE (rel->r_info))
+ {
+ case R_MIPS_GNU_VTINHERIT:
+ case R_MIPS_GNU_VTENTRY:
+ break;
+
+ default:
+ switch (h->root.type)
+ {
+ case bfd_link_hash_defined:
+ case bfd_link_hash_defweak:
+ return h->root.u.def.section;
+
+ case bfd_link_hash_common:
+ return h->root.u.c.p->section;
+ }
+ }
+ }
+ else
+ {
+ if (!(elf_bad_symtab (abfd)
+ && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
+ && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
+ && sym->st_shndx != SHN_COMMON))
+ {
+ return bfd_section_from_elf_index (abfd, sym->st_shndx);
+ }
+ }
+
+ return NULL;
+}
+
+/* Update the got entry reference counts for the section being removed. */
+
+static boolean
+mips_elf_gc_sweep_hook (abfd, info, sec, relocs)
+ bfd *abfd;
+ struct bfd_link_info *info;
+ asection *sec;
+ const Elf_Internal_Rela *relocs;
+{
+#if 0
+ Elf_Internal_Shdr *symtab_hdr;
+ struct elf_link_hash_entry **sym_hashes;
+ bfd_signed_vma *local_got_refcounts;
+ const Elf_Internal_Rela *rel, *relend;
+ unsigned long r_symndx;
+ struct elf_link_hash_entry *h;
+
+ symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+ sym_hashes = elf_sym_hashes (abfd);
+ local_got_refcounts = elf_local_got_refcounts (abfd);
+
+ relend = relocs + sec->reloc_count;
+ for (rel = relocs; rel < relend; rel++)
+ switch (ELF32_R_TYPE (rel->r_info))
+ {
+ case R_MIPS_GOT16:
+ case R_MIPS_CALL16:
+ case R_MIPS_CALL_HI16:
+ case R_MIPS_CALL_LO16:
+ case R_MIPS_GOT_HI16:
+ case R_MIPS_GOT_LO16:
+ /* ??? It would seem that the existing MIPS code does no sort
+ of reference counting or whatnot on its GOT and PLT entries,
+ so it is not possible to garbage collect them at this time. */
+ break;
+
+ default:
+ break;
+ }
+#endif
+
+ return true;
+}
+
+
/* Adjust a symbol defined by a dynamic object and referenced by a
regular object. The current definition is in some section of the
dynamic object, but we're not including those sections. We have to
h->root.u.def.value = s->_raw_size;
/* XXX Write this stub address somewhere. */
- h->plt_offset = s->_raw_size;
+ h->plt.offset = s->_raw_size;
/* Make room for this stub code. */
s->_raw_size += MIPS_FUNCTION_STUB_SIZE;
if (strncmp (name, ".rel", 4) == 0)
{
if (s->_raw_size == 0)
- strip = true;
+ {
+ /* We only strip the section if the output section name
+ has the same name. Otherwise, there might be several
+ input sections for this output section. FIXME: This
+ code is probably not needed these days anyhow, since
+ the linker now does not create empty output sections. */
+ if (s->output_section != NULL
+ && strcmp (name,
+ bfd_get_section_name (s->output_section->owner,
+ s->output_section)) == 0)
+ strip = true;
+ }
else
{
const char *outname;
dynobj = elf_hash_table (info)->dynobj;
gval = sym->st_value;
- if (h->plt_offset != (bfd_vma) -1)
+ if (h->plt.offset != (bfd_vma) -1)
{
asection *s;
bfd_byte *p;
p += 4;
bfd_put_32 (output_bfd, STUB_LI16 + h->dynindx, p);
- BFD_ASSERT (h->plt_offset <= s->_raw_size);
- memcpy (s->contents + h->plt_offset, stub, MIPS_FUNCTION_STUB_SIZE);
+ BFD_ASSERT (h->plt.offset <= s->_raw_size);
+ memcpy (s->contents + h->plt.offset, stub, MIPS_FUNCTION_STUB_SIZE);
- /* Mark the symbol as undefined. plt_offset != -1 occurs
+ /* Mark the symbol as undefined. plt.offset != -1 occurs
only for the referenced symbol. */
sym->st_shndx = SHN_UNDEF;
/* The run-time linker uses the st_value field of the symbol
to reset the global offset table entry for this external
to its stub address when unlinking a shared object. */
- gval = s->output_section->vma + s->output_offset + h->plt_offset;
+ gval = s->output_section->vma + s->output_offset + h->plt.offset;
sym->st_value = gval;
}
/* This symbol has an entry in the global offset table. Set its
value to the corresponding got entry, if needed. */
- if (h->got_offset == (bfd_vma) -1)
+ if (h->got.offset == (bfd_vma) -1)
{
offset = (h->dynindx - g->global_gotsym + g->local_gotno) * 4;
BFD_ASSERT (g->local_gotno * 4 <= offset
#define elf_backend_collect true
#define elf_backend_type_change_ok true
+#define elf_backend_can_gc_sections true
#define elf_info_to_howto 0
#define elf_info_to_howto_rel mips_info_to_howto_rel
#define elf_backend_sym_is_global mips_elf_sym_is_global
mips_elf_finish_dynamic_symbol
#define elf_backend_finish_dynamic_sections \
mips_elf_finish_dynamic_sections
+#define elf_backend_gc_mark_hook mips_elf_gc_mark_hook
+#define elf_backend_gc_sweep_hook mips_elf_gc_sweep_hook
+
+#define elf_backend_got_header_size (4*MIPS_RESERVED_GOTNO)
+#define elf_backend_plt_header_size 0
#include "elf32-target.h"