Support all of the V.4 relocations
[deliverable/binutils-gdb.git] / bfd / mipsbsd.c
index 020e5a2993efab4534951ec727d154414f60d313..9c610b430a1418c81d1b94e2c76ee32e4859fb38 100644 (file)
@@ -19,7 +19,6 @@ along with this program; if not, write to the Free Software
 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #define BYTES_IN_WORD 4
-#define ARCH 32
 /* #define ENTRY_CAN_BE_ZERO */
 #define N_HEADER_IN_TEXT(x) 1
 #define N_SHARED_LIB(x) 0
@@ -59,6 +58,7 @@ static boolean MY(write_object_contents) PARAMS ((bfd *abfd));
 
 #define MY_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
 #define MY_bfd_link_add_symbols _bfd_generic_link_add_symbols
+#define MY_final_link_callback unused
 #define MY_bfd_final_link _bfd_generic_final_link
 
 #define MY_backend_data &MY(backend_data)
@@ -177,6 +177,56 @@ MY(write_object_contents) (abfd)
 #define MIPS_RELOC_HI16_S      4
 #define MIPS_RELOC_LO16                5
 
+/*
+ * This is only called when performing a BFD_RELOC_MIPS_JMP relocation.
+ * The jump destination address is formed from the upper 4 bits of the
+ * "current" program counter concatenated with the jump instruction's
+ * 26 bit field and two trailing zeros.
+ * If the destination address is not in the same segment as the "current"
+ * program counter, then we need to signal an error.
+ */
+static bfd_reloc_status_type
+mips_fix_jmp_addr (abfd,reloc_entry,symbol,data,input_section,output_bfd)
+     bfd *abfd;
+     arelent *reloc_entry;
+     struct symbol_cache_entry *symbol;
+     PTR data;
+     asection *input_section;
+     bfd *output_bfd;
+{
+  bfd_vma relocation, pc;
+  /* If this is a partial relocation, just continue. */
+  if (output_bfd != (bfd *)NULL)
+    return bfd_reloc_continue;
+
+  /* If this is an undefined symbol, return error */
+  if (bfd_is_und_section (symbol->section)
+      && (symbol->flags & BSF_WEAK) == 0)
+    return bfd_reloc_undefined;
+
+  /* 
+   * Work out which section the relocation is targetted at and the
+   * initial relocation command value.
+   */
+  if (bfd_is_com_section (symbol->section))
+    relocation = 0;
+  else
+    relocation = symbol->value;
+
+  relocation += symbol->section->output_section->vma;
+  relocation += symbol->section->output_offset;
+  relocation += reloc_entry->addend;
+
+  pc = input_section->output_section->vma + input_section->output_offset +
+    reloc_entry->address + 4;
+
+  if ((relocation & 0xF0000000) != (pc & 0xF0000000))
+    return bfd_reloc_overflow;
+
+  return bfd_reloc_continue;
+}
+
 /*
  * This is only called when performing a BFD_RELOC_HI16_S relocation.
  * We need to see if bit 15 is set in the result. If it is, we add
@@ -204,11 +254,16 @@ mips_fix_hi16_s (abfd, reloc_entry, symbol, data, input_section,
   if (output_bfd != (bfd *)NULL)
     return bfd_reloc_continue;
 
+  /* If this is an undefined symbol, return error */
+  if (bfd_is_und_section (symbol->section)
+      && (symbol->flags & BSF_WEAK) == 0)
+    return bfd_reloc_undefined;
+
   /* 
    * Work out which section the relocation is targetted at and the
    * initial relocation command value.
    */
-  if (symbol->section == &bfd_com_section)
+  if (bfd_is_com_section (symbol->section))
     relocation = 0;
   else
     relocation = symbol->value;
@@ -226,16 +281,17 @@ mips_fix_hi16_s (abfd, reloc_entry, symbol, data, input_section,
 static reloc_howto_type mips_howto_table_ext[] = {
   {MIPS_RELOC_32,      0, 2, 32, false, 0,  complain_overflow_bitfield, 0,
        "32",       false, 0, 0xffffffff, false},
-  {MIPS_RELOC_JMP,     2, 2, 26, false, 0, complain_overflow_bitfield, 0,
+  {MIPS_RELOC_JMP,     2, 2, 26, false, 0, complain_overflow_dont,
+       mips_fix_jmp_addr,
        "MIPS_JMP", false, 0, 0x03ffffff, false},
-  {MIPS_RELOC_WDISP16, 2, 1, 16, true,  0, complain_overflow_signed, 0,
+  {MIPS_RELOC_WDISP16, 2, 2, 16, true,  0, complain_overflow_signed, 0,
        "WDISP16",  false, 0, 0x0000ffff, false},
-  {MIPS_RELOC_HI16,   16, 1, 16, false, 0, complain_overflow_bitfield, 0,
+  {MIPS_RELOC_HI16,   16, 2, 16, false, 0, complain_overflow_bitfield, 0,
        "HI16",     false, 0, 0x0000ffff, false},
-  {MIPS_RELOC_HI16_S, 16, 1, 16, false, 0, complain_overflow_bitfield,
+  {MIPS_RELOC_HI16_S, 16, 2, 16, false, 0, complain_overflow_bitfield,
         mips_fix_hi16_s,
         "HI16_S",   false, 0, 0x0000ffff, false},
-  {MIPS_RELOC_LO16,    0, 1, 16, false, 0, complain_overflow_dont, 0,
+  {MIPS_RELOC_LO16,    0, 2, 16, false, 0, complain_overflow_dont, 0,
        "LO16",     false, 0, 0x0000ffff, false},
 };
 
@@ -250,6 +306,7 @@ MY(reloc_howto_type_lookup) (abfd, code)
 
   switch (code)
     {
+    case BFD_RELOC_CTOR:
     case BFD_RELOC_32:
       return (&mips_howto_table_ext[MIPS_RELOC_32]);
     case BFD_RELOC_MIPS_JMP:
@@ -323,9 +380,15 @@ static CONST struct aout_backend_data MY(backend_data) = {
   PAGE_SIZE,                   /* text vma */
   MY_set_sizes,
   0,                           /* text size includes exec header */
+  0,                           /* add_dynamic_symbols */
+  0,                           /* add_one_symbol */
+  0,                           /* link_dynamic_object */
+  0,                           /* write_dynamic_symbol */
+  0,                           /* check_dynamic_reloc */
+  0                            /* finish_dynamic_link */
 };
 
-bfd_target aout_mips_little_vec =
+const bfd_target aout_mips_little_vec =
 {
   "a.out-mips-little",         /* name */
   bfd_target_aout_flavour,
@@ -365,7 +428,7 @@ bfd_target aout_mips_little_vec =
   (PTR) MY_backend_data,
 };
 
-bfd_target aout_mips_big_vec =
+const bfd_target aout_mips_big_vec =
 {
   "a.out-mips-big",            /* name */
   bfd_target_aout_flavour,
This page took 0.025237 seconds and 4 git commands to generate.