MIPS/BFD: Correctly handle `bfd_reloc_outofrange' with branches
[deliverable/binutils-gdb.git] / bfd / cofflink.c
index 13d773aca5b4fc00c08f939b538c75c4037514e4..bcdf778ac0a6afdf57f73dc125fe63d0b3a2e6c4 100644 (file)
@@ -1,5 +1,5 @@
 /* COFF specific linker code.
 /* COFF specific linker code.
-   Copyright (C) 1994-2015 Free Software Foundation, Inc.
+   Copyright (C) 1994-2016 Free Software Foundation, Inc.
    Written by Ian Lance Taylor, Cygnus Support.
 
    This file is part of BFD, the Binary File Descriptor library.
    Written by Ian Lance Taylor, Cygnus Support.
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -212,8 +212,9 @@ coff_link_check_archive_element (bfd *abfd,
   if (h->type != bfd_link_hash_undefined)
     return TRUE;
 
   if (h->type != bfd_link_hash_undefined)
     return TRUE;
 
+  /* Include this element?  */
   if (!(*info->callbacks->add_archive_element) (info, abfd, name, &abfd))
   if (!(*info->callbacks->add_archive_element) (info, abfd, name, &abfd))
-    return FALSE;
+    return TRUE;
   *pneeded = TRUE;
 
   return coff_link_add_object_symbols (abfd, info);
   *pneeded = TRUE;
 
   return coff_link_add_object_symbols (abfd, info);
@@ -872,9 +873,10 @@ _bfd_coff_final_link (bfd *abfd,
              asymbol *sym = bfd_get_outsymbols (sub) [i];
              file_ptr pos;
              struct internal_syment isym;
              asymbol *sym = bfd_get_outsymbols (sub) [i];
              file_ptr pos;
              struct internal_syment isym;
-             bfd_size_type string_size = 0;
+             union internal_auxent iaux;
+             bfd_size_type string_size = 0, indx;
              bfd_vma written = 0;
              bfd_vma written = 0;
-             bfd_boolean rewrite = FALSE;
+             bfd_boolean rewrite = FALSE, hash;
 
              if (! (sym->flags & BSF_LOCAL)
                  || (sym->flags & (BSF_SECTION_SYM | BSF_DEBUGGING_RELOC
 
              if (! (sym->flags & BSF_LOCAL)
                  || (sym->flags & (BSF_SECTION_SYM | BSF_DEBUGGING_RELOC
@@ -900,23 +902,52 @@ _bfd_coff_final_link (bfd *abfd,
                                             * symesz;
              if (bfd_seek (abfd, pos, SEEK_SET) != 0)
                goto error_return;
                                             * symesz;
              if (bfd_seek (abfd, pos, SEEK_SET) != 0)
                goto error_return;
-             if (! coff_write_alien_symbol(abfd, sym, &isym, &written,
+             if (! coff_write_alien_symbol(abfd, sym, &isym, &iaux, &written,
                                            &string_size, NULL, NULL))
                goto error_return;
 
                                            &string_size, NULL, NULL))
                goto error_return;
 
-             if (string_size)
+             hash = !flaginfo.info->traditional_format;
+
+             if (string_size >= 6 && isym.n_sclass == C_FILE
+                 && ! isym._n._n_n._n_zeroes && isym.n_numaux)
                {
                {
-                 bfd_boolean hash = !flaginfo.info->traditional_format;
-                 bfd_size_type indx;
+                 indx = _bfd_stringtab_add (flaginfo.strtab, ".file", hash,
+                                            FALSE);
+                 if (indx == (bfd_size_type) -1)
+                   goto error_return;
+                 isym._n._n_n._n_offset = STRING_SIZE_SIZE + indx;
+                 bfd_coff_swap_sym_out (abfd, &isym, flaginfo.outsyms);
+                 if (bfd_seek (abfd, pos, SEEK_SET) != 0
+                     || bfd_bwrite (flaginfo.outsyms, symesz,
+                                    abfd) != symesz)
+                   goto error_return;
+                 string_size -= 6;
+               }
 
 
+             if (string_size)
+               {
                  indx = _bfd_stringtab_add (flaginfo.strtab,
                                             bfd_asymbol_name (sym), hash,
                                             FALSE);
                  if (indx == (bfd_size_type) -1)
                    goto error_return;
                  indx = _bfd_stringtab_add (flaginfo.strtab,
                                             bfd_asymbol_name (sym), hash,
                                             FALSE);
                  if (indx == (bfd_size_type) -1)
                    goto error_return;
-                 isym._n._n_n._n_offset = STRING_SIZE_SIZE + indx;
-                 bfd_coff_swap_sym_out (abfd, &isym, flaginfo.outsyms);
-                 rewrite = TRUE;
+                 if (isym.n_sclass != C_FILE)
+                   {
+                     isym._n._n_n._n_offset = STRING_SIZE_SIZE + indx;
+                     bfd_coff_swap_sym_out (abfd, &isym, flaginfo.outsyms);
+                     rewrite = TRUE;
+                   }
+                 else
+                   {
+                     BFD_ASSERT (isym.n_numaux == 1);
+                     iaux.x_file.x_n.x_offset = STRING_SIZE_SIZE + indx;
+                     bfd_coff_swap_aux_out (abfd, &iaux, isym.n_type, C_FILE,
+                                            0, 1, flaginfo.outsyms + symesz);
+                     if (bfd_seek (abfd, pos + symesz, SEEK_SET) != 0
+                         || bfd_bwrite (flaginfo.outsyms + symesz, symesz,
+                                        abfd) != symesz)
+                       goto error_return;
+                   }
                }
 
              if (isym.n_sclass == C_FILE)
                }
 
              if (isym.n_sclass == C_FILE)
@@ -2484,10 +2515,8 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *flaginfo, bfd *input_bfd)
                          if (name == NULL)
                            return FALSE;
 
                          if (name == NULL)
                            return FALSE;
 
-                         if (! ((*flaginfo->info->callbacks->unattached_reloc)
-                                (flaginfo->info, name, input_bfd, o,
-                                 irel->r_vaddr)))
-                           return FALSE;
+                         (*flaginfo->info->callbacks->unattached_reloc)
+                           (flaginfo->info, name, input_bfd, o, irel->r_vaddr);
                        }
                    }
                }
                        }
                    }
                }
@@ -2803,18 +2832,14 @@ _bfd_coff_reloc_link_order (bfd *output_bfd,
        case bfd_reloc_outofrange:
          abort ();
        case bfd_reloc_overflow:
        case bfd_reloc_outofrange:
          abort ();
        case bfd_reloc_overflow:
-         if (! ((*flaginfo->info->callbacks->reloc_overflow)
-                (flaginfo->info, NULL,
-                 (link_order->type == bfd_section_reloc_link_order
-                  ? bfd_section_name (output_bfd,
-                                      link_order->u.reloc.p->u.section)
-                  : link_order->u.reloc.p->u.name),
-                 howto->name, link_order->u.reloc.p->addend,
-                 (bfd *) NULL, (asection *) NULL, (bfd_vma) 0)))
-           {
-             free (buf);
-             return FALSE;
-           }
+         (*flaginfo->info->callbacks->reloc_overflow)
+           (flaginfo->info, NULL,
+            (link_order->type == bfd_section_reloc_link_order
+             ? bfd_section_name (output_bfd,
+                                 link_order->u.reloc.p->u.section)
+             : link_order->u.reloc.p->u.name),
+            howto->name, link_order->u.reloc.p->addend,
+            (bfd *) NULL, (asection *) NULL, (bfd_vma) 0);
          break;
        }
       loc = link_order->offset * bfd_octets_per_byte (output_bfd);
          break;
        }
       loc = link_order->offset * bfd_octets_per_byte (output_bfd);
@@ -2870,10 +2895,9 @@ _bfd_coff_reloc_link_order (bfd *output_bfd,
        }
       else
        {
        }
       else
        {
-         if (! ((*flaginfo->info->callbacks->unattached_reloc)
-                (flaginfo->info, link_order->u.reloc.p->u.name, (bfd *) NULL,
-                 (asection *) NULL, (bfd_vma) 0)))
-           return FALSE;
+         (*flaginfo->info->callbacks->unattached_reloc)
+           (flaginfo->info, link_order->u.reloc.p->u.name,
+            (bfd *) NULL, (asection *) NULL, (bfd_vma) 0);
          irel->r_symndx = 0;
        }
     }
          irel->r_symndx = 0;
        }
     }
@@ -2977,6 +3001,12 @@ _bfd_coff_generic_relocate_section (bfd *output_bfd,
          else
            {
              sec = sections[symndx];
          else
            {
              sec = sections[symndx];
+
+             /* PR 19623: Relocations against symbols in
+                the absolute sections should ignored.  */
+              if (bfd_is_abs_section (sec))
+               continue;
+
               val = (sec->output_section->vma
                     + sec->output_offset
                     + sym->n_value);
               val = (sec->output_section->vma
                     + sec->output_offset
                     + sym->n_value);
@@ -3032,12 +3062,9 @@ _bfd_coff_generic_relocate_section (bfd *output_bfd,
            }
 
          else if (! bfd_link_relocatable (info))
            }
 
          else if (! bfd_link_relocatable (info))
-           {
-             if (! ((*info->callbacks->undefined_symbol)
-                    (info, h->root.root.string, input_bfd, input_section,
-                     rel->r_vaddr - input_section->vma, TRUE)))
-               return FALSE;
-           }
+           (*info->callbacks->undefined_symbol)
+             (info, h->root.root.string, input_bfd, input_section,
+              rel->r_vaddr - input_section->vma, TRUE);
        }
 
       /* If the input section defining the symbol has been discarded
        }
 
       /* If the input section defining the symbol has been discarded
@@ -3107,11 +3134,10 @@ _bfd_coff_generic_relocate_section (bfd *output_bfd,
                  return FALSE;
              }
 
                  return FALSE;
              }
 
-           if (! ((*info->callbacks->reloc_overflow)
-                  (info, (h ? &h->root : NULL), name, howto->name,
-                   (bfd_vma) 0, input_bfd, input_section,
-                   rel->r_vaddr - input_section->vma)))
-             return FALSE;
+           (*info->callbacks->reloc_overflow)
+             (info, (h ? &h->root : NULL), name, howto->name,
+              (bfd_vma) 0, input_bfd, input_section,
+              rel->r_vaddr - input_section->vma);
          }
        }
     }
          }
        }
     }
This page took 0.026163 seconds and 4 git commands to generate.