gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / bfd / coffgen.c
index 481e4a5c91f690c9b3b26a20b4c6467319cd1af1..94589b43d2f0d21d70e4caa87e2fb763cc0c0c28 100644 (file)
@@ -1,5 +1,5 @@
 /* Support for the generic parts of COFF, for BFD.
-   Copyright (C) 1990-2015 Free Software Foundation, Inc.
+   Copyright (C) 1990-2020 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));
@@ -173,8 +174,9 @@ make_a_section_from_file (bfd *abfd,
        case compress:
          if (!bfd_init_section_compress_status (abfd, return_section))
            {
-             (*_bfd_error_handler)
-               (_("%B: unable to initialize compress status for section %s"),
+             _bfd_error_handler
+               /* xgettext: c-format */
+               (_("%pB: unable to initialize compress status for section %s"),
                 abfd, name);
              return FALSE;
            }
@@ -192,12 +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)
-               (_("%B: unable to initialize decompress status for section %s"),
+             _bfd_error_handler
+               /* xgettext: c-format */
+               (_("%pB: unable to initialize decompress status for section %s"),
                 abfd, name);
              return FALSE;
            }
@@ -214,7 +217,7 @@ make_a_section_from_file (bfd *abfd,
          break;
        }
       if (new_name != NULL)
-       bfd_rename_section (abfd, return_section, new_name);
+       bfd_rename_section (return_section, new_name);
     }
 
   return result;
@@ -222,12 +225,12 @@ make_a_section_from_file (bfd *abfd,
 
 /* Read in a COFF object and make it into a BFD.  This is used by
    ECOFF as well.  */
-const bfd_target *
+bfd_cleanup
 coff_real_object_p (bfd *,
-                    unsigned,
-                    struct internal_filehdr *,
-                    struct internal_aouthdr *);
-const bfd_target *
+                   unsigned,
+                   struct internal_filehdr *,
+                   struct internal_aouthdr *);
+bfd_cleanup
 coff_real_object_p (bfd *abfd,
                    unsigned nscns,
                    struct internal_filehdr *internal_f,
@@ -254,14 +257,14 @@ coff_real_object_p (bfd *abfd,
   if ((internal_f->f_flags & F_EXEC) != 0)
     abfd->flags |= D_PAGED;
 
-  bfd_get_symcount (abfd) = internal_f->f_nsyms;
+  abfd->symcount = internal_f->f_nsyms;
   if (internal_f->f_nsyms)
     abfd->flags |= HAS_SYMS;
 
   if (internal_a != (struct internal_aouthdr *) NULL)
-    bfd_get_start_address (abfd) = internal_a->entry;
+    abfd->start_address = internal_a->entry;
   else
-    bfd_get_start_address (abfd) = 0;
+    abfd->start_address = 0;
 
   /* Set up the tdata area.  ECOFF uses its own routine, and overrides
      abfd->flags.  */
@@ -272,13 +275,10 @@ coff_real_object_p (bfd *abfd,
 
   scnhsz = bfd_coff_scnhsz (abfd);
   readsize = (bfd_size_type) nscns * scnhsz;
-  external_sections = (char *) bfd_alloc (abfd, readsize);
+  external_sections = (char *) _bfd_alloc_and_read (abfd, readsize, readsize);
   if (!external_sections)
     goto fail;
 
-  if (bfd_bread ((void *) external_sections, readsize, abfd) != readsize)
-    goto fail;
-
   /* Set the arch/mach *before* swapping in sections; section header swapping
      may depend on arch/mach info.  */
   if (! bfd_coff_set_arch_mach_hook (abfd, (void *) internal_f))
@@ -299,21 +299,23 @@ coff_real_object_p (bfd *abfd,
        }
     }
 
-  return abfd->xvec;
+  _bfd_coff_free_symbols (abfd);
+  return _bfd_no_cleanup;
 
  fail:
+  _bfd_coff_free_symbols (abfd);
   bfd_release (abfd, tdata);
  fail2:
   abfd->tdata.any = tdata_save;
   abfd->flags = oflags;
-  bfd_get_start_address (abfd) = ostart;
-  return (const bfd_target *) NULL;
+  abfd->start_address = ostart;
+  return NULL;
 }
 
 /* Turn a COFF file into a BFD, but fail with bfd_error_wrong_format if it is
    not a COFF file.  This is also used by ECOFF.  */
 
-const bfd_target *
+bfd_cleanup
 coff_object_p (bfd *abfd)
 {
   bfd_size_type filhsz;
@@ -327,14 +329,11 @@ coff_object_p (bfd *abfd)
   filhsz = bfd_coff_filhsz (abfd);
   aoutsz = bfd_coff_aoutsz (abfd);
 
-  filehdr = bfd_alloc (abfd, filhsz);
+  filehdr = _bfd_alloc_and_read (abfd, filhsz, filhsz);
   if (filehdr == NULL)
-    return NULL;
-  if (bfd_bread (filehdr, filhsz, abfd) != filhsz)
     {
       if (bfd_get_error () != bfd_error_system_call)
        bfd_set_error (bfd_error_wrong_format);
-      bfd_release (abfd, filehdr);
       return NULL;
     }
   bfd_coff_swap_filehdr_in (abfd, filehdr, &internal_f);
@@ -360,18 +359,13 @@ coff_object_p (bfd *abfd)
     {
       void * opthdr;
 
-      opthdr = bfd_alloc (abfd, aoutsz);
+      opthdr = _bfd_alloc_and_read (abfd, aoutsz, internal_f.f_opthdr);
       if (opthdr == NULL)
        return NULL;
-      if (bfd_bread (opthdr, (bfd_size_type) internal_f.f_opthdr, abfd)
-         != internal_f.f_opthdr)
-       {
-         bfd_release (abfd, opthdr);
-         return NULL;
-       }
       /* PR 17512: file: 11056-1136-0.004.  */
       if (internal_f.f_opthdr < aoutsz)
-       memset (((char *) opthdr) + internal_f.f_opthdr, 0, aoutsz - internal_f.f_opthdr);
+       memset (((char *) opthdr) + internal_f.f_opthdr, 0,
+               aoutsz - internal_f.f_opthdr);
 
       bfd_coff_swap_aouthdr_in (abfd, opthdr, (void *) &internal_a);
       bfd_release (abfd, opthdr);
@@ -550,11 +544,8 @@ _bfd_coff_read_internal_relocs (bfd *abfd,
   for (; erel < erel_end; erel += relsz, irel++)
     bfd_coff_swap_reloc_in (abfd, (void *) erel, (void *) irel);
 
-  if (free_external != NULL)
-    {
-      free (free_external);
-      free_external = NULL;
-    }
+  free (free_external);
+  free_external = NULL;
 
   if (cache && free_internal != NULL)
     {
@@ -572,10 +563,8 @@ _bfd_coff_read_internal_relocs (bfd *abfd,
   return internal_relocs;
 
  error_return:
-  if (free_external != NULL)
-    free (free_external);
-  if (free_internal != NULL)
-    free (free_internal);
+  free (free_external);
+  free (free_internal);
   return NULL;
 }
 
@@ -593,7 +582,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;
@@ -611,13 +600,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
@@ -673,11 +662,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
        {
@@ -821,8 +810,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));
@@ -886,13 +875,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;
@@ -1066,6 +1055,7 @@ bfd_boolean
 coff_write_alien_symbol (bfd *abfd,
                         asymbol *symbol,
                         struct internal_syment *isym,
+                        union internal_auxent *iaux,
                         bfd_vma *written,
                         bfd_size_type *string_size_p,
                         asection **debug_string_section_p,
@@ -1085,7 +1075,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;
@@ -1112,12 +1102,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
@@ -1129,7 +1119,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)
@@ -1151,6 +1141,8 @@ coff_write_alien_symbol (bfd *abfd,
                           debug_string_section_p, debug_string_size_p);
   if (isym != NULL)
     *isym = native->u.syment;
+  if (iaux != NULL && native->u.syment.n_numaux)
+    *iaux = native[1].u.auxent;
   return ret;
 }
 
@@ -1215,7 +1207,8 @@ coff_write_native_symbol (bfd *abfd,
 }
 
 static void
-null_error_handler (const char * fmt ATTRIBUTE_UNUSED, ...)
+null_error_handler (const char *fmt ATTRIBUTE_UNUSED,
+                   va_list ap ATTRIBUTE_UNUSED)
 {
 }
 
@@ -1268,7 +1261,7 @@ coff_write_symbols (bfd *abfd)
       if (c_symbol == (coff_symbol_type *) NULL
          || c_symbol->native == (combined_entry_type *) NULL)
        {
-         if (!coff_write_alien_symbol (abfd, symbol, NULL, &written,
+         if (!coff_write_alien_symbol (abfd, symbol, NULL, NULL, &written,
                                        &string_size, &debug_string_section,
                                        &debug_string_size))
            return FALSE;
@@ -1381,7 +1374,7 @@ coff_write_symbols (bfd *abfd)
 
          else if (! c_symbol->native->is_sym)
            maxlen = bfd_coff_force_symnames_in_strings (abfd) ? 0 : SYMNMLEN;
-           
+
          else if (bfd_coff_symname_in_debug (abfd,
                                              &c_symbol->native->u.syment))
            /* This symbol name is in the XCOFF .debug section.
@@ -1412,8 +1405,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];
 
@@ -1515,7 +1508,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;
@@ -1541,15 +1535,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;
@@ -1576,19 +1577,20 @@ build_debug_section (bfd *abfd, asection ** sect_return)
       return NULL;
     }
 
-  sec_size = sect->size;
-  debug_section = (char *) bfd_alloc (abfd, sec_size);
-  if (debug_section == NULL)
-    return NULL;
-
   /* Seek to the beginning of the `.debug' section and read it.
      Save the current position first; it is needed by our caller.
      Then read debug section and reset the file pointer.  */
 
   position = bfd_tell (abfd);
-  if (bfd_seek (abfd, sect->filepos, SEEK_SET) != 0
-      || bfd_bread (debug_section, sec_size, abfd) != sec_size
-      || bfd_seek (abfd, position, SEEK_SET) != 0)
+  if (bfd_seek (abfd, sect->filepos, SEEK_SET) != 0)
+    return NULL;
+
+  sec_size = sect->size;
+  debug_section = (char *) _bfd_alloc_and_read (abfd, sec_size, sec_size);
+  if (debug_section == NULL)
+    return NULL;
+
+  if (bfd_seek (abfd, position, SEEK_SET) != 0)
     return NULL;
 
   * sect_return = sect;
@@ -1622,34 +1624,28 @@ copy_name (bfd *abfd, char *name, size_t maxlen)
 bfd_boolean
 _bfd_coff_get_external_symbols (bfd *abfd)
 {
-  bfd_size_type symesz;
-  bfd_size_type size;
+  size_t symesz;
+  size_t size;
   void * syms;
 
   if (obj_coff_external_syms (abfd) != NULL)
     return TRUE;
 
   symesz = bfd_coff_symesz (abfd);
+  if (_bfd_mul_overflow (obj_raw_syment_count (abfd), symesz, &size))
+    {
+      bfd_set_error (bfd_error_file_truncated);
+      return FALSE;
+    }
 
-  size = obj_raw_syment_count (abfd) * symesz;
   if (size == 0)
     return TRUE;
 
-  syms = bfd_malloc (size);
-  if (syms == NULL)
+  if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0)
     return FALSE;
-
-  if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0
-      || bfd_bread (syms, size, abfd) != size)
-    {
-      if (syms != NULL)
-       free (syms);
-      return FALSE;
-    }
-
+  syms = _bfd_malloc_and_read (abfd, size, size);
   obj_coff_external_syms (abfd) = syms;
-
-  return TRUE;
+  return syms != NULL;
 }
 
 /* Read in the external strings.  The strings are not loaded until
@@ -1665,6 +1661,7 @@ _bfd_coff_read_string_table (bfd *abfd)
   bfd_size_type strsize;
   char *strings;
   file_ptr pos;
+  ufile_ptr filesize;
 
   if (obj_coff_strings (abfd) != NULL)
     return obj_coff_strings (abfd);
@@ -1698,10 +1695,13 @@ _bfd_coff_read_string_table (bfd *abfd)
 #endif
     }
 
-  if (strsize < STRING_SIZE_SIZE)
+  filesize = bfd_get_file_size (abfd);
+  if (strsize < STRING_SIZE_SIZE
+      || (filesize != 0 && strsize > filesize))
     {
-      (*_bfd_error_handler)
-       (_("%B: bad string table size %lu"), abfd, (unsigned long) strsize);
+      _bfd_error_handler
+       /* xgettext: c-format */
+       (_("%pB: bad string table size %" PRIu64), abfd, (uint64_t) strsize);
       bfd_set_error (bfd_error_bad_value);
       return NULL;
     }
@@ -1735,12 +1735,16 @@ _bfd_coff_read_string_table (bfd *abfd)
 bfd_boolean
 _bfd_coff_free_symbols (bfd *abfd)
 {
+  if (! bfd_family_coff (abfd))
+    return FALSE;
+
   if (obj_coff_external_syms (abfd) != NULL
       && ! obj_coff_keep_syms (abfd))
     {
       free (obj_coff_external_syms (abfd));
       obj_coff_external_syms (abfd) = NULL;
     }
+
   if (obj_coff_strings (abfd) != NULL
       && ! obj_coff_keep_strings (abfd))
     {
@@ -1748,6 +1752,7 @@ _bfd_coff_free_symbols (bfd *abfd)
       obj_coff_strings (abfd) = NULL;
       obj_coff_strings_len (abfd) = 0;
     }
+
   return TRUE;
 }
 
@@ -1777,12 +1782,16 @@ coff_get_normalized_symtab (bfd *abfd)
   if (! _bfd_coff_get_external_symbols (abfd))
     return NULL;
 
-  size = obj_raw_syment_count (abfd) * sizeof (combined_entry_type);
+  size = obj_raw_syment_count (abfd);
+  /* Check for integer overflow.  */
+  if (size > (bfd_size_type) -1 / sizeof (combined_entry_type))
+    return NULL;
+  size *= sizeof (combined_entry_type);
   internal = (combined_entry_type *) bfd_zalloc (abfd, size);
   if (internal == NULL && size != 0)
     return NULL;
   internal_end = internal + obj_raw_syment_count (abfd);
-  
+
   raw_src = (char *) obj_coff_external_syms (abfd);
 
   /* Mark the end of the symbols.  */
@@ -1804,11 +1813,8 @@ coff_get_normalized_symtab (bfd *abfd)
       symbol_ptr = internal_ptr;
       internal_ptr->is_sym = TRUE;
 
-      /* PR 17512: file: 1353-1166-0.004.  */
-      if (symbol_ptr->u.syment.n_sclass == C_FILE
-         && symbol_ptr->u.syment.n_numaux > 0
-         && raw_src + symesz + symbol_ptr->u.syment.n_numaux
-         * symesz > raw_end)
+      /* PR 17512: Prevent buffer overrun.  */
+      if (symbol_ptr->u.syment.n_numaux > (raw_end - raw_src) / symesz)
        {
          bfd_release (abfd, internal);
          return NULL;
@@ -1819,14 +1825,8 @@ coff_get_normalized_symtab (bfd *abfd)
           i++)
        {
          internal_ptr++;
-         /* PR 17512: Prevent buffer overrun.  */
-         if (internal_ptr >= internal_end)
-           {
-             bfd_release (abfd, internal);
-             return NULL;
-           }
-
          raw_src += symesz;
+
          bfd_coff_swap_aux_in (abfd, (void *) raw_src,
                                symbol_ptr->u.syment.n_type,
                                symbol_ptr->u.syment.n_sclass,
@@ -1835,14 +1835,17 @@ 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);
        }
     }
 
-  /* Free the raw symbols, but not the strings (if we have them).  */
-  obj_coff_keep_strings (abfd) = TRUE;
-  if (! _bfd_coff_free_symbols (abfd))
-    return NULL;
+  /* Free the raw symbols.  */
+  if (obj_coff_external_syms (abfd) != NULL
+      && ! obj_coff_keep_syms (abfd))
+    {
+      free (obj_coff_external_syms (abfd));
+      obj_coff_external_syms (abfd) = NULL;
+    }
 
   for (internal_ptr = internal; internal_ptr < internal_end;
        internal_ptr++)
@@ -1878,8 +1881,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 =
@@ -1904,7 +1907,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;
@@ -1921,7 +1924,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);
@@ -1975,13 +1978,20 @@ 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 *);
 }
 
 asymbol *
 coff_make_empty_symbol (bfd *abfd)
 {
-  bfd_size_type amt = sizeof (coff_symbol_type);
+  size_t amt = sizeof (coff_symbol_type);
   coff_symbol_type *new_symbol = (coff_symbol_type *) bfd_zalloc (abfd, amt);
 
   if (new_symbol == NULL)
@@ -2002,7 +2012,7 @@ coff_bfd_make_debug_symbol (bfd *abfd,
                            void * ptr ATTRIBUTE_UNUSED,
                            unsigned long sz ATTRIBUTE_UNUSED)
 {
-  bfd_size_type amt = sizeof (coff_symbol_type);
+  size_t amt = sizeof (coff_symbol_type);
   coff_symbol_type *new_symbol = (coff_symbol_type *) bfd_alloc (abfd, amt);
 
   if (new_symbol == NULL)
@@ -2130,7 +2140,7 @@ coff_print_symbol (bfd *abfd,
                                 auxp->u.auxent.x_scn.x_comdat);
                      break;
                    }
-                   /* Otherwise fall through.  */
+                 /* Fall through.  */
                case C_EXT:
                case C_AIX_WEAKEXT:
                  if (ISFCN (combined->u.syment.n_type))
@@ -2150,7 +2160,7 @@ coff_print_symbol (bfd *abfd,
                               llnos, next);
                      break;
                    }
-                 /* Otherwise fall through.  */
+                 /* Fall through.  */
                default:
                  fprintf (file, "AUX lnno %d size 0x%x tagndx %ld",
                           auxp->u.auxent.x_sym.x_misc.x_lnsz.x_lnno,
@@ -2210,13 +2220,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;
@@ -2227,7 +2237,7 @@ coff_find_nearest_line_with_names (bfd *abfd,
   combined_entry_type *pend;
   alent *l;
   struct coff_section_tdata *sec_data;
-  bfd_size_type amt;
+  size_t amt;
 
   /* Before looking through the symbol table, try to use a .stab
      section to find the information.  */
@@ -2243,26 +2253,47 @@ 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;
 
+  sec_data = coff_section_data (abfd, section);
+
   /* If the DWARF lookup failed, but there is DWARF information available
      then the problem might be that the file has been rebased.  This tool
      changes the VMAs of all the sections, but it does not update the DWARF
      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)
+       {
+         amt = sizeof (struct coff_section_tdata);
+         section->used_by_bfd = bfd_zalloc (abfd, amt);
+         sec_data = (struct coff_section_tdata *) section->used_by_bfd;
+       }
+
+      if (sec_data != NULL && sec_data->saved_bias)
+       bias = sec_data->saved_bias;
+      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;
+             sec_data->bias = bias;
+           }
+       }
 
-      bias = _bfd_dwarf2_find_symbol_bias (symbols,
-                                          & coff_data (abfd)->dwarf2_find_line_info);
-      
       if (bias
          && _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;
     }
@@ -2298,7 +2329,7 @@ coff_find_nearest_line_with_names (bfd *abfd,
       bfd_vma maxdiff;
 
       /* Look through the C_FILE symbols to find the best one.  */
-      sec_vma = bfd_get_section_vma (abfd, section);
+      sec_vma = bfd_section_vma (section);
       *filename_ptr = (char *) p->u.syment._n._n_n._n_offset;
       maxdiff = (bfd_vma) 0 - (bfd_vma) 1;
       while (1)
@@ -2331,7 +2362,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)
@@ -2340,21 +2371,30 @@ coff_find_nearest_line_with_names (bfd *abfd,
              maxdiff = offset + sec_vma - p2->u.syment.n_value;
            }
 
+         if (p->u.syment.n_value >= cof->raw_syment_count)
+           break;
+
          /* Avoid endless loops on erroneous files by ensuring that
             we always move forward in the file.  */
          if (p >= cof->raw_syments + p->u.syment.n_value)
            break;
 
          p = cof->raw_syments + p->u.syment.n_value;
-         if (p > pend || p->u.syment.n_sclass != C_FILE)
+         if (!p->is_sym || p->u.syment.n_sclass != C_FILE)
            break;
        }
     }
 
-  /* Now wander though the raw linenumbers of the section.  */
-  /* If we have been called on this section before, and the offset we
-     want is further down then we can prime the lookup loop.  */
-  sec_data = coff_section_data (abfd, section);
+  if (section->lineno_count == 0)
+    {
+      *functionname_ptr = NULL;
+      *line_ptr = 0;
+      return TRUE;
+    }
+
+  /* Now wander though the raw linenumbers of the section.
+     If we have been called on this section before, and the offset
+     we want is further down then we can prime the lookup loop.  */
   if (sec_data != NULL
       && sec_data->i > 0
       && offset >= sec_data->offset)
@@ -2383,6 +2423,7 @@ coff_find_nearest_line_with_names (bfd *abfd,
              coff_symbol_type *coff = (coff_symbol_type *) (l->u.sym);
              if (coff->symbol.value > offset)
                break;
+
              *functionname_ptr = coff->symbol.name;
              last_value = coff->symbol.value;
              if (coff->native)
@@ -2439,6 +2480,7 @@ coff_find_nearest_line_with_names (bfd *abfd,
       section->used_by_bfd = bfd_zalloc (abfd, amt);
       sec_data = (struct coff_section_tdata *) section->used_by_bfd;
     }
+
   if (sec_data != NULL)
     {
       sec_data->offset = offset;
@@ -2463,8 +2505,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
@@ -2486,7 +2528,7 @@ coff_sizeof_headers (bfd *abfd, struct bfd_link_info *info)
 {
   size_t size;
 
-  if (!info->relocatable)
+  if (!bfd_link_relocatable (info))
     size = bfd_coff_filhsz (abfd) + bfd_coff_aoutsz (abfd);
   else
     size = bfd_coff_filhsz (abfd);
@@ -2498,9 +2540,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;
 
@@ -2518,7 +2560,7 @@ bfd_coff_set_symbol_class (bfd *         abfd,
         coff_write_alien_symbol().  */
 
       combined_entry_type * native;
-      bfd_size_type amt = sizeof (* native);
+      size_t amt = sizeof (* native);
 
       native = (combined_entry_type *) bfd_zalloc (abfd, amt);
       if (native == NULL)
@@ -2571,6 +2613,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;
@@ -2579,7 +2624,7 @@ _bfd_coff_section_already_linked (bfd *abfd,
   if ((flags & SEC_GROUP) != 0)
     return FALSE;
 
-  name = bfd_get_section_name (abfd, sec);
+  name = bfd_section_name (sec);
   s_comdat = bfd_coff_get_comdat_section (abfd, sec);
 
   if (s_comdat != NULL)
@@ -2688,7 +2733,13 @@ static void
 fini_reloc_cookie_rels (struct coff_reloc_cookie *cookie,
                        asection *sec)
 {
-  if (cookie->rels && coff_section_data (NULL, sec)->relocs != cookie->rels)
+  if (cookie->rels
+      /* PR 20401.  The relocs may not have been cached, so check first.
+        If the relocs were loaded by init_reloc_cookie_rels() then this
+        will be the case.  FIXME: Would performance be improved if the
+        relocs *were* cached ?  */
+      && coff_section_data (NULL, sec)
+      && coff_section_data (NULL, sec)->relocs != cookie->rels)
     free (cookie->rels);
 }
 
@@ -2731,19 +2782,33 @@ _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_undefined:
        case bfd_link_hash_undefweak:
-        default:
-          break;
-        }
+         if (h->symbol_class == C_NT_WEAK && h->numaux == 1)
+           {
+             /* PE weak externals.  A weak symbol may include an auxiliary
+                record indicating that if the weak symbol is not resolved,
+                another external symbol is used instead.  */
+             struct coff_link_hash_entry *h2 =
+               h->auxbfd->tdata.coff_obj_data->sym_hashes[
+                   h->aux->x_sym.x_tagndx.l];
+
+             if (h2 && h2->root.type != bfd_link_hash_undefined)
+               return  h2->root.u.def.section;
+           }
+         break;
+
+       case bfd_link_hash_undefined:
+       default:
+         break;
+       }
       return NULL;
     }
 
@@ -2822,19 +2887,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;
@@ -2851,7 +2916,7 @@ _bfd_coff_gc_mark_extra_sections (struct bfd_link_info *info,
       asection *isec;
       bfd_boolean some_kept;
 
-      if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
+      if (bfd_get_flavour (ibfd) != bfd_target_coff_flavour)
        continue;
 
       /* Ensure all linker created sections are kept, and see whether
@@ -2922,10 +2987,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"))
@@ -2943,7 +3008,9 @@ coff_gc_sweep (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
          o->flags |= SEC_EXCLUDE;
 
          if (info->print_gc_sections && o->size != 0)
-            _bfd_error_handler (_("Removing unused section '%s' in file '%B'"), sub, o->name);
+           /* xgettext: c-format */
+           _bfd_error_handler (_("removing unused section '%pA' in file '%pB'"),
+                               o, sub);
 
 #if 0
          /* But we also have to update some of the relocation
@@ -3019,7 +3086,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
@@ -3032,10 +3099,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")
@@ -3045,7 +3112,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.  */
@@ -3054,3 +3121,31 @@ bfd_coff_gc_sections (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
   /* ... and mark SEC_EXCLUDE for those that go.  */
   return coff_gc_sweep (abfd, info);
 }
+
+/* Return name used to identify a comdat group.  */
+
+const char *
+bfd_coff_group_name (bfd *abfd, const asection *sec)
+{
+  struct coff_comdat_info *ci = bfd_coff_get_comdat_section (abfd, sec);
+  if (ci != NULL)
+    return ci->name;
+  return NULL;
+}
+
+bfd_boolean
+_bfd_coff_close_and_cleanup (bfd *abfd)
+{
+  if (abfd->format == bfd_object
+      && bfd_family_coff (abfd)
+      && coff_data (abfd) != NULL)
+    {
+      /* PR 25447:
+        Do not clear the keep_syms and keep_strings flags.
+        These may have been set by pe_ILF_build_a_bfd() indicating
+        that the syms and strings pointers are not to be freed.  */
+      if (!_bfd_coff_free_symbols (abfd))
+       return FALSE;
+    }
+  return _bfd_generic_close_and_cleanup (abfd);
+}
This page took 0.046166 seconds and 4 git commands to generate.