* write.c (relax_frag): Make non-static.
[deliverable/binutils-gdb.git] / bfd / coffgen.c
index 2f3644785eb406ab83b2b472bab66aff632e7d38..76e9430312c48bd2f2a18d0f1c3946a8c17955d3 100644 (file)
@@ -1,5 +1,5 @@
 /* Support for the generic parts of COFF, for BFD.
-   Copyright 1990, 91, 92, 93, 94, 1995 Free Software Foundation, Inc.
+   Copyright 1990, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
    Written by Cygnus Support.
 
 This file is part of BFD, the Binary File Descriptor library.
@@ -73,10 +73,7 @@ make_a_section_from_file (abfd, hdr, target_index)
   /* Assorted wastage to null-terminate the name, thanks AT&T! */
   name = bfd_alloc (abfd, sizeof (hdr->s_name) + 1);
   if (name == NULL)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return false;
-    }
+    return false;
   strncpy (name, (char *) &hdr->s_name[0], sizeof (hdr->s_name));
   name[sizeof (hdr->s_name)] = 0;
 
@@ -84,10 +81,8 @@ make_a_section_from_file (abfd, hdr, target_index)
   if (return_section == NULL)
     return false;
 
-  /* s_paddr is presumed to be = to s_vaddr */
-
   return_section->vma = hdr->s_vaddr;
-  return_section->lma = return_section->vma;
+  return_section->lma = hdr->s_paddr;
   return_section->_raw_size = hdr->s_size;
   return_section->filepos = hdr->s_scnptr;
   return_section->rel_filepos = hdr->s_relptr;
@@ -166,10 +161,7 @@ coff_real_object_p (abfd, nscns, internal_f, internal_a)
   readsize = nscns * scnhsz;
   external_sections = (char *) bfd_alloc (abfd, readsize);
   if (!external_sections)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      goto fail;
-    }
+    goto fail;
 
   if (bfd_read ((PTR) external_sections, 1, readsize, abfd) != readsize)
     goto fail;
@@ -329,6 +321,138 @@ coff_get_symtab (abfd, alocation)
   return bfd_get_symcount (abfd);
 }
 
+/* Get the name of a symbol.  The caller must pass in a buffer of size
+   >= SYMNMLEN + 1.  */
+
+const char *
+_bfd_coff_internal_syment_name (abfd, sym, buf)
+     bfd *abfd;
+     const struct internal_syment *sym;
+     char *buf;
+{
+  /* FIXME: It's not clear this will work correctly if sizeof
+     (_n_zeroes) != 4.  */
+  if (sym->_n._n_n._n_zeroes != 0
+      || sym->_n._n_n._n_offset == 0)
+    {
+      memcpy (buf, sym->_n._n_name, SYMNMLEN);
+      buf[SYMNMLEN] = '\0';
+      return buf;
+    }
+  else
+    {
+      const char *strings;
+
+      BFD_ASSERT (sym->_n._n_n._n_offset >= STRING_SIZE_SIZE);
+      strings = obj_coff_strings (abfd);
+      if (strings == NULL)
+       {
+         strings = _bfd_coff_read_string_table (abfd);
+         if (strings == NULL)
+           return NULL;
+       }
+      return strings + sym->_n._n_n._n_offset;
+    }
+}
+
+/* Read in and swap the relocs.  This returns a buffer holding the
+   relocs for section SEC in file ABFD.  If CACHE is true and
+   INTERNAL_RELOCS is NULL, the relocs read in will be saved in case
+   the function is called again.  If EXTERNAL_RELOCS is not NULL, it
+   is a buffer large enough to hold the unswapped relocs.  If
+   INTERNAL_RELOCS is not NULL, it is a buffer large enough to hold
+   the swapped relocs.  If REQUIRE_INTERNAL is true, then the return
+   value must be INTERNAL_RELOCS.  The function returns NULL on error.  */
+
+struct internal_reloc *
+_bfd_coff_read_internal_relocs (abfd, sec, cache, external_relocs,
+                               require_internal, internal_relocs)
+     bfd *abfd;
+     asection *sec;
+     boolean cache;
+     bfd_byte *external_relocs;
+     boolean require_internal;
+     struct internal_reloc *internal_relocs;
+{
+  bfd_size_type relsz;
+  bfd_byte *free_external = NULL;
+  struct internal_reloc *free_internal = NULL;
+  bfd_byte *erel;
+  bfd_byte *erel_end;
+  struct internal_reloc *irel;
+
+  if (coff_section_data (abfd, sec) != NULL
+      && coff_section_data (abfd, sec)->relocs != NULL)
+    {
+      if (! require_internal)
+       return coff_section_data (abfd, sec)->relocs;
+      memcpy (internal_relocs, coff_section_data (abfd, sec)->relocs,
+             sec->reloc_count * sizeof (struct internal_reloc));
+      return internal_relocs;
+    }
+
+  relsz = bfd_coff_relsz (abfd);
+
+  if (external_relocs == NULL)
+    {
+      free_external = (bfd_byte *) bfd_malloc (sec->reloc_count * relsz);
+      if (free_external == NULL && sec->reloc_count > 0)
+       goto error_return;
+      external_relocs = free_external;
+    }
+
+  if (bfd_seek (abfd, sec->rel_filepos, SEEK_SET) != 0
+      || (bfd_read (external_relocs, relsz, sec->reloc_count, abfd)
+         != relsz * sec->reloc_count))
+    goto error_return;
+
+  if (internal_relocs == NULL)
+    {
+      free_internal = ((struct internal_reloc *)
+                      bfd_malloc (sec->reloc_count
+                                  * sizeof (struct internal_reloc)));
+      if (free_internal == NULL && sec->reloc_count > 0)
+       goto error_return;
+      internal_relocs = free_internal;
+    }
+
+  /* Swap in the relocs.  */
+  erel = external_relocs;
+  erel_end = erel + relsz * sec->reloc_count;
+  irel = internal_relocs;
+  for (; erel < erel_end; erel += relsz, irel++)
+    bfd_coff_swap_reloc_in (abfd, (PTR) erel, (PTR) irel);
+
+  if (free_external != NULL)
+    {
+      free (free_external);
+      free_external = NULL;
+    }
+
+  if (cache && free_internal != NULL)
+    {
+      if (coff_section_data (abfd, sec) == NULL)
+       {
+         sec->used_by_bfd =
+           (PTR) bfd_zalloc (abfd,
+                             sizeof (struct coff_section_tdata));
+         if (sec->used_by_bfd == NULL)
+           goto error_return;
+         coff_section_data (abfd, sec)->contents = NULL;
+       }
+      coff_section_data (abfd, sec)->relocs = free_internal;
+    }
+
+  return internal_relocs;
+
+ error_return:
+  if (free_external != NULL)
+    free (free_external);
+  if (free_internal != NULL)
+    free (free_internal);
+  return NULL;
+}
+
 /* Set lineno_count for the output sections of a COFF file.  */
 
 int
@@ -361,7 +485,11 @@ coff_count_linenumbers (abfd)
        {
          coff_symbol_type *q = coffsymbol (q_maybe);
 
-         if (q->lineno != NULL)
+         /* The AIX 4.1 compiler can sometimes generate line numbers
+             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.  */
@@ -481,24 +609,23 @@ coff_renumber_symbols (bfd_ptr, first_undef)
                                                sizeof (asymbol *)
                                                * (symbol_count + 1));
     if (!newsyms)
-      {
-       bfd_set_error (bfd_error_no_memory);
-       return false;
-      }
+      return false;
     bfd_ptr->outsymbols = newsyms;
     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)))
        *newsyms++ = symbol_ptr_ptr[i];
 
     for (i = 0; i < symbol_count; i++)
       if (!bfd_is_und_section (symbol_ptr_ptr[i]->section)
-         && ((symbol_ptr_ptr[i]->flags & (BSF_GLOBAL
-                                          | BSF_NOT_AT_END
-                                          | BSF_FUNCTION))
-             == BSF_GLOBAL))
+         && (bfd_is_com_section (symbol_ptr_ptr[i]->section)
+             || ((symbol_ptr_ptr[i]->flags & (BSF_GLOBAL
+                                              | BSF_NOT_AT_END
+                                              | BSF_FUNCTION))
+                 == BSF_GLOBAL)))
        *newsyms++ = symbol_ptr_ptr[i];
 
     *first_undef = newsyms - bfd_ptr->outsymbols;
@@ -576,6 +703,18 @@ coff_mangle_symbols (bfd_ptr)
                ((combined_entry_type *) s->u.syment.n_value)->offset;
              s->fix_value = 0;
            }
+         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.  */
+             s->u.syment.n_value =
+               (coff_symbol_ptr->symbol.section->output_section->line_filepos
+                + s->u.syment.n_value * bfd_coff_linesz (bfd_ptr));
+             coff_symbol_ptr->symbol.section =
+               coff_section_from_bfd_index (bfd_ptr, N_DEBUG);
+             BFD_ASSERT (coff_symbol_ptr->symbol.flags & BSF_DEBUGGING);
+           }
          for (i = 0; i < s->u.syment.n_numaux; i++)
            {
              combined_entry_type *a = s + i + 1;
@@ -729,7 +868,8 @@ coff_write_symbol (abfd, symbol, native, written, string_size_p,
   if (native->u.syment.n_sclass == C_FILE)
     symbol->flags |= BSF_DEBUGGING;
 
-  if (symbol->flags & BSF_DEBUGGING)
+  if (symbol->flags & BSF_DEBUGGING
+      && bfd_is_abs_section (symbol->section))
     {
       native->u.syment.n_scnum = N_DEBUG;
     }
@@ -753,10 +893,7 @@ coff_write_symbol (abfd, symbol, native, written, string_size_p,
   symesz = bfd_coff_symesz (abfd);
   buf = bfd_alloc (abfd, symesz);
   if (!buf)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return false;
-    }
+    return false;
   bfd_coff_swap_sym_out (abfd, &native->u.syment, buf);
   if (bfd_write (buf, 1, symesz, abfd) != symesz)
     return false;
@@ -770,10 +907,7 @@ coff_write_symbol (abfd, symbol, native, written, string_size_p,
       auxesz = bfd_coff_auxesz (abfd);
       buf = bfd_alloc (abfd, auxesz);
       if (!buf)
-       {
-         bfd_set_error (bfd_error_no_memory);
-         return false;
-       }
+       return false;
       for (j = 0; j < native->u.syment.n_numaux; j++)
        {
          bfd_coff_swap_aux_out (abfd,
@@ -881,7 +1015,7 @@ coff_write_native_symbol (abfd, symbol, written, string_size_p,
   /* 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
      point to the right place in the lineno table.  */
-  if (lineno && !symbol->done_lineno)
+  if (lineno && !symbol->done_lineno && symbol->symbol.section->owner != NULL)
     {
       unsigned int count = 0;
       lineno[count].u.offset = *written;
@@ -1082,10 +1216,7 @@ coff_write_linenumbers (abfd)
   linesz = bfd_coff_linesz (abfd);
   buff = bfd_alloc (abfd, linesz);
   if (!buff)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return false;
-    }
+    return false;
   for (s = abfd->sections; s != (asection *) NULL; s = s->next)
     {
       if (s->lineno_count)
@@ -1141,6 +1272,11 @@ coff_get_lineno (ignore_abfd, symbol)
   return coffsymbol (symbol)->lineno;
 }
 
+#if 0
+
+/* This is only called from coff_add_missing_symbols, which has been
+   disabled.  */
+
 asymbol *
 coff_section_symbol (abfd, name)
      bfd *abfd;
@@ -1187,6 +1323,8 @@ coff_section_symbol (abfd, name)
   return sym;
 }
 
+#endif /* 0 */
+
 /* This function transforms the offsets into the symbol table into
    pointers to syments.  */
 
@@ -1217,7 +1355,7 @@ coff_pointerize_aux (abfd, table_base, symbol, indaux, auxent)
   /* 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)
+  if ((ISFCN (type) || ISTAG (class) || class == C_BLOCK || class == 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 =
@@ -1256,10 +1394,7 @@ build_debug_section (abfd)
   debug_section = (PTR) bfd_alloc (abfd,
                                   bfd_get_section_size_before_reloc (sect));
   if (debug_section == NULL)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return 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.
@@ -1297,10 +1432,7 @@ copy_name (abfd, name, maxlen)
     }
 
   if ((newname = (PTR) bfd_alloc (abfd, len + 1)) == NULL)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return (NULL);
-    }
+    return (NULL);
   strncpy (newname, name, len);
   newname[len] = '\0';
   return newname;
@@ -1323,12 +1455,9 @@ _bfd_coff_get_external_symbols (abfd)
 
   size = obj_raw_syment_count (abfd) * symesz;
 
-  syms = malloc (size);
+  syms = (PTR) bfd_malloc (size);
   if (syms == NULL && size != 0)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return false;
-    }
+    return false;
 
   if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0
       || bfd_read (syms, size, 1, abfd) != size)
@@ -1381,13 +1510,19 @@ _bfd_coff_read_string_table (abfd)
 #endif
     }
 
-  strings = malloc (strsize);
-  if (strings == NULL)
+  if (strsize < STRING_SIZE_SIZE)
     {
-      bfd_set_error (bfd_error_no_memory);
+      (*_bfd_error_handler)
+       ("%s: bad string table size %lu", bfd_get_filename (abfd),
+        (unsigned long) strsize);
+      bfd_set_error (bfd_error_bad_value);
       return NULL;
     }
 
+  strings = (char *) bfd_malloc (strsize);
+  if (strings == NULL)
+    return NULL;
+
   if (bfd_read (strings + STRING_SIZE_SIZE,
                strsize - STRING_SIZE_SIZE, 1, abfd)
       != strsize - STRING_SIZE_SIZE)
@@ -1446,12 +1581,9 @@ coff_get_normalized_symtab (abfd)
     return obj_raw_syments (abfd);
 
   size = obj_raw_syment_count (abfd) * sizeof (combined_entry_type);
-  internal = (combined_entry_type *) bfd_alloc (abfd, size);
+  internal = (combined_entry_type *) bfd_zalloc (abfd, size);
   if (internal == NULL && size != 0)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return NULL;
-    }
+    return NULL;
   internal_end = internal + obj_raw_syment_count (abfd);
 
   if (! _bfd_coff_get_external_symbols (abfd))
@@ -1475,10 +1607,6 @@ coff_get_normalized_symtab (abfd)
       unsigned int i;
       bfd_coff_swap_sym_in (abfd, (PTR) raw_src,
                            (PTR) & internal_ptr->u.syment);
-      internal_ptr->fix_value = 0;
-      internal_ptr->fix_tag = 0;
-      internal_ptr->fix_end = 0;
-      internal_ptr->fix_scnlen = 0;
       symbol_ptr = internal_ptr;
 
       for (i = 0;
@@ -1487,11 +1615,6 @@ coff_get_normalized_symtab (abfd)
        {
          internal_ptr++;
          raw_src += symesz;
-
-         internal_ptr->fix_value = 0;
-         internal_ptr->fix_tag = 0;
-         internal_ptr->fix_end = 0;
-         internal_ptr->fix_scnlen = 0;
          bfd_coff_swap_aux_in (abfd, (PTR) raw_src,
                                symbol_ptr->u.syment.n_type,
                                symbol_ptr->u.syment.n_sclass,
@@ -1557,10 +1680,7 @@ coff_get_normalized_symtab (abfd)
                }               /* possible lengths of this string. */
 
              if ((newstring = (PTR) bfd_alloc (abfd, ++i)) == NULL)
-               {
-                 bfd_set_error (bfd_error_no_memory);
-                 return (NULL);
-               }               /* on error */
+               return (NULL);
              memset (newstring, 0, i);
              strncpy (newstring, internal_ptr->u.syment._n._n_name, i - 1);
              internal_ptr->u.syment._n._n_n._n_offset = (long int) newstring;
@@ -1621,10 +1741,7 @@ coff_make_empty_symbol (abfd)
 {
   coff_symbol_type *new = (coff_symbol_type *) bfd_alloc (abfd, sizeof (coff_symbol_type));
   if (new == NULL)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return (NULL);
-    }                          /* on error */
+    return (NULL);
   memset (new, 0, sizeof *new);
   new->symbol.section = 0;
   new->native = 0;
@@ -1644,17 +1761,12 @@ coff_bfd_make_debug_symbol (abfd, ptr, sz)
 {
   coff_symbol_type *new = (coff_symbol_type *) bfd_alloc (abfd, sizeof (coff_symbol_type));
   if (new == NULL)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return (NULL);
-    }                          /* on error */
-  /* @@ This shouldn't be using a constant multiplier.  */
+    return (NULL);
+  /* @@ The 10 is a guess at a plausible maximum number of aux entries
+     (but shouldn't be a constant).  */
   new->native = (combined_entry_type *) bfd_zalloc (abfd, sizeof (combined_entry_type) * 10);
   if (!new->native)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return (NULL);
-    }                          /* on error */
+    return (NULL);
   new->symbol.section = bfd_abs_section_ptr;
   new->symbol.flags = BSF_DEBUGGING;
   new->lineno = (alent *) NULL;
@@ -1671,6 +1783,87 @@ coff_get_symbol_info (abfd, symbol, ret)
      symbol_info *ret;
 {
   bfd_symbol_info (symbol, ret);
+  if (coffsymbol (symbol)->native != NULL
+      && coffsymbol (symbol)->native->fix_value)
+    {
+      combined_entry_type *psym;
+
+      psym = ((combined_entry_type *)
+             coffsymbol (symbol)->native->u.syment.n_value);
+      ret->value = (bfd_vma) (psym - obj_raw_syments (abfd));
+    }
+}
+
+/* Return the COFF syment for a symbol.  */
+
+boolean
+bfd_coff_get_syment (abfd, symbol, psyment)
+     bfd *abfd;
+     asymbol *symbol;
+     struct internal_syment *psyment;
+{
+  coff_symbol_type *csym;
+
+  csym = coff_symbol_from (abfd, symbol);
+  if (csym == NULL || csym->native == NULL)
+    {
+      bfd_set_error (bfd_error_invalid_operation);
+      return false;
+    }
+
+  *psyment = csym->native->u.syment;
+
+  if (csym->native->fix_value)
+    psyment->n_value = ((combined_entry_type *) psyment->n_value
+                       - obj_raw_syments (abfd));
+
+  /* FIXME: We should handle fix_line here.  */
+
+  return true;
+}
+
+/* Return the COFF auxent for a symbol.  */
+
+boolean
+bfd_coff_get_auxent (abfd, symbol, indx, pauxent)
+     bfd *abfd;
+     asymbol *symbol;
+     int indx;
+     union internal_auxent *pauxent;
+{
+  coff_symbol_type *csym;
+  combined_entry_type *ent;
+
+  csym = coff_symbol_from (abfd, symbol);
+
+  if (csym == NULL
+      || csym->native == NULL
+      || indx >= csym->native->u.syment.n_numaux)
+    {
+      bfd_set_error (bfd_error_invalid_operation);
+      return false;
+    }
+
+  ent = csym->native + indx + 1;
+
+  *pauxent = ent->u.auxent;
+
+  if (ent->fix_tag)
+    pauxent->x_sym.x_tagndx.l =
+      ((combined_entry_type *) pauxent->x_sym.x_tagndx.p
+       - obj_raw_syments (abfd));
+
+  if (ent->fix_end)
+    pauxent->x_sym.x_fcnary.x_fcn.x_endndx.l =
+      ((combined_entry_type *) pauxent->x_sym.x_fcnary.x_fcn.x_endndx.p
+       - obj_raw_syments (abfd));
+
+  if (ent->fix_scnlen)
+    pauxent->x_csect.x_scnlen.l =
+      ((combined_entry_type *) pauxent->x_csect.x_scnlen.p
+       - obj_raw_syments (abfd));
+
+  return true;
 }
 
 /* Print out information about COFF symbol.  */
@@ -1699,6 +1892,7 @@ coff_print_symbol (abfd, filep, symbol, how)
     case bfd_print_symbol_all:
       if (coffsymbol (symbol)->native)
        {
+         unsigned long val;
          unsigned int aux;
          combined_entry_type *combined = coffsymbol (symbol)->native;
          combined_entry_type *root = obj_raw_syments (abfd);
@@ -1706,6 +1900,13 @@ coff_print_symbol (abfd, filep, symbol, how)
 
          fprintf (file, "[%3ld]", (long) (combined - root));
 
+         if (! combined->fix_value)
+           val = (unsigned long) combined->u.syment.n_value;
+         else
+           val = ((unsigned long)
+                  ((combined_entry_type *) combined->u.syment.n_value
+                   - root));
+
          fprintf (file,
                   "(sec %2d)(fl 0x%02x)(ty %3x)(scl %3d) (nx %d) 0x%08lx %s",
                   combined->u.syment.n_scnum,
@@ -1713,7 +1914,7 @@ coff_print_symbol (abfd, filep, symbol, how)
                   combined->u.syment.n_type,
                   combined->u.syment.n_sclass,
                   combined->u.syment.n_numaux,
-                  (unsigned long) combined->u.syment.n_value,
+                  val,
                   symbol->name);
 
          for (aux = 0; aux < combined->u.syment.n_numaux; aux++)
@@ -1745,6 +1946,13 @@ coff_print_symbol (abfd, filep, symbol, how)
                               (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_associated != 0
+                         || auxp->u.auxent.x_scn.x_comdat != 0)
+                       fprintf (file, " checksum 0x%lx assoc %d comdat %d",
+                                auxp->u.auxent.x_scn.x_checksum,
+                                auxp->u.auxent.x_scn.x_associated,
+                                auxp->u.auxent.x_scn.x_comdat);
                      break;
                    }
                  /* else fall through */
@@ -1795,16 +2003,17 @@ coff_print_symbol (abfd, filep, symbol, how)
 
 /*ARGSUSED*/
 boolean
-coff_find_nearest_line (abfd, section, ignore_symbols, offset, filename_ptr,
+coff_find_nearest_line (abfd, section, symbols, offset, filename_ptr,
                        functionname_ptr, line_ptr)
      bfd *abfd;
      asection *section;
-     asymbol **ignore_symbols;
+     asymbol **symbols;
      bfd_vma offset;
      CONST char **filename_ptr;
      CONST char **functionname_ptr;
      unsigned int *line_ptr;
 {
+  boolean found;
   unsigned int i;
   unsigned int line_base;
   coff_data_type *cof = coff_data (abfd);
@@ -1814,6 +2023,16 @@ coff_find_nearest_line (abfd, section, ignore_symbols, offset, filename_ptr,
   alent *l;
   struct coff_section_tdata *sec_data;
 
+  /* Before looking through the symbol table, try to use a .stab
+     section to find the information.  */
+  if (! _bfd_stab_section_find_nearest_line (abfd, symbols, section, offset,
+                                            &found, filename_ptr,
+                                            functionname_ptr, line_ptr,
+                                            &coff_data (abfd)->line_info))
+    return false;
+  if (found)
+    return true;
+
   *filename_ptr = 0;
   *functionname_ptr = 0;
   *line_ptr = 0;
@@ -1899,57 +2118,56 @@ coff_find_nearest_line (abfd, section, ignore_symbols, offset, filename_ptr,
       line_base = 0;
     }
 
-  l = &section->lineno[i];
-
-  for (; i < section->lineno_count; i++)
+  if (section->lineno != NULL)
     {
-      if (l->line_number == 0)
+      l = &section->lineno[i];
+
+      for (; i < section->lineno_count; i++)
        {
-         /* Get the symbol this line number points at */
-         coff_symbol_type *coff = (coff_symbol_type *) (l->u.sym);
-         if (coff->symbol.value > offset)
-           break;
-         *functionname_ptr = coff->symbol.name;
-         if (coff->native)
+         if (l->line_number == 0)
            {
-             combined_entry_type *s = coff->native;
-             s = s + 1 + s->u.syment.n_numaux;
-
-             /* In XCOFF a debugging symbol can follow the function
-                symbol.  */
-             if (s->u.syment.n_scnum == N_DEBUG)
-               s = s + 1 + s->u.syment.n_numaux;
-
-             /*
-                S should now point to the .bf of the function
-              */
-             if (s->u.syment.n_numaux)
+             /* Get the symbol this line number points at */
+             coff_symbol_type *coff = (coff_symbol_type *) (l->u.sym);
+             if (coff->symbol.value > offset)
+               break;
+             *functionname_ptr = coff->symbol.name;
+             if (coff->native)
                {
-                 /*
-                    The linenumber is stored in the auxent
-                  */
-                 union internal_auxent *a = &((s + 1)->u.auxent);
-                 line_base = a->x_sym.x_misc.x_lnsz.x_lnno;
-                 *line_ptr = line_base;
+                 combined_entry_type *s = coff->native;
+                 s = s + 1 + s->u.syment.n_numaux;
+
+                 /* In XCOFF a debugging symbol can follow the
+                    function symbol.  */
+                 if (s->u.syment.n_scnum == N_DEBUG)
+                   s = s + 1 + s->u.syment.n_numaux;
+
+                 /* S should now point to the .bf of the function.  */
+                 if (s->u.syment.n_numaux)
+                   {
+                     /* The linenumber is stored in the auxent.  */
+                     union internal_auxent *a = &((s + 1)->u.auxent);
+                     line_base = a->x_sym.x_misc.x_lnsz.x_lnno;
+                     *line_ptr = line_base;
+                   }
                }
            }
+         else
+           {
+             if (l->u.offset + bfd_get_section_vma (abfd, section) > offset)
+               break;
+             *line_ptr = l->line_number + line_base - 1;
+           }
+         l++;
        }
-      else
-       {
-         if (l->u.offset + bfd_get_section_vma (abfd, section) > offset)
-           break;
-         *line_ptr = l->line_number + line_base - 1;
-       }
-      l++;
     }
 
   /* Cache the results for the next call.  */
-  if (sec_data == NULL)
+  if (sec_data == NULL && section->owner == abfd)
     {
       section->used_by_bfd =
        ((PTR) bfd_zalloc (abfd,
                           sizeof (struct coff_section_tdata)));
-      sec_data = section->used_by_bfd;
+      sec_data = (struct coff_section_tdata *) section->used_by_bfd;
     }
   if (sec_data != NULL)
     {
This page took 0.031825 seconds and 4 git commands to generate.