packaging: Enable testing infrastructure
[external/binutils.git] / bfd / coffgen.c
index 81efd9b..5d61f39 100644 (file)
@@ -1,5 +1,5 @@
 /* Support for the generic parts of COFF, for BFD.
-   Copyright (C) 1990-2017 Free Software Foundation, Inc.
+   Copyright (C) 1990-2019 Free Software Foundation, Inc.
    Written by Cygnus Support.
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -37,6 +37,7 @@
    coff_data (abfd).  */
 
 #include "sysdep.h"
+#include <limits.h>
 #include "bfd.h"
 #include "libbfd.h"
 #include "coff/internal.h"
@@ -72,9 +73,9 @@ make_a_section_from_file (bfd *abfd,
       const char *strings;
 
       /* Flag that this BFD uses long names, even though the format might
-         expect them to be off by default.  This won't directly affect the
-         format of any output BFD created from this one, but the information
-         can be used to decide what to do.  */
+        expect them to be off by default.  This won't directly affect the
+        format of any output BFD created from this one, but the information
+        can be used to decide what to do.  */
       bfd_coff_set_long_section_names (abfd, TRUE);
       memcpy (buf, hdr->s_name + 1, SCNNMLEN - 1);
       buf[SCNNMLEN - 1] = '\0';
@@ -88,7 +89,7 @@ make_a_section_from_file (bfd *abfd,
            return FALSE;
          strings += strindex;
          name = (char *) bfd_alloc (abfd,
-                                     (bfd_size_type) strlen (strings) + 1 + 1);
+                                    (bfd_size_type) strlen (strings) + 1 + 1);
          if (name == NULL)
            return FALSE;
          strcpy (name, strings);
@@ -99,7 +100,7 @@ make_a_section_from_file (bfd *abfd,
     {
       /* Assorted wastage to null-terminate the name, thanks AT&T! */
       name = (char *) bfd_alloc (abfd,
-                                 (bfd_size_type) sizeof (hdr->s_name) + 1 + 1);
+                                (bfd_size_type) sizeof (hdr->s_name) + 1 + 1);
       if (name == NULL)
        return FALSE;
       strncpy (name, (char *) &hdr->s_name[0], sizeof (hdr->s_name));
@@ -175,7 +176,7 @@ make_a_section_from_file (bfd *abfd,
            {
              _bfd_error_handler
                /* xgettext: c-format */
-               (_("%B: unable to initialize compress status for section %s"),
+               (_("%pB: unable to initialize compress status for section %s"),
                 abfd, name);
              return FALSE;
            }
@@ -193,13 +194,13 @@ make_a_section_from_file (bfd *abfd,
                  memcpy (new_name + 2, name + 1, len);
                }
            }
-         break;
+        break;
        case decompress:
          if (!bfd_init_section_decompress_status (abfd, return_section))
            {
              _bfd_error_handler
                /* xgettext: c-format */
-               (_("%B: unable to initialize decompress status for section %s"),
+               (_("%pB: unable to initialize decompress status for section %s"),
                 abfd, name);
              return FALSE;
            }
@@ -226,9 +227,9 @@ make_a_section_from_file (bfd *abfd,
    ECOFF as well.  */
 const bfd_target *
 coff_real_object_p (bfd *,
-                    unsigned,
-                    struct internal_filehdr *,
-                    struct internal_aouthdr *);
+                   unsigned,
+                   struct internal_filehdr *,
+                   struct internal_aouthdr *);
 const bfd_target *
 coff_real_object_p (bfd *abfd,
                    unsigned nscns,
@@ -595,7 +596,7 @@ coff_count_linenumbers (bfd *abfd)
   if (limit == 0)
     {
       /* This may be from the backend linker, in which case the
-         lineno_count in the sections is correct.  */
+        lineno_count in the sections is correct.  */
       for (s = abfd->sections; s != NULL; s = s->next)
        total += s->lineno_count;
       return total;
@@ -613,13 +614,13 @@ coff_count_linenumbers (bfd *abfd)
          coff_symbol_type *q = coffsymbol (q_maybe);
 
          /* The AIX 4.1 compiler can sometimes generate line numbers
-             attached to debugging symbols.  We try to simply ignore
-             those here.  */
+            attached to debugging symbols.  We try to simply ignore
+            those here.  */
          if (q->lineno != NULL
              && q->symbol.section->owner != NULL)
            {
              /* This symbol has line numbers.  Increment the owning
-                section's linenumber count.  */
+                section's linenumber count.  */
              alent *l = q->lineno;
 
              do
@@ -675,11 +676,11 @@ fixup_symbol_value (bfd *abfd,
          syment->n_value = (coff_symbol_ptr->symbol.value
                             + coff_symbol_ptr->symbol.section->output_offset);
          if (! obj_pe (abfd))
-            {
-              syment->n_value += (syment->n_sclass == C_STATLAB)
-                ? coff_symbol_ptr->symbol.section->output_section->lma
-                : coff_symbol_ptr->symbol.section->output_section->vma;
-            }
+           {
+             syment->n_value += (syment->n_sclass == C_STATLAB)
+               ? coff_symbol_ptr->symbol.section->output_section->lma
+               : coff_symbol_ptr->symbol.section->output_section->vma;
+           }
        }
       else
        {
@@ -823,8 +824,8 @@ coff_mangle_symbols (bfd *bfd_ptr)
          if (s->fix_line)
            {
              /* The value is the offset into the line number entries
-                 for the symbol's section.  On output, the symbol's
-                 section should be N_DEBUG.  */
+                for the symbol's section.  On output, the symbol's
+                section should be N_DEBUG.  */
              s->u.syment.n_value =
                (coff_symbol_ptr->symbol.section->output_section->line_filepos
                 + s->u.syment.n_value * bfd_coff_linesz (bfd_ptr));
@@ -888,13 +889,13 @@ coff_fix_symbol_name (bfd *abfd,
 
       if (bfd_coff_force_symnames_in_strings (abfd))
        {
-          native->u.syment._n._n_n._n_offset =
+         native->u.syment._n._n_n._n_offset =
              (*string_size_p + STRING_SIZE_SIZE);
          native->u.syment._n._n_n._n_zeroes = 0;
          *string_size_p += 6;  /* strlen(".file") + 1 */
        }
       else
-       strncpy (native->u.syment._n._n_name, ".file", SYMNMLEN);
+       strncpy (native->u.syment._n._n_name, ".file", SYMNMLEN);
 
       BFD_ASSERT (! (native + 1)->is_sym);
       auxent = &(native + 1)->u.auxent;
@@ -1088,7 +1089,7 @@ coff_write_alien_symbol (bfd *abfd,
     {
       symbol->name = "";
       if (isym != NULL)
-        memset (isym, 0, sizeof (*isym));
+       memset (isym, 0, sizeof (*isym));
       return TRUE;
     }
   native = dummy;
@@ -1115,12 +1116,12 @@ coff_write_alien_symbol (bfd *abfd,
   else if (symbol->flags & BSF_DEBUGGING)
     {
       /* There isn't much point to writing out a debugging symbol
-         unless we are prepared to convert it into COFF debugging
-         format.  So, we just ignore them.  We must clobber the symbol
-         name to keep it from being put in the string table.  */
+        unless we are prepared to convert it into COFF debugging
+        format.  So, we just ignore them.  We must clobber the symbol
+        name to keep it from being put in the string table.  */
       symbol->name = "";
       if (isym != NULL)
-        memset (isym, 0, sizeof (*isym));
+       memset (isym, 0, sizeof (*isym));
       return TRUE;
     }
   else
@@ -1132,7 +1133,7 @@ coff_write_alien_symbol (bfd *abfd,
        native->u.syment.n_value += output_section->vma;
 
       /* Copy the any flags from the file header into the symbol.
-         FIXME: Why?  */
+        FIXME: Why?  */
       {
        coff_symbol_type *c = coff_symbol_from (symbol);
        if (c != (coff_symbol_type *) NULL)
@@ -1418,8 +1419,8 @@ coff_write_symbols (bfd *abfd)
   else
     {
       /* We would normally not write anything here, but we'll write
-         out 4 so that any stupid coff reader which tries to read the
-         string table even when there isn't one won't croak.  */
+        out 4 so that any stupid coff reader which tries to read the
+        string table even when there isn't one won't croak.  */
       unsigned int size = STRING_SIZE_SIZE;
       bfd_byte buffer[STRING_SIZE_SIZE];
 
@@ -1521,7 +1522,8 @@ coff_pointerize_aux (bfd *abfd,
                     combined_entry_type *table_base,
                     combined_entry_type *symbol,
                     unsigned int indaux,
-                    combined_entry_type *auxent)
+                    combined_entry_type *auxent,
+                    combined_entry_type *table_end)
 {
   unsigned int type = symbol->u.syment.n_type;
   unsigned int n_sclass = symbol->u.syment.n_sclass;
@@ -1547,15 +1549,22 @@ coff_pointerize_aux (bfd *abfd,
 
   if ((ISFCN (type) || ISTAG (n_sclass) || n_sclass == C_BLOCK
        || n_sclass == C_FCN)
-      && auxent->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.l > 0)
+      && auxent->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.l > 0
+      && auxent->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.l
+      < (long) obj_raw_syment_count (abfd)
+      && table_base + auxent->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.l
+      < table_end)
     {
       auxent->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.p =
        table_base + auxent->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.l;
       auxent->fix_end = 1;
     }
+
   /* A negative tagndx is meaningless, but the SCO 3.2v4 cc can
      generate one, so we must be careful to ignore it.  */
-  if (auxent->u.auxent.x_sym.x_tagndx.l > 0)
+  if ((unsigned long) auxent->u.auxent.x_sym.x_tagndx.l
+      < obj_raw_syment_count (abfd)
+      && table_base + auxent->u.auxent.x_sym.x_tagndx.l < table_end)
     {
       auxent->u.auxent.x_sym.x_tagndx.p =
        table_base + auxent->u.auxent.x_sym.x_tagndx.l;
@@ -1644,10 +1653,10 @@ _bfd_coff_get_external_symbols (bfd *abfd)
   if (size < obj_raw_syment_count (abfd)
       || (bfd_get_file_size (abfd) > 0
          && size > bfd_get_file_size (abfd)))
-    
+
     {
-      _bfd_error_handler (_("%B: corrupt symbol count: %#Lx"),
-                         abfd, obj_raw_syment_count (abfd));
+      _bfd_error_handler (_("%pB: corrupt symbol count: %#" PRIx64 ""),
+                         abfd, (uint64_t) obj_raw_syment_count (abfd));
       return FALSE;
     }
 
@@ -1655,8 +1664,10 @@ _bfd_coff_get_external_symbols (bfd *abfd)
   if (syms == NULL)
     {
       /* PR 21013: Provide an error message when the alloc fails.  */
-      _bfd_error_handler (_("%B: not enough memory to allocate space for %#Lx symbols of size %#Lx"),
-                         abfd, obj_raw_syment_count (abfd), symesz);
+      _bfd_error_handler (_("%pB: not enough memory to allocate space "
+                           "for %#" PRIx64 " symbols of size %#" PRIx64),
+                         abfd, (uint64_t) obj_raw_syment_count (abfd),
+                         (uint64_t) symesz);
       return FALSE;
     }
 
@@ -1718,11 +1729,11 @@ _bfd_coff_read_string_table (bfd *abfd)
 #endif
     }
 
-  if (strsize < STRING_SIZE_SIZE)
+  if (strsize < STRING_SIZE_SIZE || strsize > bfd_get_file_size (abfd))
     {
       _bfd_error_handler
        /* xgettext: c-format */
-       (_("%B: bad string table size %Lu"), abfd, strsize);
+       (_("%pB: bad string table size %" PRIu64), abfd, (uint64_t) strsize);
       bfd_set_error (bfd_error_bad_value);
       return NULL;
     }
@@ -1864,7 +1875,7 @@ coff_get_normalized_symtab (bfd *abfd)
 
          internal_ptr->is_sym = FALSE;
          coff_pointerize_aux (abfd, internal, symbol_ptr, i,
-                              internal_ptr);
+                              internal_ptr, internal_end);
        }
     }
 
@@ -1907,8 +1918,8 @@ coff_get_normalized_symtab (bfd *abfd)
          else
            {
              /* Ordinary short filename, put into memory anyway.  The
-                 Microsoft PE tools sometimes store a filename in
-                 multiple AUX entries.  */
+                Microsoft PE tools sometimes store a filename in
+                multiple AUX entries.  */
              if (internal_ptr->u.syment.n_numaux > 1
                  && coff_data (abfd)->pe)
                internal_ptr->u.syment._n._n_n._n_offset =
@@ -1933,7 +1944,7 @@ coff_get_normalized_symtab (bfd *abfd)
              char *newstring;
 
              /* Find the length of this string without walking into memory
-                that isn't ours.  */
+                that isn't ours.  */
              for (i = 0; i < 8; ++i)
                if (internal_ptr->u.syment._n._n_name[i] == '\0')
                  break;
@@ -1950,7 +1961,7 @@ coff_get_normalized_symtab (bfd *abfd)
          else if (!bfd_coff_symname_in_debug (abfd, &internal_ptr->u.syment))
            {
              /* Long name already.  Point symbol at the string in the
-                 table.  */
+                table.  */
              if (string_table == NULL)
                {
                  string_table = _bfd_coff_read_string_table (abfd);
@@ -2004,6 +2015,13 @@ coff_get_reloc_upper_bound (bfd *abfd, sec_ptr asect)
       bfd_set_error (bfd_error_invalid_operation);
       return -1;
     }
+#if SIZEOF_LONG == SIZEOF_INT
+  if (asect->reloc_count >= LONG_MAX / sizeof (arelent *))
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      return -1;
+    }
+#endif
   return (asect->reloc_count + 1) * sizeof (arelent *);
 }
 
@@ -2239,13 +2257,13 @@ _bfd_coff_is_local_label_name (bfd *abfd ATTRIBUTE_UNUSED,
 
 bfd_boolean
 coff_find_nearest_line_with_names (bfd *abfd,
-                                   asymbol **symbols,
-                                   asection *section,
-                                   bfd_vma offset,
-                                   const char **filename_ptr,
-                                   const char **functionname_ptr,
-                                   unsigned int *line_ptr,
-                                   const struct dwarf_debug_section *debug_sections)
+                                  asymbol **symbols,
+                                  asection *section,
+                                  bfd_vma offset,
+                                  const char **filename_ptr,
+                                  const char **functionname_ptr,
+                                  unsigned int *line_ptr,
+                                  const struct dwarf_debug_section *debug_sections)
 {
   bfd_boolean found;
   unsigned int i;
@@ -2272,7 +2290,7 @@ coff_find_nearest_line_with_names (bfd *abfd,
   /* Also try examining DWARF2 debugging information.  */
   if (_bfd_dwarf2_find_nearest_line (abfd, symbols, NULL, section, offset,
                                     filename_ptr, functionname_ptr,
-                                    line_ptr, NULL, debug_sections, 0,
+                                    line_ptr, NULL, debug_sections,
                                     &coff_data(abfd)->dwarf2_find_line_info))
     return TRUE;
 
@@ -2284,7 +2302,7 @@ coff_find_nearest_line_with_names (bfd *abfd,
      information.  So try again, using a bias against the address sought.  */
   if (coff_data (abfd)->dwarf2_find_line_info != NULL)
     {
-      bfd_signed_vma bias;
+      bfd_signed_vma bias = 0;
 
       /* Create a cache of the result for the next call.  */
       if (sec_data == NULL && section->owner == abfd)
@@ -2296,10 +2314,11 @@ coff_find_nearest_line_with_names (bfd *abfd,
 
       if (sec_data != NULL && sec_data->saved_bias)
        bias = sec_data->saved_bias;
-      else
+      else if (symbols)
        {
          bias = _bfd_dwarf2_find_symbol_bias (symbols,
                                               & coff_data (abfd)->dwarf2_find_line_info);
+
          if (sec_data)
            {
              sec_data->saved_bias = TRUE;
@@ -2311,7 +2330,7 @@ coff_find_nearest_line_with_names (bfd *abfd,
          && _bfd_dwarf2_find_nearest_line (abfd, symbols, NULL, section,
                                            offset + bias,
                                            filename_ptr, functionname_ptr,
-                                           line_ptr, NULL, debug_sections, 0,
+                                           line_ptr, NULL, debug_sections,
                                            &coff_data(abfd)->dwarf2_find_line_info))
        return TRUE;
     }
@@ -2380,7 +2399,7 @@ coff_find_nearest_line_with_names (bfd *abfd,
            file_addr += coff_section_from_bfd_index (abfd,
                                                      p2->u.syment.n_scnum)->vma;
          /* We use <= MAXDIFF here so that if we get a zero length
-             file, we actually use the next file entry.  */
+            file, we actually use the next file entry.  */
          if (p2 < pend
              && offset + sec_vma >= file_addr
              && offset + sec_vma - file_addr <= maxdiff)
@@ -2520,8 +2539,8 @@ coff_find_nearest_line (bfd *abfd,
   if (discriminator_ptr)
     *discriminator_ptr = 0;
   return coff_find_nearest_line_with_names (abfd, symbols, section, offset,
-                                            filename_ptr, functionname_ptr,
-                                            line_ptr, dwarf_debug_sections);
+                                           filename_ptr, functionname_ptr,
+                                           line_ptr, dwarf_debug_sections);
 }
 
 bfd_boolean
@@ -2555,9 +2574,9 @@ coff_sizeof_headers (bfd *abfd, struct bfd_link_info *info)
 /* Change the class of a coff symbol held by BFD.  */
 
 bfd_boolean
-bfd_coff_set_symbol_class (bfd *         abfd,
-                          asymbol *     symbol,
-                          unsigned int  symbol_class)
+bfd_coff_set_symbol_class (bfd *        abfd,
+                          asymbol *     symbol,
+                          unsigned int  symbol_class)
 {
   coff_symbol_type * csym;
 
@@ -2628,6 +2647,9 @@ _bfd_coff_section_already_linked (bfd *abfd,
   struct bfd_section_already_linked_hash_entry *already_linked_list;
   struct coff_comdat_info *s_comdat;
 
+  if (sec->output_section == bfd_abs_section_ptr)
+    return FALSE;
+
   flags = sec->flags;
   if ((flags & SEC_LINK_ONCE) == 0)
     return FALSE;
@@ -2794,13 +2816,13 @@ _bfd_coff_gc_mark_hook (asection *sec,
   if (h != NULL)
     {
       switch (h->root.type)
-        {
-        case bfd_link_hash_defined:
-        case bfd_link_hash_defweak:
-          return h->root.u.def.section;
+       {
+       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;
+       case bfd_link_hash_common:
+         return h->root.u.c.p->section;
 
        case bfd_link_hash_undefweak:
          if (h->symbol_class == C_NT_WEAK && h->numaux == 1)
@@ -2818,9 +2840,9 @@ _bfd_coff_gc_mark_hook (asection *sec,
          break;
 
        case bfd_link_hash_undefined:
-        default:
-          break;
-        }
+       default:
+         break;
+       }
       return NULL;
     }
 
@@ -2899,19 +2921,19 @@ _bfd_coff_gc_mark (struct bfd_link_info *info,
       struct coff_reloc_cookie cookie;
 
       if (!init_reloc_cookie_for_section (&cookie, info, sec))
-        ret = FALSE;
+       ret = FALSE;
       else
-        {
-          for (; cookie.rel < cookie.relend; cookie.rel++)
-            {
+       {
+         for (; cookie.rel < cookie.relend; cookie.rel++)
+           {
              if (!_bfd_coff_gc_mark_reloc (info, sec, gc_mark_hook, &cookie))
                {
                  ret = FALSE;
                  break;
                }
            }
-          fini_reloc_cookie_for_section (&cookie, sec);
-        }
+         fini_reloc_cookie_for_section (&cookie, sec);
+       }
     }
 
   return ret;
@@ -2999,10 +3021,10 @@ coff_gc_sweep (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
       for (o = sub->sections; o != NULL; o = o->next)
        {
            /* Keep debug and special sections.  */
-          if ((o->flags & (SEC_DEBUGGING | SEC_LINKER_CREATED)) != 0
+         if ((o->flags & (SEC_DEBUGGING | SEC_LINKER_CREATED)) != 0
              || (o->flags & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)) == 0)
            o->gc_mark = 1;
-          else if (CONST_STRNEQ (o->name, ".idata")
+         else if (CONST_STRNEQ (o->name, ".idata")
                   || CONST_STRNEQ (o->name, ".pdata")
                   || CONST_STRNEQ (o->name, ".xdata")
                   || CONST_STRNEQ (o->name, ".rsrc"))
@@ -3021,7 +3043,7 @@ coff_gc_sweep (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
 
          if (info->print_gc_sections && o->size != 0)
            /* xgettext: c-format */
-           _bfd_error_handler (_("Removing unused section '%A' in file '%B'"),
+           _bfd_error_handler (_("removing unused section '%pA' in file '%pB'"),
                                o, sub);
 
 #if 0
@@ -3098,7 +3120,7 @@ bfd_coff_gc_sections (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
   if (!bed->can_gc_sections
       || !is_coff_hash_table (info->hash))
     {
-      _bfd_error_handler(_("Warning: gc-sections option ignored"));
+      _bfd_error_handler(_("warning: gc-sections option ignored"));
       return TRUE;
     }
 #endif
@@ -3111,10 +3133,10 @@ bfd_coff_gc_sections (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
       asection *o;
 
       if (bfd_get_flavour (sub) != bfd_target_coff_flavour)
-        continue;
+       continue;
 
       for (o = sub->sections; o != NULL; o = o->next)
-        {
+       {
          if (((o->flags & (SEC_EXCLUDE | SEC_KEEP)) == SEC_KEEP
               || CONST_STRNEQ (o->name, ".vectors")
               || CONST_STRNEQ (o->name, ".ctors")
@@ -3124,7 +3146,7 @@ bfd_coff_gc_sections (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
              if (!_bfd_coff_gc_mark (info, o, _bfd_coff_gc_mark_hook))
                return FALSE;
            }
-        }
+       }
     }
 
   /* Allow the backend to mark additional target specific sections.  */