Revert changes in previous deltas that introduced new failures into
[deliverable/binutils-gdb.git] / bfd / coffgen.c
index 0ecc6023e6d5766c2a6c1a65ec9f2e023313fa23..4856a40e5e72e3d227099d090366bdbe5648d961 100644 (file)
@@ -1,7 +1,5 @@
 /* Support for the generic parts of COFF, for BFD.
-   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-   2000, 2001, 2002, 2003, 2004, 2005, 2007
-   Free Software Foundation, Inc.
+   Copyright (C) 1990-2014 Free Software Foundation, Inc.
    Written by Cygnus Support.
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -59,8 +57,13 @@ make_a_section_from_file (bfd *abfd,
 
   name = NULL;
 
-  /* Handle long section names as in PE.  */
-  if (bfd_coff_long_section_names (abfd)
+  /* Handle long section names as in PE.  On reading, we want to
+    accept long names if the format permits them at all, regardless
+    of the current state of the flag that dictates if we would generate
+    them in outputs; this construct checks if that is the case by
+    attempting to set the flag, without changing its state; the call
+    will fail for formats that do not support long names at all.  */
+  if (bfd_coff_set_long_section_names (abfd, bfd_coff_long_section_names (abfd))
       && hdr->s_name[0] == '/')
     {
       char buf[SCNNMLEN];
@@ -68,6 +71,11 @@ make_a_section_from_file (bfd *abfd,
       char *p;
       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.  */
+      bfd_coff_set_long_section_names (abfd, TRUE);
       memcpy (buf, hdr->s_name + 1, SCNNMLEN - 1);
       buf[SCNNMLEN - 1] = '\0';
       strindex = strtol (buf, &p, 10);
@@ -76,11 +84,11 @@ make_a_section_from_file (bfd *abfd,
          strings = _bfd_coff_read_string_table (abfd);
          if (strings == NULL)
            return FALSE;
-         /* FIXME: For extra safety, we should make sure that
-             strindex does not run us past the end, but right now we
-             don't know the length of the string table.  */
+         if ((bfd_size_type)(strindex + 2) >= obj_coff_strings_len (abfd))
+           return FALSE;
          strings += strindex;
-         name = bfd_alloc (abfd, (bfd_size_type) strlen (strings) + 1);
+         name = (char *) bfd_alloc (abfd,
+                                     (bfd_size_type) strlen (strings) + 1 + 1);
          if (name == NULL)
            return FALSE;
          strcpy (name, strings);
@@ -90,7 +98,8 @@ make_a_section_from_file (bfd *abfd,
   if (name == NULL)
     {
       /* Assorted wastage to null-terminate the name, thanks AT&T! */
-      name = bfd_alloc (abfd, (bfd_size_type) sizeof (hdr->s_name) + 1);
+      name = (char *) bfd_alloc (abfd,
+                                 (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));
@@ -134,13 +143,87 @@ make_a_section_from_file (bfd *abfd,
   if (hdr->s_scnptr != 0)
     return_section->flags |= SEC_HAS_CONTENTS;
 
+  /* Compress/decompress DWARF debug sections with names: .debug_* and
+     .zdebug_*, after the section flags is set.  */
+  if ((flags & SEC_DEBUGGING)
+      && ((name[1] == 'd' && name[6] == '_')
+         || (name[1] == 'z' && name[7] == '_')))
+    {
+      enum { nothing, compress, decompress } action = nothing;
+      char *new_name = NULL;
+
+      if (bfd_is_section_compressed (abfd, return_section))
+       {
+         /* Compressed section.  Check if we should decompress.  */
+         if ((abfd->flags & BFD_DECOMPRESS))
+           action = decompress;
+       }
+      else if (!bfd_is_section_compressed (abfd, return_section))
+       {
+         /* Normal section.  Check if we should compress.  */
+         if ((abfd->flags & BFD_COMPRESS) && return_section->size != 0)
+           action = compress;
+       }
+
+      switch (action)
+       {
+       case nothing:
+         break;
+       case compress:
+         if (!bfd_init_section_compress_status (abfd, return_section))
+           {
+             (*_bfd_error_handler)
+               (_("%B: unable to initialize compress status for section %s"),
+                abfd, name);
+             return FALSE;
+           }
+         if (name[1] != 'z')
+           {
+             unsigned int len = strlen (name);
+
+             new_name = bfd_alloc (abfd, len + 2);
+             if (new_name == NULL)
+               return FALSE;
+             new_name[0] = '.';
+             new_name[1] = 'z';
+             memcpy (new_name + 2, name + 1, len);
+           }
+         break;
+       case decompress:
+         if (!bfd_init_section_decompress_status (abfd, return_section))
+           {
+             (*_bfd_error_handler)
+               (_("%B: unable to initialize decompress status for section %s"),
+                abfd, name);
+             return FALSE;
+           }
+         if (name[1] == 'z')
+           {
+             unsigned int len = strlen (name);
+
+             new_name = bfd_alloc (abfd, len);
+             if (new_name == NULL)
+               return FALSE;
+             new_name[0] = '.';
+             memcpy (new_name + 1, name + 2, len - 1);
+           }
+         break;
+       }
+      if (new_name != NULL)
+       bfd_rename_section (abfd, return_section, new_name);
+    }
+
   return result;
 }
 
 /* Read in a COFF object and make it into a BFD.  This is used by
    ECOFF as well.  */
-
-static const bfd_target *
+const bfd_target *
+coff_real_object_p (bfd *,
+                    unsigned,
+                    struct internal_filehdr *,
+                    struct internal_aouthdr *);
+const bfd_target *
 coff_real_object_p (bfd *abfd,
                    unsigned nscns,
                    struct internal_filehdr *internal_f,
@@ -185,7 +268,7 @@ coff_real_object_p (bfd *abfd,
 
   scnhsz = bfd_coff_scnhsz (abfd);
   readsize = (bfd_size_type) nscns * scnhsz;
-  external_sections = bfd_alloc (abfd, readsize);
+  external_sections = (char *) bfd_alloc (abfd, readsize);
   if (!external_sections)
     goto fail;
 
@@ -295,20 +378,20 @@ coff_object_p (bfd *abfd)
 /* Get the BFD section from a COFF symbol section number.  */
 
 asection *
-coff_section_from_bfd_index (bfd *abfd, int index)
+coff_section_from_bfd_index (bfd *abfd, int section_index)
 {
   struct bfd_section *answer = abfd->sections;
 
-  if (index == N_ABS)
+  if (section_index == N_ABS)
     return bfd_abs_section_ptr;
-  if (index == N_UNDEF)
+  if (section_index == N_UNDEF)
     return bfd_und_section_ptr;
-  if (index == N_DEBUG)
+  if (section_index == N_DEBUG)
     return bfd_abs_section_ptr;
 
   while (answer)
     {
-      if (answer->target_index == index)
+      if (answer->target_index == section_index)
        return answer;
       answer = answer->next;
     }
@@ -380,6 +463,8 @@ _bfd_coff_internal_syment_name (bfd *abfd,
          if (strings == NULL)
            return NULL;
        }
+      if (sym->_n._n_n._n_offset >= obj_coff_strings_len (abfd))
+       return NULL;
       return strings + sym->_n._n_n._n_offset;
     }
 }
@@ -427,7 +512,7 @@ _bfd_coff_read_internal_relocs (bfd *abfd,
   amt = sec->reloc_count * relsz;
   if (external_relocs == NULL)
     {
-      free_external = bfd_malloc (amt);
+      free_external = (bfd_byte *) bfd_malloc (amt);
       if (free_external == NULL)
        goto error_return;
       external_relocs = free_external;
@@ -441,7 +526,7 @@ _bfd_coff_read_internal_relocs (bfd *abfd,
     {
       amt = sec->reloc_count;
       amt *= sizeof (struct internal_reloc);
-      free_internal = bfd_malloc (amt);
+      free_internal = (struct internal_reloc *) bfd_malloc (amt);
       if (free_internal == NULL)
        goto error_return;
       internal_relocs = free_internal;
@@ -565,7 +650,7 @@ fixup_symbol_value (bfd *abfd,
                    struct internal_syment *syment)
 {
   /* Normalize the symbol flags.  */
-  if (coff_symbol_ptr->symbol.section 
+  if (coff_symbol_ptr->symbol.section
       && bfd_is_com_section (coff_symbol_ptr->symbol.section))
     {
       /* A common symbol is undefined with a value.  */
@@ -641,7 +726,7 @@ coff_renumber_symbols (bfd *bfd_ptr, int *first_undef)
     bfd_size_type amt;
 
     amt = sizeof (asymbol *) * ((bfd_size_type) symbol_count + 1);
-    newsyms = bfd_alloc (bfd_ptr, amt);
+    newsyms = (asymbol **) bfd_alloc (bfd_ptr, amt);
     if (!newsyms)
       return FALSE;
     bfd_ptr->outsymbols = newsyms;
@@ -902,7 +987,10 @@ coff_write_symbol (bfd *abfd,
 {
   unsigned int numaux = native->u.syment.n_numaux;
   int type = native->u.syment.n_type;
-  int class = native->u.syment.n_sclass;
+  int n_sclass = (int) native->u.syment.n_sclass;
+  asection *output_section = symbol->section->output_section
+                              ? symbol->section->output_section
+                              : symbol->section;
   void * buf;
   bfd_size_type symesz;
 
@@ -921,7 +1009,7 @@ coff_write_symbol (bfd *abfd,
 
   else
     native->u.syment.n_scnum =
-      symbol->section->output_section->target_index;
+      output_section->target_index;
 
   coff_fix_symbol_name (abfd, symbol, native, string_size_p,
                        debug_string_section_p, debug_string_size_p);
@@ -948,7 +1036,7 @@ coff_write_symbol (bfd *abfd,
        {
          bfd_coff_swap_aux_out (abfd,
                                 &((native + j + 1)->u.auxent),
-                                type, class, (int) j,
+                                type, n_sclass, (int) j,
                                 native->u.syment.n_numaux,
                                 buf);
          if (bfd_bwrite (buf, auxesz, abfd) != auxesz)
@@ -968,20 +1056,36 @@ coff_write_symbol (bfd *abfd,
    file originally.  This symbol may have been created by the linker,
    or we may be linking a non COFF file to a COFF file.  */
 
-static bfd_boolean
+bfd_boolean
 coff_write_alien_symbol (bfd *abfd,
                         asymbol *symbol,
+                        struct internal_syment *isym,
                         bfd_vma *written,
                         bfd_size_type *string_size_p,
                         asection **debug_string_section_p,
                         bfd_size_type *debug_string_size_p)
 {
   combined_entry_type *native;
-  combined_entry_type dummy;
-
-  native = &dummy;
+  combined_entry_type dummy[2];
+  asection *output_section = symbol->section->output_section
+                              ? symbol->section->output_section
+                              : symbol->section;
+  struct bfd_link_info *link_info = coff_data (abfd)->link_info;
+  bfd_boolean ret;
+
+  if ((!link_info || link_info->strip_discarded)
+      && !bfd_is_abs_section (symbol->section)
+      && symbol->section->output_section == bfd_abs_section_ptr)
+    {
+      symbol->name = "";
+      if (isym != NULL)
+        memset (isym, 0, sizeof(*isym));
+      return TRUE;
+    }
+  native = dummy;
   native->u.syment.n_type = T_NULL;
   native->u.syment.n_flags = 0;
+  native->u.syment.n_numaux = 0;
   if (bfd_is_und_section (symbol->section))
     {
       native->u.syment.n_scnum = N_UNDEF;
@@ -992,6 +1096,11 @@ coff_write_alien_symbol (bfd *abfd,
       native->u.syment.n_scnum = N_UNDEF;
       native->u.syment.n_value = symbol->value;
     }
+  else if (symbol->flags & BSF_FILE)
+    {
+      native->u.syment.n_scnum = N_DEBUG;
+      native->u.syment.n_numaux = 1;
+    }
   else if (symbol->flags & BSF_DEBUGGING)
     {
       /* There isn't much point to writing out a debugging symbol
@@ -999,16 +1108,17 @@ coff_write_alien_symbol (bfd *abfd,
          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));
       return TRUE;
     }
   else
     {
-      native->u.syment.n_scnum =
-       symbol->section->output_section->target_index;
+      native->u.syment.n_scnum = output_section->target_index;
       native->u.syment.n_value = (symbol->value
                                  + symbol->section->output_offset);
       if (! obj_pe (abfd))
-       native->u.syment.n_value += symbol->section->output_section->vma;
+       native->u.syment.n_value += output_section->vma;
 
       /* Copy the any flags from the file header into the symbol.
          FIXME: Why?  */
@@ -1020,16 +1130,20 @@ coff_write_alien_symbol (bfd *abfd,
     }
 
   native->u.syment.n_type = 0;
-  if (symbol->flags & BSF_LOCAL)
+  if (symbol->flags & BSF_FILE)
+    native->u.syment.n_sclass = C_FILE;
+  else if (symbol->flags & BSF_LOCAL)
     native->u.syment.n_sclass = C_STAT;
   else if (symbol->flags & BSF_WEAK)
     native->u.syment.n_sclass = obj_pe (abfd) ? C_NT_WEAK : C_WEAKEXT;
   else
     native->u.syment.n_sclass = C_EXT;
-  native->u.syment.n_numaux = 0;
 
-  return coff_write_symbol (abfd, symbol, native, written, string_size_p,
-                           debug_string_section_p, debug_string_size_p);
+  ret = coff_write_symbol (abfd, symbol, native, written, string_size_p,
+                          debug_string_section_p, debug_string_size_p);
+  if (isym != NULL)
+    *isym = native->u.syment;
+  return ret;
 }
 
 /* Write a native symbol to a COFF file.  */
@@ -1044,6 +1158,15 @@ coff_write_native_symbol (bfd *abfd,
 {
   combined_entry_type *native = symbol->native;
   alent *lineno = symbol->lineno;
+  struct bfd_link_info *link_info = coff_data (abfd)->link_info;
+
+  if ((!link_info || link_info->strip_discarded)
+      && !bfd_is_abs_section (symbol->symbol.section)
+      && symbol->symbol.section->output_section == bfd_abs_section_ptr)
+    {
+      symbol->symbol.name = "";
+      return TRUE;
+    }
 
   /* If this symbol has an associated line number, we must store the
      symbol index in the line number field.  We also tag the auxent to
@@ -1082,6 +1205,11 @@ coff_write_native_symbol (bfd *abfd,
                            debug_string_size_p);
 }
 
+static void
+null_error_handler (const char * fmt ATTRIBUTE_UNUSED, ...)
+{
+}
+
 /* Write out the COFF symbols.  */
 
 bfd_boolean
@@ -1131,13 +1259,50 @@ 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, &written, &string_size,
-                                       &debug_string_section,
+         if (!coff_write_alien_symbol (abfd, symbol, NULL, &written,
+                                       &string_size, &debug_string_section,
                                        &debug_string_size))
            return FALSE;
        }
       else
        {
+         if (coff_backend_info (abfd)->_bfd_coff_classify_symbol != NULL)
+           {
+             bfd_error_handler_type current_error_handler;
+             enum coff_symbol_classification sym_class;
+             unsigned char *n_sclass;
+
+             /* Suppress error reporting by bfd_coff_classify_symbol.
+                Error messages can be generated when we are processing a local
+                symbol which has no associated section and we do not have to
+                worry about this, all we need to know is that it is local.  */
+             current_error_handler = bfd_set_error_handler (null_error_handler);
+             sym_class = bfd_coff_classify_symbol (abfd,
+                                                   &c_symbol->native->u.syment);
+             (void) bfd_set_error_handler (current_error_handler);
+
+             n_sclass = &c_symbol->native->u.syment.n_sclass;
+
+             /* If the symbol class has been changed (eg objcopy/ld script/etc)
+                we cannot retain the existing sclass from the original symbol.
+                Weak symbols only have one valid sclass, so just set it always.
+                If it is not local class and should be, set it C_STAT.
+                If it is global and not classified as global, or if it is
+                weak (which is also classified as global), set it C_EXT.  */
+
+             if (symbol->flags & BSF_WEAK)
+               *n_sclass = obj_pe (abfd) ? C_NT_WEAK : C_WEAKEXT;
+             else if (symbol->flags & BSF_LOCAL && sym_class != COFF_SYMBOL_LOCAL)
+               *n_sclass = C_STAT;
+             else if (symbol->flags & BSF_GLOBAL
+                      && (sym_class != COFF_SYMBOL_GLOBAL
+#ifdef COFF_WITH_PE
+                          || *n_sclass == C_NT_WEAK
+#endif
+                          || *n_sclass == C_WEAKEXT))
+               c_symbol->native->u.syment.n_sclass = C_EXT;
+           }
+
          if (!coff_write_native_symbol (abfd, c_symbol, &written,
                                         &string_size, &debug_string_section,
                                         &debug_string_size))
@@ -1339,7 +1504,7 @@ coff_pointerize_aux (bfd *abfd,
                     combined_entry_type *auxent)
 {
   unsigned int type = symbol->u.syment.n_type;
-  unsigned int class = symbol->u.syment.n_sclass;
+  unsigned int n_sclass = symbol->u.syment.n_sclass;
 
   if (coff_backend_info (abfd)->_bfd_coff_pointerize_aux_hook)
     {
@@ -1349,16 +1514,17 @@ coff_pointerize_aux (bfd *abfd,
     }
 
   /* Don't bother if this is a file or a section.  */
-  if (class == C_STAT && type == T_NULL)
+  if (n_sclass == C_STAT && type == T_NULL)
     return;
-  if (class == C_FILE)
+  if (n_sclass == C_FILE)
     return;
 
   /* Otherwise patch up.  */
 #define N_TMASK coff_data  (abfd)->local_n_tmask
 #define N_BTSHFT coff_data (abfd)->local_n_btshft
-  
-  if ((ISFCN (type) || ISTAG (class) || class == C_BLOCK || class == C_FCN)
+
+  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.p =
@@ -1380,7 +1546,7 @@ coff_pointerize_aux (bfd *abfd,
    we didn't want to go to the trouble until someone needed it.  */
 
 static char *
-build_debug_section (bfd *abfd)
+build_debug_section (bfd *abfd, asection ** sect_return)
 {
   char *debug_section;
   file_ptr position;
@@ -1395,7 +1561,7 @@ build_debug_section (bfd *abfd)
     }
 
   sec_size = sect->size;
-  debug_section = bfd_alloc (abfd, sec_size);
+  debug_section = (char *) bfd_alloc (abfd, sec_size);
   if (debug_section == NULL)
     return NULL;
 
@@ -1408,6 +1574,8 @@ build_debug_section (bfd *abfd)
       || bfd_bread (debug_section, sec_size, abfd) != sec_size
       || bfd_seek (abfd, position, SEEK_SET) != 0)
     return NULL;
+
+  * sect_return = sect;
   return debug_section;
 }
 
@@ -1425,7 +1593,7 @@ copy_name (bfd *abfd, char *name, size_t maxlen)
     if (name[len] == '\0')
       break;
 
-  if ((newname = bfd_alloc (abfd, (bfd_size_type) len + 1)) == NULL)
+  if ((newname = (char *) bfd_alloc (abfd, (bfd_size_type) len + 1)) == NULL)
     return NULL;
 
   strncpy (newname, name, len);
@@ -1451,6 +1619,14 @@ _bfd_coff_get_external_symbols (bfd *abfd)
   if (size == 0)
     return TRUE;
 
+  /* PR binutils/17512: Do not even try to load
+     a symbol table bigger than the entire file...  */
+  if (size >= (bfd_size_type) bfd_get_size (abfd))
+    {
+      fprintf (stderr, "XXX SIZE FAIL 1\n");
+    return FALSE;
+    }
+
   syms = bfd_malloc (size);
   if (syms == NULL)
     return FALSE;
@@ -1470,7 +1646,9 @@ _bfd_coff_get_external_symbols (bfd *abfd)
 
 /* Read in the external strings.  The strings are not loaded until
    they are needed.  This is because we have no simple way of
-   detecting a missing string table in an archive.  */
+   detecting a missing string table in an archive.  If the strings
+   are loaded then the STRINGS and STRINGS_LEN fields in the
+   coff_tdata structure will be set.  */
 
 const char *
 _bfd_coff_read_string_table (bfd *abfd)
@@ -1520,7 +1698,7 @@ _bfd_coff_read_string_table (bfd *abfd)
       return NULL;
     }
 
-  strings = bfd_malloc (strsize);
+  strings = (char *) bfd_malloc (strsize);
   if (strings == NULL)
     return NULL;
 
@@ -1532,6 +1710,7 @@ _bfd_coff_read_string_table (bfd *abfd)
     }
 
   obj_coff_strings (abfd) = strings;
+  obj_coff_strings_len (abfd) = strsize;
 
   return strings;
 }
@@ -1552,6 +1731,7 @@ _bfd_coff_free_symbols (bfd *abfd)
     {
       free (obj_coff_strings (abfd));
       obj_coff_strings (abfd) = NULL;
+      obj_coff_strings_len (abfd) = 0;
     }
   return TRUE;
 }
@@ -1572,18 +1752,28 @@ coff_get_normalized_symtab (bfd *abfd)
   char *raw_src;
   char *raw_end;
   const char *string_table = NULL;
-  char *debug_section = NULL;
+  asection * debug_sec = NULL;
+  char *debug_sec_data = NULL;
   bfd_size_type size;
 
   if (obj_raw_syments (abfd) != NULL)
     return obj_raw_syments (abfd);
 
-  size = obj_raw_syment_count (abfd) * sizeof (combined_entry_type);
-  internal = bfd_zalloc (abfd, size);
+  size = obj_raw_syment_count (abfd);
+  /* PR binutils/17512: Do not even try to load
+     a symbol table bigger than the entire file...
+     Note - we do not fail on a size of 0.  Linker created
+     bfds can have this property and they are not corrupt.  */
+  if (size >= (bfd_size_type) bfd_get_size (abfd)
+      && bfd_get_size (abfd) > 0)
+    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);
-
+  
   if (! _bfd_coff_get_external_symbols (abfd))
     return NULL;
 
@@ -1601,8 +1791,8 @@ coff_get_normalized_symtab (bfd *abfd)
        raw_src < raw_end;
        raw_src += symesz, internal_ptr++)
     {
-
       unsigned int i;
+
       bfd_coff_swap_sym_in (abfd, (void *) raw_src,
                            (void *) & internal_ptr->u.syment);
       symbol_ptr = internal_ptr;
@@ -1612,6 +1802,10 @@ coff_get_normalized_symtab (bfd *abfd)
           i++)
        {
          internal_ptr++;
+         /* PR 17512: Prevent buffer overrun.  */
+         if (internal_ptr >= internal_end)
+           return NULL;
+
          raw_src += symesz;
          bfd_coff_swap_aux_in (abfd, (void *) raw_src,
                                symbol_ptr->u.syment.n_type,
@@ -1645,11 +1839,14 @@ coff_get_normalized_symtab (bfd *abfd)
                  if (string_table == NULL)
                    return NULL;
                }
-
-             internal_ptr->u.syment._n._n_n._n_offset =
-               ((bfd_hostptr_t)
-                (string_table
-                 + (internal_ptr + 1)->u.auxent.x_file.x_n.x_offset));
+             if ((bfd_size_type)((internal_ptr + 1)->u.auxent.x_file.x_n.x_offset)
+                 >= obj_coff_strings_len (abfd))
+               internal_ptr->u.syment._n._n_n._n_offset = (bfd_hostptr_t) _("<corrupt>");
+             else
+               internal_ptr->u.syment._n._n_n._n_offset =
+                 ((bfd_hostptr_t)
+                  (string_table
+                   + (internal_ptr + 1)->u.auxent.x_file.x_n.x_offset));
            }
          else
            {
@@ -1685,7 +1882,7 @@ coff_get_normalized_symtab (bfd *abfd)
                if (internal_ptr->u.syment._n._n_name[i] == '\0')
                  break;
 
-             newstring = bfd_zalloc (abfd, (bfd_size_type) (i + 1));
+             newstring = (char *) bfd_zalloc (abfd, (bfd_size_type) (i + 1));
              if (newstring == NULL)
                return NULL;
              strncpy (newstring, internal_ptr->u.syment._n._n_name, i);
@@ -1693,7 +1890,7 @@ coff_get_normalized_symtab (bfd *abfd)
              internal_ptr->u.syment._n._n_n._n_zeroes = 0;
            }
          else if (internal_ptr->u.syment._n._n_n._n_offset == 0)
-           internal_ptr->u.syment._n._n_n._n_offset = (bfd_vma) "";
+           internal_ptr->u.syment._n._n_n._n_offset = (bfd_hostptr_t) "";
          else if (!bfd_coff_symname_in_debug (abfd, &internal_ptr->u.syment))
            {
              /* Long name already.  Point symbol at the string in the
@@ -1704,18 +1901,31 @@ coff_get_normalized_symtab (bfd *abfd)
                  if (string_table == NULL)
                    return NULL;
                }
-             internal_ptr->u.syment._n._n_n._n_offset =
-               ((bfd_hostptr_t)
-                (string_table
-                 + internal_ptr->u.syment._n._n_n._n_offset));
+             if (internal_ptr->u.syment._n._n_n._n_offset >= obj_coff_strings_len (abfd))
+               internal_ptr->u.syment._n._n_n._n_offset = (bfd_hostptr_t) _("<corrupt>");
+             else
+               internal_ptr->u.syment._n._n_n._n_offset =
+                 ((bfd_hostptr_t)
+                  (string_table
+                   + internal_ptr->u.syment._n._n_n._n_offset));
            }
          else
            {
              /* Long name in debug section.  Very similar.  */
-             if (debug_section == NULL)
-               debug_section = build_debug_section (abfd);
-             internal_ptr->u.syment._n._n_n._n_offset = (bfd_hostptr_t)
-               (debug_section + internal_ptr->u.syment._n._n_n._n_offset);
+             if (debug_sec_data == NULL)
+               debug_sec_data = build_debug_section (abfd, & debug_sec);
+             if (debug_sec_data != NULL)
+               {
+                 BFD_ASSERT (debug_sec != NULL);
+                 /* PR binutils/17512: Catch out of range offsets into the debug data.  */
+                 if (internal_ptr->u.syment._n._n_n._n_offset > debug_sec->size)
+                   internal_ptr->u.syment._n._n_n._n_offset = (bfd_hostptr_t) _("<corrupt>");
+                 else
+                   internal_ptr->u.syment._n._n_n._n_offset = (bfd_hostptr_t)
+                     (debug_sec_data + internal_ptr->u.syment._n._n_n._n_offset);
+               }
+             else
+               internal_ptr->u.syment._n._n_n._n_offset = (bfd_hostptr_t) "";
            }
        }
       internal_ptr += internal_ptr->u.syment.n_numaux;
@@ -1743,17 +1953,17 @@ asymbol *
 coff_make_empty_symbol (bfd *abfd)
 {
   bfd_size_type amt = sizeof (coff_symbol_type);
-  coff_symbol_type *new = bfd_zalloc (abfd, amt);
+  coff_symbol_type *new_symbol = (coff_symbol_type *) bfd_zalloc (abfd, amt);
 
-  if (new == NULL)
+  if (new_symbol == NULL)
     return NULL;
-  new->symbol.section = 0;
-  new->native = 0;
-  new->lineno = NULL;
-  new->done_lineno = FALSE;
-  new->symbol.the_bfd = abfd;
+  new_symbol->symbol.section = 0;
+  new_symbol->native = 0;
+  new_symbol->lineno = NULL;
+  new_symbol->done_lineno = FALSE;
+  new_symbol->symbol.the_bfd = abfd;
 
-  return & new->symbol;
+  return & new_symbol->symbol;
 }
 
 /* Make a debugging symbol.  */
@@ -1764,23 +1974,23 @@ coff_bfd_make_debug_symbol (bfd *abfd,
                            unsigned long sz ATTRIBUTE_UNUSED)
 {
   bfd_size_type amt = sizeof (coff_symbol_type);
-  coff_symbol_type *new = bfd_alloc (abfd, amt);
+  coff_symbol_type *new_symbol = (coff_symbol_type *) bfd_alloc (abfd, amt);
 
-  if (new == NULL)
+  if (new_symbol == NULL)
     return NULL;
   /* @@ The 10 is a guess at a plausible maximum number of aux entries
      (but shouldn't be a constant).  */
   amt = sizeof (combined_entry_type) * 10;
-  new->native = bfd_zalloc (abfd, amt);
-  if (!new->native)
+  new_symbol->native = (combined_entry_type *) bfd_zalloc (abfd, amt);
+  if (!new_symbol->native)
     return NULL;
-  new->symbol.section = bfd_abs_section_ptr;
-  new->symbol.flags = BSF_DEBUGGING;
-  new->lineno = NULL;
-  new->done_lineno = FALSE;
-  new->symbol.the_bfd = abfd;
-  
-  return & new->symbol;
+  new_symbol->symbol.section = bfd_abs_section_ptr;
+  new_symbol->symbol.flags = BSF_DEBUGGING;
+  new_symbol->lineno = NULL;
+  new_symbol->done_lineno = FALSE;
+  new_symbol->symbol.the_bfd = abfd;
+
+  return & new_symbol->symbol;
 }
 
 void
@@ -1908,16 +2118,7 @@ coff_print_symbol (bfd *abfd,
                   combined->u.syment.n_type,
                   combined->u.syment.n_sclass,
                   combined->u.syment.n_numaux);
-#ifdef BFD64
-         /* fprintf_vma() on a 64-bit enabled host will always print a 64-bit
-            value, but really we want to display the address in the target's
-            address size.  Since we do not have a field in the bfd structure
-            to tell us this, we take a guess, based on the target's name.  */
-         if (strstr (bfd_get_target (abfd), "64") == NULL)
-           fprintf (file, "%08lx", (unsigned long) (val & 0xffffffff));
-         else
-#endif
-           fprintf_vma (file, val);
+         bfd_fprintf_vma (abfd, file, val);
          fprintf (file, " %s", symbol->name);
 
          for (aux = 0; aux < combined->u.syment.n_numaux; aux++)
@@ -1946,7 +2147,7 @@ coff_print_symbol (bfd *abfd,
                    /* Probably a section symbol ?  */
                    {
                      fprintf (file, "AUX scnlen 0x%lx nreloc %d nlnno %d",
-                              (long) auxp->u.auxent.x_scn.x_scnlen,
+                              (unsigned long) auxp->u.auxent.x_scn.x_scnlen,
                               auxp->u.auxent.x_scn.x_nreloc,
                               auxp->u.auxent.x_scn.x_nlinno);
                      if (auxp->u.auxent.x_scn.x_checksum != 0
@@ -1960,6 +2161,7 @@ coff_print_symbol (bfd *abfd,
                    }
                    /* Otherwise fall through.  */
                case C_EXT:
+               case C_AIX_WEAKEXT:
                  if (ISFCN (combined->u.syment.n_type))
                    {
                      long next, llnos;
@@ -1972,7 +2174,8 @@ coff_print_symbol (bfd *abfd,
                      llnos = auxp->u.auxent.x_sym.x_fcnary.x_fcn.x_lnnoptr;
                      fprintf (file,
                               "AUX tagndx %ld ttlsiz 0x%lx lnnos %ld next %ld",
-                              tagndx, auxp->u.auxent.x_sym.x_misc.x_fsize,
+                              tagndx,
+                              (unsigned long) auxp->u.auxent.x_sym.x_misc.x_fsize,
                               llnos, next);
                      break;
                    }
@@ -1998,7 +2201,7 @@ coff_print_symbol (bfd *abfd,
              while (l->line_number)
                {
                  fprintf (file, "\n%4d : ", l->line_number);
-                 fprintf_vma (file, l->u.offset + symbol->section->vma);
+                 bfd_fprintf_vma (abfd, file, l->u.offset + symbol->section->vma);
                  l++;
                }
            }
@@ -2032,13 +2235,14 @@ _bfd_coff_is_local_label_name (bfd *abfd ATTRIBUTE_UNUSED,
    nearest to the wanted location.  */
 
 bfd_boolean
-coff_find_nearest_line (bfd *abfd,
-                       asection *section,
-                       asymbol **symbols,
-                       bfd_vma offset,
-                       const char **filename_ptr,
-                       const char **functionname_ptr,
-                       unsigned int *line_ptr)
+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)
 {
   bfd_boolean found;
   unsigned int i;
@@ -2063,9 +2267,9 @@ coff_find_nearest_line (bfd *abfd,
     return TRUE;
 
   /* Also try examining DWARF2 debugging information.  */
-  if (_bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
+  if (_bfd_dwarf2_find_nearest_line (abfd, symbols, NULL, section, offset,
                                     filename_ptr, functionname_ptr,
-                                    line_ptr, 0,
+                                    line_ptr, NULL, debug_sections, 0,
                                     &coff_data(abfd)->dwarf2_find_line_info))
     return TRUE;
 
@@ -2104,6 +2308,7 @@ coff_find_nearest_line (bfd *abfd,
       maxdiff = (bfd_vma) 0 - (bfd_vma) 1;
       while (1)
        {
+         bfd_vma file_addr;
          combined_entry_type *p2;
 
          for (p2 = p + 1 + p->u.syment.n_numaux;
@@ -2122,11 +2327,16 @@ coff_find_nearest_line (bfd *abfd,
                }
            }
 
+         file_addr = (bfd_vma) p2->u.syment.n_value;
+         /* PR 11512: Include the section address of the function name symbol.  */
+         if (p2->u.syment.n_scnum > 0)
+           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.  */
          if (p2 < pend
-             && offset + sec_vma >= (bfd_vma) p2->u.syment.n_value
-             && offset + sec_vma - (bfd_vma) p2->u.syment.n_value <= maxdiff)
+             && offset + sec_vma >= file_addr
+             && offset + sec_vma - file_addr <= maxdiff)
            {
              *filename_ptr = (char *) p->u.syment._n._n_n._n_offset;
              maxdiff = offset + sec_vma - p2->u.syment.n_value;
@@ -2144,7 +2354,7 @@ coff_find_nearest_line (bfd *abfd,
     }
 
   /* Now wander though the raw linenumbers of the section.  */
-  /* If we have been called on this section before, and the offset we
+  /* 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 (sec_data != NULL
@@ -2231,7 +2441,7 @@ coff_find_nearest_line (bfd *abfd,
   if (sec_data != NULL)
     {
       sec_data->offset = offset;
-      sec_data->i = i;
+      sec_data->i = i - 1;
       sec_data->function = *functionname_ptr;
       sec_data->line_base = line_base;
     }
@@ -2239,6 +2449,23 @@ coff_find_nearest_line (bfd *abfd,
   return TRUE;
 }
 
+bfd_boolean
+coff_find_nearest_line (bfd *abfd,
+                       asymbol **symbols,
+                       asection *section,
+                       bfd_vma offset,
+                       const char **filename_ptr,
+                       const char **functionname_ptr,
+                       unsigned int *line_ptr,
+                       unsigned int *discriminator_ptr)
+{
+  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);
+}
+
 bfd_boolean
 coff_find_inliner_info (bfd *abfd,
                        const char **filename_ptr,
@@ -2272,7 +2499,7 @@ coff_sizeof_headers (bfd *abfd, struct bfd_link_info *info)
 bfd_boolean
 bfd_coff_set_symbol_class (bfd *         abfd,
                           asymbol *     symbol,
-                          unsigned int  class)
+                          unsigned int  symbol_class)
 {
   coff_symbol_type * csym;
 
@@ -2292,12 +2519,12 @@ bfd_coff_set_symbol_class (bfd *         abfd,
       combined_entry_type * native;
       bfd_size_type amt = sizeof (* native);
 
-      native = bfd_zalloc (abfd, amt);
+      native = (combined_entry_type *) bfd_zalloc (abfd, amt);
       if (native == NULL)
        return FALSE;
 
       native->u.syment.n_type   = T_NULL;
-      native->u.syment.n_sclass = class;
+      native->u.syment.n_sclass = symbol_class;
 
       if (bfd_is_und_section (symbol->section))
        {
@@ -2326,7 +2553,7 @@ bfd_coff_set_symbol_class (bfd *         abfd,
       csym->native = native;
     }
   else
-    csym->native->u.syment.n_sclass = class;
+    csym->native->u.syment.n_sclass = symbol_class;
 
   return TRUE;
 }
@@ -2340,3 +2567,70 @@ bfd_coff_get_comdat_section (bfd *abfd, struct bfd_section *sec)
   else
     return NULL;
 }
+
+bfd_boolean
+_bfd_coff_section_already_linked (bfd *abfd,
+                                 asection *sec,
+                                 struct bfd_link_info *info)
+{
+  flagword flags;
+  const char *name, *key;
+  struct bfd_section_already_linked *l;
+  struct bfd_section_already_linked_hash_entry *already_linked_list;
+  struct coff_comdat_info *s_comdat;
+
+  flags = sec->flags;
+  if ((flags & SEC_LINK_ONCE) == 0)
+    return FALSE;
+
+  /* The COFF backend linker doesn't support group sections.  */
+  if ((flags & SEC_GROUP) != 0)
+    return FALSE;
+
+  name = bfd_get_section_name (abfd, sec);
+  s_comdat = bfd_coff_get_comdat_section (abfd, sec);
+
+  if (s_comdat != NULL)
+    key = s_comdat->name;
+  else
+    {
+      if (CONST_STRNEQ (name, ".gnu.linkonce.")
+         && (key = strchr (name + sizeof (".gnu.linkonce.") - 1, '.')) != NULL)
+       key++;
+      else
+       /* FIXME: gcc as of 2011-09 emits sections like .text$<key>,
+          .xdata$<key> and .pdata$<key> only the first of which has a
+          comdat key.  Should these all match the LTO IR key?  */
+       key = name;
+    }
+
+  already_linked_list = bfd_section_already_linked_table_lookup (key);
+
+  for (l = already_linked_list->entry; l != NULL; l = l->next)
+    {
+      struct coff_comdat_info *l_comdat;
+
+      l_comdat = bfd_coff_get_comdat_section (l->sec->owner, l->sec);
+
+      /* The section names must match, and both sections must be
+        comdat and have the same comdat name, or both sections must
+        be non-comdat.  LTO IR plugin sections are an exception.  They
+        are always named .gnu.linkonce.t.<key> (<key> is some string)
+        and match any comdat section with comdat name of <key>, and
+        any linkonce section with the same suffix, ie.
+        .gnu.linkonce.*.<key>.  */
+      if (((s_comdat != NULL) == (l_comdat != NULL)
+          && strcmp (name, l->sec->name) == 0)
+         || (l->sec->owner->flags & BFD_PLUGIN) != 0)
+       {
+         /* The section has already been linked.  See if we should
+            issue a warning.  */
+         return _bfd_handle_already_linked (sec, l, info);
+       }
+    }
+
+  /* This is the first section with this name.  Record it.  */
+  if (!bfd_section_already_linked_table_insert (already_linked_list, sec))
+    info->callbacks->einfo (_("%F%P: already_linked_table: %E\n"));
+  return FALSE;
+}
This page took 0.047308 seconds and 4 git commands to generate.