Apply several patches from Maciej W. Rozycki
authorNick Clifton <nickc@redhat.com>
Sun, 11 Feb 2001 23:11:41 +0000 (23:11 +0000)
committerNick Clifton <nickc@redhat.com>
Sun, 11 Feb 2001 23:11:41 +0000 (23:11 +0000)
bfd/ChangeLog
bfd/elf32-mips.c
gas/ChangeLog
gas/config/tc-mips.c
opcodes/ChangeLog
opcodes/mips-dis.c

index 05740c1f10e90895a004bf2fb04ad29a5a94ba2f..a96c3dac05935c5b21c0a77ab2fd23757ec31b2c 100644 (file)
@@ -1,3 +1,36 @@
+2001-02-11  Maciej W. Rozycki  <macro@ds2.pg.gda.pl>
+
+       * elf32-mips.c (mips_elf_create_dynamic_relocation): Undo patch
+       from 2000-10-13.  Do not add the symbol's value for R_MIPS_REL32
+       relocations against dynsym symbols.
+
+       * elf32-mips.c (elf_mips_howto_table): Fix the comment on
+       the R_MIPS_26 relocation.
+       (mips_elf_calculate_relocation): Use (p + 4) instead of p for
+       the R_MIPS_26 relocation.
+       (mips_elf_perform_relocation): Fix the comment on the R_MIPS16_26
+       relocation.
+       * elf64-mips.c (mips_elf64_howto_table_rel): Fix the comment on
+       the R_MIPS_26 relocation.
+       (mips_elf64_howto_table_rela): Likewise.
+
+       * elf32-mips.c (struct mips_elf_link_hash_entry): Added no_fn_stub
+       member to mark symbols that have non-CALL relocations against
+       them.
+       (mips_elf_link_hash_newfunc): Initialize no_fn_stub.
+       (mips_elf_calculate_relocation): Handle R_MIPS_CALL16 like
+       R_MIPS_GOT16.
+       (_bfd_mips_elf_check_relocs): Set no_fn_stub for a symbol if a
+       non-CALL relocation against it is encountered.
+       (_bfd_mips_elf_copy_indirect_symbol): Merge no_fn_stub as well.
+       (_bfd_mips_elf_adjust_dynamic_symbol): Only create a stub if
+       no_fn_stub is not set.
+
+       * elf32-mips.c (mips_elf_output_extsym): Get the output section
+       information from the real symbol for indirect ones.
+       Check no_fn_stub to find out if a symbol has a function stub
+       indeed.
+
 2001-02-11  Michael Sokolov  <msokolov@ivan.Harhan.ORG>
 
        * Makefile.am (stamp-lib): ranlib the libbfd.a in the build directory.
index 5bb1e94c2e99727b1d3673e5de8723701defc154..7eb8aa2daff7a215b3e771c35ac56cc7067e2974 100644 (file)
@@ -80,6 +80,12 @@ struct mips_elf_link_hash_entry
      section) against this symbol.  */
   unsigned int min_dyn_reloc_index;
 
+  /* We must not create a stub for a symbol that has relocations
+     related to taking the function's address, i.e. any but
+     R_MIPS_CALL*16 ones -- see "MIPS ABI Supplement, 3rd Edition",
+     p. 4-20.  */
+  boolean no_fn_stub;
+
   /* If there is a stub that 32 bit functions should use to call this
      16 bit function, this points to the section containing the stub.  */
   asection *fn_stub;
@@ -193,7 +199,7 @@ static bfd_vma mips_elf_got16_entry
 static boolean mips_elf_create_dynamic_relocation
   PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Rela *,
           struct mips_elf_link_hash_entry *, asection *,
-          bfd_vma, bfd_vma *, asection *, boolean local_p));
+          bfd_vma, bfd_vma *, asection *));
 static void mips_elf_allocate_dynamic_relocations
   PARAMS ((bfd *, unsigned int));
 static boolean mips_elf_stub_section_p
@@ -531,7 +537,7 @@ static reloc_howto_type elf_mips_howto_table[] =
         complain_overflow_dont, /* complain_on_overflow */
                                /* This needs complex overflow
                                   detection, because the upper four
-                                  bits must match the PC.  */
+                                  bits must match the PC + 4.  */
         bfd_elf_generic_reloc, /* special_function */
         "R_MIPS_26",           /* name */
         true,                  /* partial_inplace */
@@ -3955,6 +3961,7 @@ mips_elf_link_hash_newfunc (entry, table, string)
       ret->esym.ifd = -2;
       ret->possibly_dynamic_relocs = 0;
       ret->min_dyn_reloc_index = 0;
+      ret->no_fn_stub = false;
       ret->fn_stub = NULL;
       ret->need_fn_stub = false;
       ret->call_stub = NULL;
@@ -4330,24 +4337,36 @@ mips_elf_output_extsym (h, data)
     }
   else if ((h->root.elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)
     {
-      /* Set type and value for a symbol with a function stub.  */
-      h->esym.asym.st = stProc;
-      sec = h->root.root.u.def.section;
-      if (sec == NULL)
-       h->esym.asym.value = 0;
-      else
+      struct mips_elf_link_hash_entry *hd = h;
+      boolean no_fn_stub = h->no_fn_stub;
+
+      while (hd->root.root.type == bfd_link_hash_indirect)
        {
-         output_section = sec->output_section;
-         if (output_section != NULL)
-           h->esym.asym.value = (h->root.plt.offset
-                                 + sec->output_offset
-                                 + output_section->vma);
-         else
-           h->esym.asym.value = 0;
+         hd = (struct mips_elf_link_hash_entry *)h->root.root.u.i.link;
+         no_fn_stub = no_fn_stub || hd->no_fn_stub;
        }
+
+      if (!no_fn_stub)
+       {
+         /* Set type and value for a symbol with a function stub.  */
+         h->esym.asym.st = stProc;
+         sec = hd->root.root.u.def.section;
+         if (sec == NULL)
+           h->esym.asym.value = 0;
+         else
+           {
+             output_section = sec->output_section;
+             if (output_section != NULL)
+               h->esym.asym.value = (hd->root.plt.offset
+                                     + sec->output_offset
+                                     + output_section->vma);
+             else
+               h->esym.asym.value = 0;
+           }
 #if 0 /* FIXME?  */
-      h->esym.ifd = 0;
+         h->esym.ifd = 0;
 #endif
+       }
     }
 
   if (! bfd_ecoff_debug_one_external (einfo->abfd, einfo->debug, einfo->swap,
@@ -5748,7 +5767,7 @@ mips_elf_next_relocation (r_type, relocation, relend)
 
 static boolean
 mips_elf_create_dynamic_relocation (output_bfd, info, rel, h, sec,
-                                   symbol, addendp, input_section, local_p)
+                                   symbol, addendp, input_section)
      bfd *output_bfd;
      struct bfd_link_info *info;
      const Elf_Internal_Rela *rel;
@@ -5757,7 +5776,6 @@ mips_elf_create_dynamic_relocation (output_bfd, info, rel, h, sec,
      bfd_vma symbol;
      bfd_vma *addendp;
      asection *input_section;
-     boolean local_p;
 {
   Elf_Internal_Rel outrel;
   boolean skip;
@@ -5842,15 +5860,16 @@ mips_elf_create_dynamic_relocation (output_bfd, info, rel, h, sec,
          /* The relocation we're building is section-relative.
             Therefore, the original addend must be adjusted by the
             section offset.  */
-         *addendp += symbol - sec->output_section->vma;
+         *addendp += section_offset;
          /* Now, the relocation is just against the section.  */
          symbol = sec->output_section->vma;
        }
 
-      /* If the relocation is against a local symbol was previously an
-        absolute relocation, we must adjust it by the value we give
-        it in the dynamic symbol table.  */
-      if (local_p && r_type != R_MIPS_REL32)
+      /* If the relocation was previously an absolute relocation and
+        this symbol will not be referred to by the relocation, we must
+        adjust it by the value we give it in the dynamic symbol table.
+        Otherwise leave the job up to the dynamic linker.  */
+      if (!indx && r_type != R_MIPS_REL32)
        *addendp += symbol;
 
       /* The relocation is always an REL32 relocation because we don't
@@ -6225,7 +6244,7 @@ mips_elf_calculate_relocation (abfd,
                                 symbol + addend, sgot->contents + g);
            }
        }
-      else if (r_type == R_MIPS_GOT16)
+      else if (r_type == R_MIPS_GOT16 || r_type == R_MIPS_CALL16)
        /* There's no need to create a local GOT entry here; the
           calculation for a local GOT16 entry does not involve G.  */
        break;
@@ -6288,7 +6307,7 @@ mips_elf_calculate_relocation (abfd,
                                                   sec,
                                                   symbol,
                                                   &value,
-                                                  input_section, local_p))
+                                                  input_section))
            return false;
        }
       else
@@ -6320,14 +6339,14 @@ mips_elf_calculate_relocation (abfd,
       break;
 
     case R_MIPS16_26:
-      /* The calculation for R_MIPS_26 is just the same as for an
+      /* The calculation for R_MIPS16_26 is just the same as for an
         R_MIPS_26.  It's only the storage of the relocated field into
         the output file that's different.  That's handled in
         mips_elf_perform_relocation.  So, we just fall through to the
         R_MIPS_26 case here.  */
     case R_MIPS_26:
       if (local_p)
-       value = (((addend << 2) | (p & 0xf0000000)) + symbol) >> 2;
+       value = (((addend << 2) | ((p + 4) & 0xf0000000)) + symbol) >> 2;
       else
        value = (mips_elf_sign_extend (addend << 2, 28) + symbol) >> 2;
       value &= howto->dst_mask;
@@ -6393,6 +6412,7 @@ mips_elf_calculate_relocation (abfd,
       break;
 
     case R_MIPS_GOT16:
+    case R_MIPS_CALL16:
       if (local_p)
        {
          boolean forced;
@@ -6415,7 +6435,6 @@ mips_elf_calculate_relocation (abfd,
 
       /* Fall through.  */
 
-    case R_MIPS_CALL16:
     case R_MIPS_GOT_DISP:
       value = g;
       overflowed_p = mips_elf_overflow_p (value, 16);
@@ -6620,9 +6639,9 @@ mips_elf_perform_relocation (info, howto, relocation, value,
         ((sub1 << 16) | sub2)).
 
         When producing a relocateable object file, the calculation is
-        (((A < 2) | (P & 0xf0000000) + S) >> 2)
+        (((A < 2) | ((P + 4) & 0xf0000000) + S) >> 2)
         When producing a fully linked file, the calculation is
-        let R = (((A < 2) | (P & 0xf0000000) + S) >> 2)
+        let R = (((A < 2) | ((P + 4) & 0xf0000000) + S) >> 2)
         ((R & 0x1f0000) << 5) | ((R & 0x3e00000) >> 5) | (R & 0xffff)  */
 
       if (!info->relocateable)
@@ -7728,10 +7747,10 @@ _bfd_mips_elf_check_relocs (abfd, info, sec, relocs)
          /* We may need a local GOT entry for this relocation.  We
             don't count R_MIPS_GOT_PAGE because we can estimate the
             maximum number of pages needed by looking at the size of
-            the segment.  Similar comments apply to R_MIPS_GOT16.  We
-            don't count R_MIPS_GOT_HI16, or R_MIPS_CALL_HI16 because
-            these are always followed by an R_MIPS_GOT_LO16 or
-            R_MIPS_CALL_LO16.
+            the segment.  Similar comments apply to R_MIPS_GOT16 and
+            R_MIPS_CALL16.  We don't count R_MIPS_GOT_HI16, or
+            R_MIPS_CALL_HI16 because these are always followed by an
+            R_MIPS_GOT_LO16 or R_MIPS_CALL_LO16.
 
             This estimation is very conservative since we can merge
             duplicate entries in the GOT.  In order to be less
@@ -7863,6 +7882,25 @@ _bfd_mips_elf_check_relocs (abfd, info, sec, relocs)
          break;
        }
 
+      /* We must not create a stub for a symbol that has relocations
+         related to taking the function's address.  */
+      switch (r_type)
+       {
+       default:
+         if (h != NULL)
+           {
+             struct mips_elf_link_hash_entry *mh;
+
+             mh = (struct mips_elf_link_hash_entry *) h;
+             mh->no_fn_stub = true;
+           }
+         break;
+       case R_MIPS_CALL16:
+       case R_MIPS_CALL_HI16:
+       case R_MIPS_CALL_LO16:
+         break;
+       }
+
       /* If this reloc is not a 16 bit call, and it has a global
          symbol, then we will need the fn_stub if there is one.
          References from a stub section do not count.  */
@@ -7998,6 +8036,8 @@ _bfd_mips_elf_copy_indirect_symbol (dir, ind)
       || (indmips->min_dyn_reloc_index != 0
          && indmips->min_dyn_reloc_index < dirmips->min_dyn_reloc_index))
     dirmips->min_dyn_reloc_index = indmips->min_dyn_reloc_index;
+  if (indmips->no_fn_stub)
+    dirmips->no_fn_stub = true;
 }
 
 /* Adjust a symbol defined by a dynamic object and referenced by a
@@ -8038,8 +8078,9 @@ _bfd_mips_elf_adjust_dynamic_symbol (info, h)
     mips_elf_allocate_dynamic_relocations (dynobj,
                                           hmips->possibly_dynamic_relocs);
 
-  /* For a function, create a stub, if needed.  */
-  if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)
+  /* For a function, create a stub, if allowed.  */
+  if (! hmips->no_fn_stub
+      && (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)
     {
       if (! elf_hash_table (info)->dynamic_sections_created)
        return true;
index 400085b37add3a3831a582cfcd43370a9d9da563..d83016a4eb2aaeb2a5f63a2f2447427d177f8695 100644 (file)
@@ -1,3 +1,12 @@
+2001-02-11  Maciej W. Rozycki  <macro@ds2.pg.gda.pl>
+
+       * config/tc-mips.c (macro): For M_LA_AB emit a
+       BFD_RELOC_MIPS_CALL16 relocation or a
+       BFD_RELOC_MIPS_CALL_HI16/BFD_RELOC_MIPS_CALL_LO16 pair instead of
+       BFD_RELOC_MIPS_GOT16 and
+       BFD_RELOC_MIPS_GOT_HI16/BFD_RELOC_MIPS_GOT_LO16, respectively for
+       loading the jump register when generating SVR4_PIC code.
+
 2001-02-10  Chris Demetriou  <cgd@broadcom.com>
 
        * configure.in: Make 'mipself' and 'mipsecoff' emulations
index 77ec76f3953b01a705d75615d1a56e31b9799bbb..acc22e21fd541232d795540dc0e090e56fccad94 100644 (file)
@@ -3936,7 +3936,7 @@ macro (ip)
          if (mips_trap)
            macro_build ((char *) NULL, &icnt, NULL, "teq", "s,t", 0, 0);
          else
-             macro_build ((char *) NULL, &icnt, NULL, "break", "c", 7);
+           macro_build ((char *) NULL, &icnt, NULL, "break", "c", 7);
          return;
        }
 
@@ -3957,7 +3957,7 @@ macro (ip)
          macro_build ((char *) NULL, &icnt, NULL,
                       dbl ? "ddiv" : "div",
                       "z,s,t", sreg, treg);
-           macro_build ((char *) NULL, &icnt, NULL, "break", "c", 7);
+         macro_build ((char *) NULL, &icnt, NULL, "break", "c", 7);
        }
       expr1.X_add_number = -1;
       macro_build ((char *) NULL, &icnt, &expr1,
@@ -3996,7 +3996,7 @@ macro (ip)
             that later insns are available for delay slot filling.  */
          --mips_opts.noreorder;
 
-           macro_build ((char *) NULL, &icnt, NULL, "break", "c", 6);
+         macro_build ((char *) NULL, &icnt, NULL, "break", "c", 6);
        }
       macro_build ((char *) NULL, &icnt, NULL, s, "d", dreg);
       break;
@@ -4213,9 +4213,13 @@ macro (ip)
        }
       else if (mips_pic == SVR4_PIC && ! mips_big_got)
        {
+         int lw_reloc_type = (int) BFD_RELOC_MIPS_GOT16;
+
          /* If this is a reference to an external symbol, and there
             is no constant, we want
               lw       $tempreg,<sym>($gp)     (BFD_RELOC_MIPS_GOT16)
+            or if tempreg is PIC_CALL_REG
+              lw       $tempreg,<sym>($gp)     (BFD_RELOC_MIPS_CALL16)
             For a local symbol, we want
               lw       $tempreg,<sym>($gp)     (BFD_RELOC_MIPS_GOT16)
               nop
@@ -4242,9 +4246,11 @@ macro (ip)
          expr1.X_add_number = offset_expr.X_add_number;
          offset_expr.X_add_number = 0;
          frag_grow (32);
+         if (expr1.X_add_number == 0 && tempreg == PIC_CALL_REG)
+           lw_reloc_type = (int) BFD_RELOC_MIPS_CALL16;
          macro_build ((char *) NULL, &icnt, &offset_expr,
                       dbl ? "ld" : "lw",
-                      "t,o(b)", tempreg, (int) BFD_RELOC_MIPS_GOT16, GP);
+                      "t,o(b)", tempreg, lw_reloc_type, GP);
          if (expr1.X_add_number == 0)
            {
              int off;
@@ -4350,12 +4356,18 @@ macro (ip)
       else if (mips_pic == SVR4_PIC)
        {
          int gpdel;
+         int lui_reloc_type = (int) BFD_RELOC_MIPS_GOT_HI16;
+         int lw_reloc_type = (int) BFD_RELOC_MIPS_GOT_LO16;
 
          /* This is the large GOT case.  If this is a reference to an
             external symbol, and there is no constant, we want
               lui      $tempreg,<sym>          (BFD_RELOC_MIPS_GOT_HI16)
               addu     $tempreg,$tempreg,$gp
               lw       $tempreg,<sym>($tempreg) (BFD_RELOC_MIPS_GOT_LO16)
+            or if tempreg is PIC_CALL_REG
+              lui      $tempreg,<sym>          (BFD_RELOC_MIPS_CALL_HI16)
+              addu     $tempreg,$tempreg,$gp
+              lw       $tempreg,<sym>($tempreg) (BFD_RELOC_MIPS_CALL_LO16)
             For a local symbol, we want
               lw       $tempreg,<sym>($gp)     (BFD_RELOC_MIPS_GOT16)
               nop
@@ -4394,8 +4406,13 @@ macro (ip)
            gpdel = 4;
          else
            gpdel = 0;
+         if (expr1.X_add_number == 0 && tempreg == PIC_CALL_REG)
+           {
+             lui_reloc_type = (int) BFD_RELOC_MIPS_CALL_HI16;
+             lw_reloc_type = (int) BFD_RELOC_MIPS_CALL_LO16;
+           }
          macro_build ((char *) NULL, &icnt, &offset_expr, "lui", "t,u",
-                      tempreg, (int) BFD_RELOC_MIPS_GOT_HI16);
+                      tempreg, lui_reloc_type);
          macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
                       ((bfd_arch_bits_per_address (stdoutput) == 32
                         || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
@@ -4403,8 +4420,7 @@ macro (ip)
                       "d,v,t", tempreg, tempreg, GP);
          macro_build ((char *) NULL, &icnt, &offset_expr,
                       dbl ? "ld" : "lw",
-                      "t,o(b)", tempreg, (int) BFD_RELOC_MIPS_GOT_LO16,
-                      tempreg);
+                      "t,o(b)", tempreg, lw_reloc_type, tempreg);
          if (expr1.X_add_number == 0)
            {
              int off;
index 6c93aa73479e2bcbe035cc9f6b4ab5e27b02408a..dfca2e92cff475fa897d853ff5b489635786b91d 100644 (file)
@@ -1,3 +1,10 @@
+2001-02-11  Maciej W. Rozycki  <macro@ds2.pg.gda.pl>
+
+        * mips-dis.c (print_insn_arg): Use top four bits of the address of
+       the following instruction not of the jump itself for the jump
+       target.
+       (print_mips16_insn_arg): Likewise.
+
 2001-02-11  Michael Sokolov  <msokolov@ivan.Harhan.ORG>
 
        * Makefile.am (stamp-lib): ranlib the libopcodes.a in the build
index a75dc89d9f8097a28f4c0a9d0f6fa72c85acd684..849f9f2003020762aa92b5aebde4c87c44c894bd 100644 (file)
@@ -137,7 +137,7 @@ print_insn_arg (d, l, pc, info)
 
     case 'a':
       (*info->print_address_func)
-       (((pc & ~ (bfd_vma) 0x0fffffff)
+       ((((pc + 4) & ~ (bfd_vma) 0x0fffffff)
          | (((l >> OP_SH_TARGET) & OP_MASK_TARGET) << 2)),
         info);
       break;
@@ -1038,9 +1038,9 @@ print_mips16_insn_arg (type, op, l, use_extend, extend, memaddr, info)
       if (! use_extend)
        extend = 0;
       l = ((l & 0x1f) << 23) | ((l & 0x3e0) << 13) | (extend << 2);
-      (*info->print_address_func) ((memaddr & 0xf0000000) | l, info);
+      (*info->print_address_func) (((memaddr + 4) & 0xf0000000) | l, info);
       info->insn_type = dis_jsr;
-      info->target = (memaddr & 0xf0000000) | l;
+      info->target = ((memaddr + 4) & 0xf0000000) | l;
       info->branch_delay_insns = 1;
       break;