1999-09-06 Donn Terry <donn@interix.com>
[deliverable/binutils-gdb.git] / bfd / coffgen.c
index 8724715116fb489fba3b45ae45d4bb3a4e06487e..53aaf4fbc510f956fe877ac93e17e8b77f82db81 100644 (file)
@@ -1,5 +1,6 @@
 /* Support for the generic parts of COFF, for BFD.
 /* Support for the generic parts of COFF, for BFD.
-   Copyright 1990, 91, 92, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
+   Copyright 1990, 91, 92, 93, 94, 95, 96, 97, 98, 1999
+   Free Software Foundation, Inc.
    Written by Cygnus Support.
 
 This file is part of BFD, the Binary File Descriptor library.
    Written by Cygnus Support.
 
 This file is part of BFD, the Binary File Descriptor library.
@@ -283,18 +284,14 @@ coff_object_p (abfd)
       opthdr = bfd_alloc (abfd, aoutsz);
       if (opthdr == NULL)
        return 0;;
       opthdr = bfd_alloc (abfd, aoutsz);
       if (opthdr == NULL)
        return 0;;
-      if (bfd_read (opthdr, 1, aoutsz, abfd) != aoutsz)
+      if (bfd_read (opthdr, 1, internal_f.f_opthdr, abfd)
+         != internal_f.f_opthdr)
        {
          return 0;
        }
        {
          return 0;
        }
-      bfd_coff_swap_aouthdr_in (abfd, opthdr, (PTR) & internal_a);
+      bfd_coff_swap_aouthdr_in (abfd, opthdr, (PTR) &internal_a);
     }
 
     }
 
-  /* Seek past the opt hdr stuff */
-  if (bfd_seek (abfd, (file_ptr) (internal_f.f_opthdr + filhsz), SEEK_SET)
-      != 0)
-    return NULL;
-
   return coff_real_object_p (abfd, nscns, &internal_f,
                             (internal_f.f_opthdr != 0
                              ? &internal_a
   return coff_real_object_p (abfd, nscns, &internal_f,
                             (internal_f.f_opthdr != 0
                              ? &internal_a
@@ -562,7 +559,7 @@ coff_count_linenumbers (abfd)
 /*ARGSUSED*/
 coff_symbol_type *
 coff_symbol_from (ignore_abfd, symbol)
 /*ARGSUSED*/
 coff_symbol_type *
 coff_symbol_from (ignore_abfd, symbol)
-     bfd *ignore_abfd;
+     bfd *ignore_abfd ATTRIBUTE_UNUSED;
      asymbol *symbol;
 {
   if (bfd_asymbol_flavour (symbol) != bfd_target_coff_flavour)
      asymbol *symbol;
 {
   if (bfd_asymbol_flavour (symbol) != bfd_target_coff_flavour)
@@ -597,6 +594,7 @@ fixup_symbol_value (abfd, coff_symbol_ptr, syment)
       syment->n_scnum = N_UNDEF;
       syment->n_value = 0;
     }
       syment->n_scnum = N_UNDEF;
       syment->n_value = 0;
     }
+  /* FIXME: Do we need to handle the absolute section here?  */
   else
     {
       if (coff_symbol_ptr->symbol.section)
   else
     {
       if (coff_symbol_ptr->symbol.section)
@@ -661,16 +659,18 @@ coff_renumber_symbols (bfd_ptr, first_undef)
       if ((symbol_ptr_ptr[i]->flags & BSF_NOT_AT_END) != 0
          || (!bfd_is_und_section (symbol_ptr_ptr[i]->section)
              && !bfd_is_com_section (symbol_ptr_ptr[i]->section)
       if ((symbol_ptr_ptr[i]->flags & BSF_NOT_AT_END) != 0
          || (!bfd_is_und_section (symbol_ptr_ptr[i]->section)
              && !bfd_is_com_section (symbol_ptr_ptr[i]->section)
-             && ((symbol_ptr_ptr[i]->flags & (BSF_GLOBAL | BSF_FUNCTION))
-                 != BSF_GLOBAL)))
+             && ((symbol_ptr_ptr[i]->flags & BSF_FUNCTION) != 0
+                 || ((symbol_ptr_ptr[i]->flags & (BSF_GLOBAL | BSF_WEAK))
+                     == 0))))
        *newsyms++ = symbol_ptr_ptr[i];
 
     for (i = 0; i < symbol_count; i++)
       if ((symbol_ptr_ptr[i]->flags & BSF_NOT_AT_END) == 0
          && !bfd_is_und_section (symbol_ptr_ptr[i]->section)
          && (bfd_is_com_section (symbol_ptr_ptr[i]->section)
        *newsyms++ = symbol_ptr_ptr[i];
 
     for (i = 0; i < symbol_count; i++)
       if ((symbol_ptr_ptr[i]->flags & BSF_NOT_AT_END) == 0
          && !bfd_is_und_section (symbol_ptr_ptr[i]->section)
          && (bfd_is_com_section (symbol_ptr_ptr[i]->section)
-             || ((symbol_ptr_ptr[i]->flags & (BSF_GLOBAL | BSF_FUNCTION))
-                 == BSF_GLOBAL)))
+             || ((symbol_ptr_ptr[i]->flags & BSF_FUNCTION) == 0
+                 && ((symbol_ptr_ptr[i]->flags & (BSF_GLOBAL | BSF_WEAK))
+                     != 0))))
        *newsyms++ = symbol_ptr_ptr[i];
 
     *first_undef = newsyms - bfd_ptr->outsymbols;
        *newsyms++ = symbol_ptr_ptr[i];
 
     *first_undef = newsyms - bfd_ptr->outsymbols;
@@ -1035,6 +1035,8 @@ coff_write_alien_symbol (abfd, symbol, written, string_size_p,
   native->u.syment.n_type = 0;
   if (symbol->flags & BSF_LOCAL)
     native->u.syment.n_sclass = C_STAT;
   native->u.syment.n_type = 0;
   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;
   else
     native->u.syment.n_sclass = C_EXT;
   native->u.syment.n_numaux = 0;
@@ -1350,7 +1352,7 @@ coff_write_linenumbers (abfd)
 /*ARGSUSED */
 alent *
 coff_get_lineno (ignore_abfd, symbol)
 /*ARGSUSED */
 alent *
 coff_get_lineno (ignore_abfd, symbol)
-     bfd *ignore_abfd;
+     bfd *ignore_abfd ATTRIBUTE_UNUSED;
      asymbol *symbol;
 {
   return coffsymbol (symbol)->lineno;
      asymbol *symbol;
 {
   return coffsymbol (symbol)->lineno;
@@ -1420,8 +1422,8 @@ coff_pointerize_aux (abfd, table_base, symbol, indaux, auxent)
      unsigned int indaux;
      combined_entry_type *auxent;
 {
      unsigned int indaux;
      combined_entry_type *auxent;
 {
-  int type = symbol->u.syment.n_type;
-  int class = symbol->u.syment.n_sclass;
+  unsigned int type = symbol->u.syment.n_type;
+  unsigned int class = symbol->u.syment.n_sclass;
 
   if (coff_backend_info (abfd)->_bfd_coff_pointerize_aux_hook)
     {
 
   if (coff_backend_info (abfd)->_bfd_coff_pointerize_aux_hook)
     {
@@ -1603,7 +1605,7 @@ _bfd_coff_read_string_table (abfd)
   if (strsize < STRING_SIZE_SIZE)
     {
       (*_bfd_error_handler)
   if (strsize < STRING_SIZE_SIZE)
     {
       (*_bfd_error_handler)
-       ("%s: bad string table size %lu", bfd_get_filename (abfd),
+       (_("%s: bad string table size %lu"), bfd_get_filename (abfd),
         (unsigned long) strsize);
       bfd_set_error (bfd_error_bad_value);
       return NULL;
         (unsigned long) strsize);
       bfd_set_error (bfd_error_bad_value);
       return NULL;
@@ -1745,10 +1747,26 @@ coff_get_normalized_symtab (abfd)
            }
          else
            {
            }
          else
            {
-             /* ordinary short filename, put into memory anyway */
-             internal_ptr->u.syment._n._n_n._n_offset = (long)
-               copy_name (abfd, (internal_ptr + 1)->u.auxent.x_file.x_fname,
-                          FILNMLEN);
+             /* Ordinary short filename, put into memory anyway.  The
+                 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 =
+                   ((long)
+                    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)
+                    copy_name (abfd,
+                               (internal_ptr + 1)->u.auxent.x_file.x_fname,
+                               FILNMLEN));
+               }
            }
        }
       else
            }
        }
       else
@@ -1846,8 +1864,8 @@ coff_make_empty_symbol (abfd)
 asymbol *
 coff_bfd_make_debug_symbol (abfd, ptr, sz)
      bfd *abfd;
 asymbol *
 coff_bfd_make_debug_symbol (abfd, ptr, sz)
      bfd *abfd;
-     PTR ptr;
-     unsigned long sz;
+     PTR ptr ATTRIBUTE_UNUSED;
+     unsigned long sz ATTRIBUTE_UNUSED;
 {
   coff_symbol_type *new = (coff_symbol_type *) bfd_alloc (abfd, sizeof (coff_symbol_type));
   if (new == NULL)
 {
   coff_symbol_type *new = (coff_symbol_type *) bfd_alloc (abfd, sizeof (coff_symbol_type));
   if (new == NULL)
@@ -2094,10 +2112,10 @@ coff_print_symbol (abfd, filep, symbol, how)
 
 boolean
 _bfd_coff_is_local_label_name (abfd, name)
 
 boolean
 _bfd_coff_is_local_label_name (abfd, name)
-     bfd *abfd;
+     bfd *abfd ATTRIBUTE_UNUSED;
      const char *name;
 {
      const char *name;
 {
-  return ((name[0] == '.' && name[1] == 'L') ? true : false);
+  return name[0] == '.' && name[1] == 'L';
 }
 
 /* Provided a BFD, a section and an offset into the section, calculate
 }
 
 /* Provided a BFD, a section and an offset into the section, calculate
@@ -2162,9 +2180,11 @@ coff_find_nearest_line (abfd, section, symbols, offset, filename_ptr,
 
   if (p < pend)
     {
 
   if (p < pend)
     {
+      bfd_vma sec_vma;
       bfd_vma maxdiff;
 
       /* Look through the C_FILE symbols to find the best one.  */
       bfd_vma maxdiff;
 
       /* Look through the C_FILE symbols to find the best one.  */
+      sec_vma = bfd_get_section_vma (abfd, section);
       *filename_ptr = (char *) p->u.syment._n._n_n._n_offset;
       maxdiff = (bfd_vma) 0 - (bfd_vma) 1;
       while (1)
       *filename_ptr = (char *) p->u.syment._n._n_n._n_offset;
       maxdiff = (bfd_vma) 0 - (bfd_vma) 1;
       while (1)
@@ -2187,12 +2207,14 @@ coff_find_nearest_line (abfd, section, symbols, offset, filename_ptr,
                }
            }
 
                }
            }
 
+         /* We use <= MAXDIFF here so that if we get a zero length
+             file, we actually use the next file entry.  */
          if (p2 < pend
          if (p2 < pend
-             && offset >= (bfd_vma) p2->u.syment.n_value
-             && offset - (bfd_vma) p2->u.syment.n_value < maxdiff)
+             && offset + sec_vma >= (bfd_vma) p2->u.syment.n_value
+             && offset + sec_vma - (bfd_vma) p2->u.syment.n_value <= maxdiff)
            {
              *filename_ptr = (char *) p->u.syment._n._n_n._n_offset;
            {
              *filename_ptr = (char *) p->u.syment._n._n_n._n_offset;
-             maxdiff = offset - p2->u.syment.n_value;
+             maxdiff = offset + sec_vma - p2->u.syment.n_value;
            }
 
          /* Avoid endless loops on erroneous files by ensuring that
            }
 
          /* Avoid endless loops on erroneous files by ensuring that
@@ -2226,6 +2248,8 @@ coff_find_nearest_line (abfd, section, symbols, offset, filename_ptr,
 
   if (section->lineno != NULL)
     {
 
   if (section->lineno != NULL)
     {
+      bfd_vma last_value = 0;
+
       l = &section->lineno[i];
 
       for (; i < section->lineno_count; i++)
       l = &section->lineno[i];
 
       for (; i < section->lineno_count; i++)
@@ -2237,6 +2261,7 @@ coff_find_nearest_line (abfd, section, symbols, offset, filename_ptr,
              if (coff->symbol.value > offset)
                break;
              *functionname_ptr = coff->symbol.name;
              if (coff->symbol.value > offset)
                break;
              *functionname_ptr = coff->symbol.name;
+             last_value = coff->symbol.value;
              if (coff->native)
                {
                  combined_entry_type *s = coff->native;
              if (coff->native)
                {
                  combined_entry_type *s = coff->native;
@@ -2259,12 +2284,26 @@ coff_find_nearest_line (abfd, section, symbols, offset, filename_ptr,
            }
          else
            {
            }
          else
            {
-             if (l->u.offset + bfd_get_section_vma (abfd, section) > offset)
+             if (l->u.offset > offset)
                break;
              *line_ptr = l->line_number + line_base - 1;
            }
          l++;
        }
                break;
              *line_ptr = l->line_number + line_base - 1;
            }
          l++;
        }
+
+      /* If we fell off the end of the loop, then assume that this
+        symbol has no line number info.  Otherwise, symbols with no
+        line number info get reported with the line number of the
+        last line of the last symbol which does have line number
+        info.  We use 0x100 as a slop to account for cases where the
+        last line has executable code.  */
+      if (i >= section->lineno_count
+         && last_value != 0
+         && offset - last_value > 0x100)
+       {
+         *functionname_ptr = NULL;
+         *line_ptr = 0;
+       }
     }
 
   /* Cache the results for the next call.  */
     }
 
   /* Cache the results for the next call.  */
@@ -2305,3 +2344,71 @@ coff_sizeof_headers (abfd, reloc)
   size += abfd->section_count * bfd_coff_scnhsz (abfd);
   return size;
 }
   size += abfd->section_count * bfd_coff_scnhsz (abfd);
   return size;
 }
+
+/* Change the class of a coff symbol held by BFD.  */
+boolean
+bfd_coff_set_symbol_class (abfd, symbol, class)
+     bfd *         abfd;
+     asymbol *     symbol;
+     unsigned int  class;
+{
+  coff_symbol_type * csym;
+
+  csym = coff_symbol_from (abfd, symbol);
+  if (csym == NULL)
+    {
+      bfd_set_error (bfd_error_invalid_operation);
+      return false;
+    }
+  else if (csym->native == NULL)
+    {
+      /* This is an alien symbol which no native coff backend data.
+        We cheat here by creating a fake native entry for it and
+        then filling in the class.  This code is based on that in
+        coff_write_alien_symbol().  */
+      
+      combined_entry_type * native;
+
+      native = (combined_entry_type *) bfd_alloc (abfd, sizeof (* native));
+      if (native == NULL)
+       return false;
+
+      memset (native, 0, sizeof (* native));
+      
+      native->u.syment.n_type   = T_NULL;
+      native->u.syment.n_sclass = class;
+      
+      if (bfd_is_und_section (symbol->section))
+       {
+         native->u.syment.n_scnum = N_UNDEF;
+         native->u.syment.n_value = symbol->value;
+       }
+      else if (bfd_is_com_section (symbol->section))
+       {
+         native->u.syment.n_scnum = N_UNDEF;
+         native->u.syment.n_value = symbol->value;
+       }
+      else
+       {
+         native->u.syment.n_scnum =
+           symbol->section->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;
+         
+         /* Copy the any flags from the the file header into the symbol.
+            FIXME: Why?  */
+         native->u.syment.n_flags = bfd_asymbol_bfd (& csym->symbol)->flags;
+       }
+      
+      csym->native = native;
+    }
+  else
+    {
+      csym->native->u.syment.n_sclass = class;
+    }
+  
+  return true;
+}
+
This page took 0.026504 seconds and 4 git commands to generate.