* go32-nat.c (go32_stop): Delete.
[deliverable/binutils-gdb.git] / bfd / coffgen.c
index c541e6a590eb2d9abb7e367edd568192ff95c9d5..8781557e99b801ab0bf2f94638835dc9c80296ac 100644 (file)
@@ -1,6 +1,6 @@
 /* Support for the generic parts of COFF, for BFD.
    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
 /* 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
+   2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
    Free Software Foundation, Inc.
    Written by Cygnus Support.
 
    Free Software Foundation, Inc.
    Written by Cygnus Support.
 
@@ -8,7 +8,7 @@
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
@@ -18,7 +18,8 @@
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
 
 /* Most of this hacked by  Steve Chamberlain, sac@cygnus.com.
    Split out of coffcode.h by Ian Taylor, ian@cygnus.com.  */
 
 /* Most of this hacked by  Steve Chamberlain, sac@cygnus.com.
    Split out of coffcode.h by Ian Taylor, ian@cygnus.com.  */
@@ -37,8 +38,8 @@
    Those functions may not use any COFF specific information, such as
    coff_data (abfd).  */
 
    Those functions may not use any COFF specific information, such as
    coff_data (abfd).  */
 
-#include "bfd.h"
 #include "sysdep.h"
 #include "sysdep.h"
+#include "bfd.h"
 #include "libbfd.h"
 #include "coff/internal.h"
 #include "libcoff.h"
 #include "libbfd.h"
 #include "coff/internal.h"
 #include "libcoff.h"
@@ -58,8 +59,13 @@ make_a_section_from_file (bfd *abfd,
 
   name = NULL;
 
 
   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];
       && hdr->s_name[0] == '/')
     {
       char buf[SCNNMLEN];
@@ -67,6 +73,11 @@ make_a_section_from_file (bfd *abfd,
       char *p;
       const char *strings;
 
       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);
       memcpy (buf, hdr->s_name + 1, SCNNMLEN - 1);
       buf[SCNNMLEN - 1] = '\0';
       strindex = strtol (buf, &p, 10);
@@ -408,6 +419,9 @@ _bfd_coff_read_internal_relocs (bfd *abfd,
   struct internal_reloc *irel;
   bfd_size_type amt;
 
   struct internal_reloc *irel;
   bfd_size_type amt;
 
+  if (sec->reloc_count == 0)
+    return internal_relocs;    /* Nothing to do.  */
+
   if (coff_section_data (abfd, sec) != NULL
       && coff_section_data (abfd, sec)->relocs != NULL)
     {
   if (coff_section_data (abfd, sec) != NULL
       && coff_section_data (abfd, sec)->relocs != NULL)
     {
@@ -424,7 +438,7 @@ _bfd_coff_read_internal_relocs (bfd *abfd,
   if (external_relocs == NULL)
     {
       free_external = bfd_malloc (amt);
   if (external_relocs == NULL)
     {
       free_external = bfd_malloc (amt);
-      if (free_external == NULL && sec->reloc_count > 0)
+      if (free_external == NULL)
        goto error_return;
       external_relocs = free_external;
     }
        goto error_return;
       external_relocs = free_external;
     }
@@ -438,7 +452,7 @@ _bfd_coff_read_internal_relocs (bfd *abfd,
       amt = sec->reloc_count;
       amt *= sizeof (struct internal_reloc);
       free_internal = bfd_malloc (amt);
       amt = sec->reloc_count;
       amt *= sizeof (struct internal_reloc);
       free_internal = bfd_malloc (amt);
-      if (free_internal == NULL && sec->reloc_count > 0)
+      if (free_internal == NULL)
        goto error_return;
       internal_relocs = free_internal;
     }
        goto error_return;
       internal_relocs = free_internal;
     }
@@ -561,7 +575,8 @@ fixup_symbol_value (bfd *abfd,
                    struct internal_syment *syment)
 {
   /* Normalize the symbol flags.  */
                    struct internal_syment *syment)
 {
   /* Normalize the symbol flags.  */
-  if (bfd_is_com_section (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.  */
       syment->n_scnum = N_UNDEF;
     {
       /* A common symbol is undefined with a value.  */
       syment->n_scnum = N_UNDEF;
@@ -725,8 +740,8 @@ coff_mangle_symbols (bfd *bfd_ptr)
            {
              /* FIXME: We should use a union here.  */
              s->u.syment.n_value =
            {
              /* FIXME: We should use a union here.  */
              s->u.syment.n_value =
-               (bfd_vma)((combined_entry_type *)
-                         ((unsigned long) s->u.syment.n_value))->offset;
+               (bfd_hostptr_t) ((combined_entry_type *)
+                         ((bfd_hostptr_t) s->u.syment.n_value))->offset;
              s->fix_value = 0;
            }
          if (s->fix_line)
              s->fix_value = 0;
            }
          if (s->fix_line)
@@ -1077,6 +1092,11 @@ coff_write_native_symbol (bfd *abfd,
                            debug_string_size_p);
 }
 
                            debug_string_size_p);
 }
 
+static void
+null_error_handler (const char * fmt ATTRIBUTE_UNUSED, ...)
+{
+}
+
 /* Write out the COFF symbols.  */
 
 bfd_boolean
 /* Write out the COFF symbols.  */
 
 bfd_boolean
@@ -1133,6 +1153,42 @@ coff_write_symbols (bfd *abfd)
        }
       else
        {
        }
       else
        {
+         if (coff_backend_info (abfd)->_bfd_coff_classify_symbol != NULL)
+           {
+             bfd_error_handler_type current_error_handler;
+             enum coff_symbol_classification 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);
+             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 && class != COFF_SYMBOL_LOCAL)
+               *n_sclass = C_STAT;
+             else if (symbol->flags & BSF_GLOBAL
+                      && (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))
          if (!coff_write_native_symbol (abfd, c_symbol, &written,
                                         &string_size, &debug_string_section,
                                         &debug_string_size))
@@ -1443,9 +1499,11 @@ _bfd_coff_get_external_symbols (bfd *abfd)
   symesz = bfd_coff_symesz (abfd);
 
   size = obj_raw_syment_count (abfd) * symesz;
   symesz = bfd_coff_symesz (abfd);
 
   size = obj_raw_syment_count (abfd) * symesz;
+  if (size == 0)
+    return TRUE;
 
   syms = bfd_malloc (size);
 
   syms = bfd_malloc (size);
-  if (syms == NULL && size != 0)
+  if (syms == NULL)
     return FALSE;
 
   if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0
     return FALSE;
 
   if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0
@@ -1640,7 +1698,7 @@ coff_get_normalized_symtab (bfd *abfd)
                }
 
              internal_ptr->u.syment._n._n_n._n_offset =
                }
 
              internal_ptr->u.syment._n._n_n._n_offset =
-               ((long)
+               ((bfd_hostptr_t)
                 (string_table
                  + (internal_ptr + 1)->u.auxent.x_file.x_n.x_offset));
            }
                 (string_table
                  + (internal_ptr + 1)->u.auxent.x_file.x_n.x_offset));
            }
@@ -1652,13 +1710,13 @@ coff_get_normalized_symtab (bfd *abfd)
              if (internal_ptr->u.syment.n_numaux > 1
                  && coff_data (abfd)->pe)
                internal_ptr->u.syment._n._n_n._n_offset =
              if (internal_ptr->u.syment.n_numaux > 1
                  && coff_data (abfd)->pe)
                internal_ptr->u.syment._n._n_n._n_offset =
-                 ((long)
+                 ((bfd_hostptr_t)
                   copy_name (abfd,
                              (internal_ptr + 1)->u.auxent.x_file.x_fname,
                              internal_ptr->u.syment.n_numaux * symesz));
              else
                internal_ptr->u.syment._n._n_n._n_offset =
                   copy_name (abfd,
                              (internal_ptr + 1)->u.auxent.x_file.x_fname,
                              internal_ptr->u.syment.n_numaux * symesz));
              else
                internal_ptr->u.syment._n._n_n._n_offset =
-                 ((long)
+                 ((bfd_hostptr_t)
                   copy_name (abfd,
                              (internal_ptr + 1)->u.auxent.x_file.x_fname,
                              (size_t) bfd_coff_filnmlen (abfd)));
                   copy_name (abfd,
                              (internal_ptr + 1)->u.auxent.x_file.x_fname,
                              (size_t) bfd_coff_filnmlen (abfd)));
@@ -1682,11 +1740,11 @@ coff_get_normalized_symtab (bfd *abfd)
              if (newstring == NULL)
                return NULL;
              strncpy (newstring, internal_ptr->u.syment._n._n_name, i);
              if (newstring == NULL)
                return NULL;
              strncpy (newstring, internal_ptr->u.syment._n._n_name, i);
-             internal_ptr->u.syment._n._n_n._n_offset = (long int) newstring;
+             internal_ptr->u.syment._n._n_n._n_offset = (bfd_hostptr_t) newstring;
              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_zeroes = 0;
            }
          else if (internal_ptr->u.syment._n._n_n._n_offset == 0)
-           internal_ptr->u.syment._n._n_n._n_offset = (long int) "";
+           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
          else if (!bfd_coff_symname_in_debug (abfd, &internal_ptr->u.syment))
            {
              /* Long name already.  Point symbol at the string in the
@@ -1698,7 +1756,7 @@ coff_get_normalized_symtab (bfd *abfd)
                    return NULL;
                }
              internal_ptr->u.syment._n._n_n._n_offset =
                    return NULL;
                }
              internal_ptr->u.syment._n._n_n._n_offset =
-               ((long int)
+               ((bfd_hostptr_t)
                 (string_table
                  + internal_ptr->u.syment._n._n_n._n_offset));
            }
                 (string_table
                  + internal_ptr->u.syment._n._n_n._n_offset));
            }
@@ -1707,7 +1765,7 @@ coff_get_normalized_symtab (bfd *abfd)
              /* Long name in debug section.  Very similar.  */
              if (debug_section == NULL)
                debug_section = build_debug_section (abfd);
              /* 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 = (long int)
+             internal_ptr->u.syment._n._n_n._n_offset = (bfd_hostptr_t)
                (debug_section + internal_ptr->u.syment._n._n_n._n_offset);
            }
        }
                (debug_section + internal_ptr->u.syment._n._n_n._n_offset);
            }
        }
@@ -1784,7 +1842,7 @@ coff_get_symbol_info (bfd *abfd, asymbol *symbol, symbol_info *ret)
   if (coffsymbol (symbol)->native != NULL
       && coffsymbol (symbol)->native->fix_value)
     ret->value = coffsymbol (symbol)->native->u.syment.n_value -
   if (coffsymbol (symbol)->native != NULL
       && coffsymbol (symbol)->native->fix_value)
     ret->value = coffsymbol (symbol)->native->u.syment.n_value -
-      (unsigned long) obj_raw_syments (abfd);
+      (bfd_hostptr_t) obj_raw_syments (abfd);
 }
 
 /* Return the COFF syment for a symbol.  */
 }
 
 /* Return the COFF syment for a symbol.  */
@@ -1807,7 +1865,7 @@ bfd_coff_get_syment (bfd *abfd,
 
   if (csym->native->fix_value)
     psyment->n_value = psyment->n_value -
 
   if (csym->native->fix_value)
     psyment->n_value = psyment->n_value -
-      (unsigned long) obj_raw_syments (abfd);
+      (bfd_hostptr_t) obj_raw_syments (abfd);
 
   /* FIXME: We should handle fix_line here.  */
 
 
   /* FIXME: We should handle fix_line here.  */
 
@@ -1893,7 +1951,7 @@ coff_print_symbol (bfd *abfd,
          if (! combined->fix_value)
            val = (bfd_vma) combined->u.syment.n_value;
          else
          if (! combined->fix_value)
            val = (bfd_vma) combined->u.syment.n_value;
          else
-           val = combined->u.syment.n_value - (unsigned long) root;
+           val = combined->u.syment.n_value - (bfd_hostptr_t) root;
 
          fprintf (file, "(sec %2d)(fl 0x%02x)(ty %3x)(scl %3d) (nx %d) 0x",
                   combined->u.syment.n_scnum,
 
          fprintf (file, "(sec %2d)(fl 0x%02x)(ty %3x)(scl %3d) (nx %d) 0x",
                   combined->u.syment.n_scnum,
@@ -1901,7 +1959,16 @@ coff_print_symbol (bfd *abfd,
                   combined->u.syment.n_type,
                   combined->u.syment.n_sclass,
                   combined->u.syment.n_numaux);
                   combined->u.syment.n_type,
                   combined->u.syment.n_sclass,
                   combined->u.syment.n_numaux);
-         fprintf_vma (file, val);
+#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);
          fprintf (file, " %s", symbol->name);
 
          for (aux = 0; aux < combined->u.syment.n_numaux; aux++)
          fprintf (file, " %s", symbol->name);
 
          for (aux = 0; aux < combined->u.syment.n_numaux; aux++)
@@ -1930,7 +1997,7 @@ coff_print_symbol (bfd *abfd,
                    /* Probably a section symbol ?  */
                    {
                      fprintf (file, "AUX scnlen 0x%lx nreloc %d nlnno %d",
                    /* 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
                               auxp->u.auxent.x_scn.x_nreloc,
                               auxp->u.auxent.x_scn.x_nlinno);
                      if (auxp->u.auxent.x_scn.x_checksum != 0
@@ -1944,6 +2011,7 @@ coff_print_symbol (bfd *abfd,
                    }
                    /* Otherwise fall through.  */
                case C_EXT:
                    }
                    /* Otherwise fall through.  */
                case C_EXT:
+               case C_AIX_WEAKEXT:
                  if (ISFCN (combined->u.syment.n_type))
                    {
                      long next, llnos;
                  if (ISFCN (combined->u.syment.n_type))
                    {
                      long next, llnos;
@@ -1956,7 +2024,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",
                      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;
                    }
                               llnos, next);
                      break;
                    }
@@ -2128,7 +2197,7 @@ coff_find_nearest_line (bfd *abfd,
     }
 
   /* Now wander though the raw linenumbers of the section.  */
     }
 
   /* 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
      want is further down then we can prime the lookup loop.  */
   sec_data = coff_section_data (abfd, section);
   if (sec_data != NULL
@@ -2215,7 +2284,7 @@ coff_find_nearest_line (bfd *abfd,
   if (sec_data != NULL)
     {
       sec_data->offset = offset;
   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;
     }
       sec_data->function = *functionname_ptr;
       sec_data->line_base = line_base;
     }
@@ -2238,11 +2307,11 @@ coff_find_inliner_info (bfd *abfd,
 }
 
 int
 }
 
 int
-coff_sizeof_headers (bfd *abfd, bfd_boolean reloc)
+coff_sizeof_headers (bfd *abfd, struct bfd_link_info *info)
 {
   size_t size;
 
 {
   size_t size;
 
-  if (! reloc)
+  if (!info->relocatable)
     size = bfd_coff_filhsz (abfd) + bfd_coff_aoutsz (abfd);
   else
     size = bfd_coff_filhsz (abfd);
     size = bfd_coff_filhsz (abfd) + bfd_coff_aoutsz (abfd);
   else
     size = bfd_coff_filhsz (abfd);
This page took 0.031335 seconds and 4 git commands to generate.