/* MIPS-specific support for 32-bit ELF
- Copyright 1993, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
+ Copyright 1993, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
Most of the information added by Ian Lance Taylor, Cygnus Support,
<ian@cygnus.com>.
static int mips_elf_additional_program_headers PARAMS ((bfd *));
static boolean mips_elf_modify_segment_map PARAMS ((bfd *));
static INLINE int elf_mips_isa PARAMS ((flagword));
+static INLINE int elf_mips_mach PARAMS ((flagword));
static boolean mips_elf32_section_from_shdr
PARAMS ((bfd *, Elf32_Internal_Shdr *, char *));
static boolean mips_elf32_section_processing
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_11_PCREL = 120,
+ R_MIPS_DVP_27_S4 = 121
/* end-sanitize-sky */
};
true, /* partial_inplace */
0x0000ffff, /* src_mask */
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 */
+
};
/* The reloc used for BFD_RELOC_CTOR when doing a 64 bit link. This
false); /* pcrel_offset */
/* start-sanitize-sky */
-/* DVP relocations. */
-static reloc_howto_type elf_mips_dvp_11_pcrel_howto =
+/* DVP relocations.
+ Note that partial_inplace and pcrel_offset are backwards from the
+ mips port. This is intentional as it seems more reasonable. */
+static reloc_howto_type elf_mips_dvp_11_pcrel_howto =
HOWTO (R_MIPS_DVP_11_PCREL, /* type */
3, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
complain_overflow_signed, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_MIPS_DVP_11_PCREL", /* name */
- true, /* partial_inplace */
+ false, /* partial_inplace */
0x7ff, /* src_mask */
0x7ff, /* dst_mask */
true); /* pcrel_offset */
+static reloc_howto_type elf_mips_dvp_27_s4_howto =
+ HOWTO (R_MIPS_DVP_27_S4, /* type */
+ 4, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 27, /* bitsize */
+ false, /* pc_relative */
+ 4, /* bitpos */
+ complain_overflow_unsigned, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_DVP_27_S4", /* name */
+ false, /* partial_inplace */
+ 0x7ffffff0, /* src_mask */
+ 0x7ffffff0, /* dst_mask */
+ false); /* pcrel_offset */
/* end-sanitize-sky */
/* Do a R_MIPS_HI16 relocation. This has to be done in combination
*pgp = 4;
_bfd_set_gp_value (output_bfd, *pgp);
*error_message =
- (char *) "GP relative relocation when _gp not defined";
+ (char *) _("GP relative relocation when _gp not defined");
return bfd_reloc_dangerous;
}
}
&& reloc_entry->addend == 0)
{
*error_message = (char *)
- "32bits gp relative relocation occurs for an external symbol";
+ _("32bits gp relative relocation occurs for an external symbol");
return bfd_reloc_outofrange;
}
if (! warned)
(*_bfd_error_handler)
- ("Linking mips16 objects into %s format is not supported",
+ (_("Linking mips16 objects into %s format is not supported"),
bfd_get_target (input_section->output_section->owner));
warned = true;
}
return 4;
}
+/* Return the MACH for a MIPS e_flags value. */
+
+static INLINE int
+elf_mips_mach (flags)
+ flagword flags;
+{
+ switch (flags & EF_MIPS_MACH)
+ {
+ 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 */
+
+ case E_MIPS_MACH_5400:
+ return bfd_mach_mips5400;
+ /* end-sanitize-vr5400 */
+ /* start-sanitize-r5900 */
+
+ case E_MIPS_MACH_5900:
+ return bfd_mach_mips5900;
+ /* end-sanitize-r5900 */
+
+ default:
+ switch (flags & EF_MIPS_ARCH)
+ {
+ default:
+ 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;
+ }
+ }
+
+ return 0;
+}
+
/* A mapping from BFD reloc types to MIPS ELF reloc types. */
struct elf_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 }
+ { BFD_RELOC_MIPS_CALL_LO16, R_MIPS_CALL_LO16 },
+ /* start-sanitize-r5900 */
+ { BFD_RELOC_MIPS15_S3, R_MIPS15_S3 },
+ /* end-sanitize-r5900 */
};
/* 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. If this is a mips3
- file, then we assume that we are using 64 bit addresses, and use
- R_MIPS_64. Otherwise, we use R_MIPS_32. */
+ /* 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)
{
- if (elf_mips_isa (elf_elfheader (abfd)->e_flags) < 3)
+ if (bfd_arch_bits_per_address (abfd) == 32)
return &elf_mips_howto_table[(int) R_MIPS_32];
else
return &elf_mips_ctor64_howto;
/* 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;
/* end-sanitize-sky */
return NULL;
/* 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;
/* end-sanitize-sky */
else
{
_bfd_mips_elf_object_p (abfd)
bfd *abfd;
{
- switch (elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH)
- {
- default:
- case E_MIPS_ARCH_1:
- (void) bfd_default_set_arch_mach (abfd, bfd_arch_mips, 3000);
- break;
-
- case E_MIPS_ARCH_2:
- (void) bfd_default_set_arch_mach (abfd, bfd_arch_mips, 6000);
- break;
-
- case E_MIPS_ARCH_3:
- (void) bfd_default_set_arch_mach (abfd, bfd_arch_mips, 4000);
- break;
-
- case E_MIPS_ARCH_4:
- (void) bfd_default_set_arch_mach (abfd, bfd_arch_mips, 8000);
- break;
- }
-
+ bfd_default_set_arch_mach (abfd, bfd_arch_mips,
+ elf_mips_mach (elf_elfheader (abfd)->e_flags));
return true;
}
switch (bfd_get_mach (abfd))
{
- case 3000:
+ default:
+ case bfd_mach_mips3000:
val = E_MIPS_ARCH_1;
break;
-
- case 6000:
+
+ case bfd_mach_mips3900:
+ val = E_MIPS_ARCH_1 | E_MIPS_MACH_3900;
+ break;
+
+ case bfd_mach_mips6000:
val = E_MIPS_ARCH_2;
break;
- case 4000:
+ case bfd_mach_mips4000:
val = E_MIPS_ARCH_3;
break;
- case 8000:
- val = E_MIPS_ARCH_4;
+ case bfd_mach_mips4010:
+ val = E_MIPS_ARCH_3 | E_MIPS_MACH_4010;
break;
- default:
- val = 0;
+ case bfd_mach_mips4100:
+ val = E_MIPS_ARCH_3 | E_MIPS_MACH_4100;
+ break;
+ /* start-sanitize-vr4320 */
+
+ case bfd_mach_mips4320:
+ val = E_MIPS_ARCH_3 | E_MIPS_MACH_4320;
+ break;
+ /* end-sanitize-vr4320 */
+
+ case bfd_mach_mips4650:
+ val = E_MIPS_ARCH_3 | E_MIPS_MACH_4650;
+ break;
+ /* start-sanitize-tx49 */
+
+ case bfd_mach_mips4900:
+ val = E_MIPS_ARCH_3 | E_MIPS_MACH_4900;
+ break;
+ /* end-sanitize-tx49 */
+ /* start-sanitize-vr5400 */
+
+ case bfd_mach_mips5400:
+ val = E_MIPS_ARCH_3 | E_MIPS_MACH_5400;
+ break;
+ /* end-sanitize-vr5400 */
+ /* start-sanitize-r5900 */
+
+ case bfd_mach_mips5900:
+ val = E_MIPS_ARCH_3 | E_MIPS_MACH_5900;
+ break;
+ /* end-sanitize-r5900 */
+
+ case bfd_mach_mips8000:
+ val = E_MIPS_ARCH_4;
break;
}
- elf_elfheader (abfd)->e_flags &=~ EF_MIPS_ARCH;
+ elf_elfheader (abfd)->e_flags &= ~ (EF_MIPS_ARCH | EF_MIPS_MACH);
elf_elfheader (abfd)->e_flags |= val;
- /* Set the sh_info field for .gptab sections. */
+ /* Set the sh_info field for .gptab sections and other appropriate
+ info for each special section. */
for (i = 1, hdrpp = elf_elfsections (abfd) + 1;
i < elf_elfheader (abfd)->e_shnum;
i++, hdrpp++)
BFD_ASSERT (sec != NULL);
(*hdrpp)->sh_link = elf_section_data (sec)->this_idx;
break;
+
+/* start-sanitize-sky */
+ case SHT_DVP_OVERLAY_TABLE:
+ /* ??? This may not be technically necessary, just going with
+ the flow ... */
+ sec = bfd_get_section_by_name (abfd, SHNAME_DVP_OVERLAY_STRTAB);
+ if (sec != NULL)
+ (*hdrpp)->sh_link = elf_section_data (sec)->this_idx;
+ break;
+/* end-sanitize-sky */
}
}
}
if (ibfd->xvec->byteorder != obfd->xvec->byteorder
&& obfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN)
{
- (*_bfd_error_handler)
- ("%s: compiled for a %s endian system and target is %s endian",
- bfd_get_filename (ibfd),
- bfd_big_endian (ibfd) ? "big" : "little",
- bfd_big_endian (obfd) ? "big" : "little");
+ const char *msg;
+
+ if (bfd_big_endian (ibfd))
+ msg = _("%s: compiled for a big endian system and target is little endian");
+ else
+ msg = _("%s: compiled for a little endian system and target is big endian");
+
+ (*_bfd_error_handler) (msg, bfd_get_filename (ibfd));
bfd_set_error (bfd_error_wrong_format);
return false;
new_flags &= ~EF_MIPS_PIC;
old_flags &= ~EF_MIPS_PIC;
(*_bfd_error_handler)
- ("%s: linking PIC files with non-PIC files",
+ (_("%s: linking PIC files with non-PIC files"),
bfd_get_filename (ibfd));
ok = false;
}
new_flags &= ~EF_MIPS_CPIC;
old_flags &= ~EF_MIPS_CPIC;
(*_bfd_error_handler)
- ("%s: linking abicalls files with non-abicalls files",
+ (_("%s: linking abicalls files with non-abicalls files"),
bfd_get_filename (ibfd));
ok = false;
}
- /* 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. */
- if ((new_flags & EF_MIPS_ARCH) != (old_flags & EF_MIPS_ARCH))
+ /* Compare the ISA's. */
+ if ((new_flags & (EF_MIPS_ARCH | EF_MIPS_MACH))
+ != (old_flags & (EF_MIPS_ARCH | EF_MIPS_MACH)))
{
- int new_isa, old_isa;
+ /* If either has no machine specified, just compare the general isa's. */
+ if ( !(new_flags & EF_MIPS_MACH) || !(old_flags & EF_MIPS_MACH))
+ {
+ int new_isa, old_isa;
+
+ /* 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)
+ ? (old_isa != 1 && old_isa != 2)
+ : (old_isa == 1 || old_isa == 2))
+ {
+ (*_bfd_error_handler)
+ (_("%s: ISA mismatch (-mips%d) with previous modules (-mips%d)"),
+ bfd_get_filename (ibfd), new_isa, old_isa);
+ ok = false;
+ }
+ }
- new_isa = elf_mips_isa (new_flags);
- old_isa = elf_mips_isa (old_flags);
- if ((new_isa == 1 || new_isa == 2)
- ? (old_isa != 1 && old_isa != 2)
- : (old_isa == 1 || old_isa == 2))
+ else
{
(*_bfd_error_handler)
- ("%s: ISA mismatch (-mips%d) with previous modules (-mips%d)",
- bfd_get_filename (ibfd), new_isa, old_isa);
+ (_("%s: ISA mismatch (%d) with previous modules (%d)"),
+ bfd_get_filename (ibfd),
+ elf_mips_mach (new_flags),
+ elf_mips_mach (old_flags));
ok = false;
}
-
- new_flags &= ~ EF_MIPS_ARCH;
- old_flags &= ~ EF_MIPS_ARCH;
+
+ new_flags &= ~ (EF_MIPS_ARCH | EF_MIPS_MACH);
+ old_flags &= ~ (EF_MIPS_ARCH | EF_MIPS_MACH);
}
/* Warn about any other mismatches */
if (new_flags != old_flags)
{
(*_bfd_error_handler)
- ("%s: uses different e_flags (0x%lx) fields than previous modules (0x%lx)",
+ (_("%s: uses different e_flags (0x%lx) fields than previous modules (0x%lx)"),
bfd_get_filename (ibfd), (unsigned long) new_flags,
(unsigned long) old_flags);
ok = false;
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:
sizeof ".MIPS.post_rel" - 1) != 0)
return false;
break;
+/* start-sanitize-sky */
+ case SHT_DVP_OVERLAY_TABLE:
+ if (strcmp (name, SHNAME_DVP_OVERLAY_TABLE) !=0)
+ return false;
+ break;
+ case SHT_DVP_OVERLAY:
+ if (strncmp (name, SHNAME_DVP_OVERLAY_PREFIX,
+ sizeof (SHNAME_DVP_OVERLAY_PREFIX) - 1) !=0)
+ return false;
+ break;
+/* end-sanitize-sky */
default:
return false;
}
hdr->sh_flags |= SHF_MIPS_NOSTRIP;
/* The sh_link field is set in final_write_processing. */
}
+/* start-sanitize-sky */
+ else if (strcmp (name, SHNAME_DVP_OVERLAY_TABLE) == 0)
+ {
+ hdr->sh_type = SHT_DVP_OVERLAY_TABLE;
+ hdr->sh_entsize = sizeof (Elf64_Dvp_External_Overlay);
+ /* The sh_link field is set in final_write_processing. */
+ }
+ else if (strcmp (name, SHNAME_DVP_OVERLAY_STRTAB) == 0)
+ hdr->sh_type = SHT_STRTAB;
+ else if (strncmp (name, SHNAME_DVP_OVERLAY_PREFIX,
+ sizeof (SHNAME_DVP_OVERLAY_PREFIX) - 1) == 0)
+ hdr->sh_type = SHT_DVP_OVERLAY;
+/* end-sanitize-sky */
return true;
}
unsigned long i;
PDR pdr;
SYMR sym;
- const char *no_name_func = "static procedure (no name)";
+ const char *no_name_func = _("static procedure (no name)");
epdr = NULL;
rpdr = NULL;
esym.asym.st = stLocal;
esym.asym.reserved = 0;
esym.asym.index = indexNil;
+ last = 0;
for (i = 0; i < 8; i++)
{
esym.asym.sc = sc[i];
else
{
(*_bfd_error_handler)
- ("%s: illegal section name `%s'",
+ (_("%s: illegal section name `%s'"),
bfd_get_filename (abfd), o->name);
bfd_set_error (bfd_error_nonrepresentable_section);
return false;
if (assigned_gotno >= g->local_gotno)
{
(*_bfd_error_handler)
- ("more got entries are needed for hipage relocations");
+ (_("more got entries are needed for hipage relocations"));
bfd_set_error (bfd_error_bad_value);
return false;
}
if ((r_type < 0 || r_type >= (int) R_MIPS_max)
/* start-sanitize-sky */
&& r_type != R_MIPS_DVP_11_PCREL
+ && r_type != R_MIPS_DVP_27_S4
/* end-sanitize-sky */
&& r_type != R_MIPS16_26
&& r_type != R_MIPS16_GPREL)
/* 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;
/* end-sanitize-sky */
else
howto = elf_mips_howto_table + r_type;
{
if (! ((*info->callbacks->reloc_dangerous)
(info,
- "GP relative relocation when GP not defined",
+ _("GP relative relocation when GP not defined"),
input_bfd, input_section,
rel->r_offset)))
return false;
{
if (! ((*info->callbacks->reloc_dangerous)
(info,
- "_gp_disp used when GP not defined",
+ _("_gp_disp used when GP not defined"),
input_bfd, input_section,
rel->r_offset)))
return false;
next reloc must be the corresponding LO16 reloc. */
BFD_ASSERT (h != NULL && h->got_offset != (bfd_vma) -1);
BFD_ASSERT ((rel + 1) < relend);
- BFD_ASSERT (ELF32_R_TYPE ((rel + 1)->r_info)
+ BFD_ASSERT ((int) ELF32_R_TYPE ((rel + 1)->r_info)
== (r_type == R_MIPS_CALL_HI16
- ? R_MIPS_CALL_LO16
- : R_MIPS_GOT_LO16));
+ ? (int) R_MIPS_CALL_LO16
+ : (int) R_MIPS_GOT_LO16));
offset = (h->dynindx - g->global_gotsym + g->local_gotno) * 4;
BFD_ASSERT (g->local_gotno <= offset
&& ((insn >> 26) & 0x3f) != 0x1d)
{
(*_bfd_error_handler)
- ("%s: %s+0x%lx: jump to mips16 routine which is not jal",
+ (_("%s: %s+0x%lx: jump to mips16 routine which is not jal"),
bfd_get_filename (input_bfd),
input_section->name,
(unsigned long) rel->r_offset);
r = bfd_reloc_overflow;
}
+ /* Don't bother to report a relocation overflow for a call
+ to a weak undefined symbol with a value of zero. This
+ permits us to use
+ if (!f) f();
+ even if we aren't in range to call address zero. */
+ if (r == bfd_reloc_overflow
+ && (r_type == R_MIPS16_26 || r_type == R_MIPS_26)
+ && relocation + addend == 0
+ && h != NULL
+ && h->root.type == bfd_link_hash_undefweak)
+ r = bfd_reloc_ok;
+
if (SGI_COMPAT (abfd)
&& scpt != NULL
&& (input_section->flags & SEC_ALLOC) != 0)
if (h == NULL)
{
(*_bfd_error_handler)
- ("%s: CALL16 reloc at 0x%lx not against global symbol",
+ (_("%s: CALL16 reloc at 0x%lx not against global symbol"),
bfd_get_filename (abfd), (unsigned long) rel->r_offset);
bfd_set_error (bfd_error_bad_value);
return false;
sym.st_other = 0;
i = 0;
+ last = 0;
+ dindx = 0;
while ((name = *namep++) != NULL)
{
s = bfd_get_section_by_name (output_bfd, name);