* ecoff.c (ecoff_set_symbol_info): Mark local stProc or stLabel
authorIan Lance Taylor <ian@airs.com>
Wed, 12 Oct 1994 21:51:04 +0000 (21:51 +0000)
committerIan Lance Taylor <ian@airs.com>
Wed, 12 Oct 1994 21:51:04 +0000 (21:51 +0000)
symbols as BSF_DEBUGGING.
PR 5769.

bfd/ChangeLog
bfd/ecoff.c

index 3bf91b122032f5e1386edbc02359c3fa20c64f00..52ad1c4ad35f535577b9ae10201be53e76a26639 100644 (file)
@@ -7,6 +7,9 @@ Wed Oct 12 16:46:43 1994  Ken Raeburn  <raeburn@cujo.cygnus.com>
 
 Wed Oct 12 11:54:37 1994  Ian Lance Taylor  <ian@sanguine.cygnus.com>
 
+       * ecoff.c (ecoff_set_symbol_info): Mark local stProc or stLabel
+       symbols as BSF_DEBUGGING.
+
        * rs6000-core.c (rs6000coff_core_file_matches_executable_p): Make
        str1 and str2 const pointers.
 
index a2ed76d0b52481ee7d37175080808a351147d42a..a157b2a8d05d451c8ad09ae08864328864b4e67b 100644 (file)
@@ -25,6 +25,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "libbfd.h"
 #include "aout/ar.h"
 #include "aout/ranlib.h"
+#include "aout/stab_gnu.h"
 
 /* FIXME: We need the definitions of N_SET[ADTB], but aout64.h defines
    some other stuff which we don't want and which conflicts with stuff
@@ -152,14 +153,17 @@ _bfd_ecoff_new_section_hook (abfd, section)
      asection *section;
 {
   /* For the .pdata section, which has a special meaning on the Alpha,
-     we set the alignment to 8.  We correct this later in
+     we set the alignment power to 3.  We correct this later in
      ecoff_compute_section_file_positions.  We do this hackery because
      we need to know the exact unaligned size of the .pdata section in
-     order to set the lnnoptr field correctly.  */
+     order to set the lnnoptr field correctly.  For every other
+     section we use an alignment power of 4; this could be made target
+     dependent by adding a field to ecoff_backend_data, but 4 appears
+     to be correct for both the MIPS and the Alpha.  */
   if (strcmp (section->name, _PDATA) == 0)
     section->alignment_power = 3;
   else
-    section->alignment_power = abfd->xvec->align_power_min;
+    section->alignment_power = 4;
 
   if (strcmp (section->name, _TEXT) == 0)
     section->flags |= SEC_CODE | SEC_LOAD | SEC_ALLOC;
@@ -340,9 +344,10 @@ ecoff_sec_to_styp_flags (name, flags)
 
 /*ARGSUSED*/
 flagword
-_bfd_ecoff_styp_to_sec_flags (abfd, hdr)
+_bfd_ecoff_styp_to_sec_flags (abfd, hdr, name)
      bfd *abfd;
      PTR hdr;
+     const char *name;
 {
   struct internal_scnhdr *internal_s = (struct internal_scnhdr *) hdr;
   long styp_flags = internal_s->s_flags;
@@ -871,7 +876,7 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext, indirect_ptr_ptr)
       (*indirect_ptr_ptr)->value = (bfd_vma) asym;
 
       asym->flags = BSF_DEBUGGING;
-      asym->section = &bfd_und_section;
+      asym->section = bfd_und_section_ptr;
       *indirect_ptr_ptr = NULL;
       return true;
     }
@@ -880,7 +885,7 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext, indirect_ptr_ptr)
       && (ECOFF_UNMARK_STAB (ecoff_sym->index) | N_EXT) == (N_INDR | N_EXT))
     {
       asym->flags = BSF_DEBUGGING | BSF_INDIRECT;
-      asym->section = &bfd_ind_section;
+      asym->section = bfd_ind_section_ptr;
       /* Pass this symbol on to the next call to this function.  */
       *indirect_ptr_ptr = asym;
       return true;
@@ -910,7 +915,18 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext, indirect_ptr_ptr)
   if (ext)
     asym->flags = BSF_EXPORT | BSF_GLOBAL;
   else
-    asym->flags = BSF_LOCAL;
+    {
+      asym->flags = BSF_LOCAL;
+      /* Normally, a local stProc symbol will have a corresponding
+         external symbol.  We mark the local symbol as a debugging
+         symbol, in order to prevent nm from printing both out.
+         Similarly, we mark stLabel fields as debugging symbols.  In
+         both cases, we do want to set the value correctly based on
+         the symbol class.  */
+      if (ecoff_sym->st == stProc
+         || ecoff_sym->st == stLabel)
+       asym->flags |= BSF_DEBUGGING;
+    }
   switch (ecoff_sym->sc)
     {
     case scNil:
@@ -936,10 +952,10 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext, indirect_ptr_ptr)
       asym->flags = BSF_DEBUGGING;
       break;
     case scAbs:
-      asym->section = &bfd_abs_section;
+      asym->section = bfd_abs_section_ptr;
       break;
     case scUndefined:
-      asym->section = &bfd_und_section;
+      asym->section = bfd_und_section_ptr;
       asym->flags = 0;
       asym->value = 0;
       break;
@@ -969,7 +985,7 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext, indirect_ptr_ptr)
     case scCommon:
       if (asym->value > ecoff_data (abfd)->gp_size)
        {
-         asym->section = &bfd_com_section;
+         asym->section = bfd_com_section_ptr;
          asym->flags = 0;
          break;
        }
@@ -996,7 +1012,7 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext, indirect_ptr_ptr)
       asym->flags = BSF_DEBUGGING;
       break;
     case scSUndefined:
-      asym->section = &bfd_und_section;
+      asym->section = bfd_und_section_ptr;
       asym->flags = 0;
       asym->value = 0;
       break;
@@ -1895,7 +1911,7 @@ ecoff_slurp_reloc_table (abfd, section, symbols)
       else if (intern.r_symndx == RELOC_SECTION_NONE
               || intern.r_symndx == RELOC_SECTION_ABS)
        {
-         rptr->sym_ptr_ptr = bfd_abs_section.symbol_ptr_ptr;
+         rptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
          rptr->addend = 0;
        }
       else
@@ -2003,18 +2019,12 @@ _bfd_ecoff_find_nearest_line (abfd, section, ignore_symbols, offset,
 {
   const struct ecoff_debug_swap * const debug_swap
     = &ecoff_backend (abfd)->debug_swap;
+  struct ecoff_debug_info * const debug_info = &ecoff_data (abfd)->debug_info;
   FDR *fdr_ptr;
   FDR *fdr_start;
   FDR *fdr_end;
   FDR *fdr_hold;
-  bfd_size_type external_pdr_size;
-  char *pdr_ptr;
-  char *pdr_end;
-  PDR pdr;
-  bfd_vma first_off;
-  unsigned char *line_ptr;
-  unsigned char *line_end;
-  int lineno;
+  boolean stabs;
 
   /* If we're not in the .text section, we don't have any line
      numbers.  */
@@ -2024,8 +2034,7 @@ _bfd_ecoff_find_nearest_line (abfd, section, ignore_symbols, offset,
     return false;
 
   /* Make sure we have the FDR's.  */
-  if (! _bfd_ecoff_slurp_symbolic_info (abfd, (asection *) NULL,
-                                       &ecoff_data (abfd)->debug_info)
+  if (! _bfd_ecoff_slurp_symbolic_info (abfd, (asection *) NULL, debug_info)
       || bfd_get_symcount (abfd) == 0)
     return false;
 
@@ -2034,8 +2043,8 @@ _bfd_ecoff_find_nearest_line (abfd, section, ignore_symbols, offset,
      memory order.  If speed is ever important, this can become a
      binary search.  We must ignore FDR's with no PDR entries; they
      will have the adr of the FDR before or after them.  */
-  fdr_start = ecoff_data (abfd)->debug_info.fdr;
-  fdr_end = fdr_start + ecoff_data (abfd)->debug_info.symbolic_header.ifdMax;
+  fdr_start = debug_info->fdr;
+  fdr_end = fdr_start + debug_info->symbolic_header.ifdMax;
   fdr_hold = (FDR *) NULL;
   for (fdr_ptr = fdr_start; fdr_ptr < fdr_end; fdr_ptr++)
     {
@@ -2049,112 +2058,289 @@ _bfd_ecoff_find_nearest_line (abfd, section, ignore_symbols, offset,
     return false;
   fdr_ptr = fdr_hold;
 
-  /* Each FDR has a list of procedure descriptors (PDR).  PDR's also
-     have an address, which is relative to the FDR address, and are
-     also stored in increasing memory order.  */
-  offset -= fdr_ptr->adr;
-  external_pdr_size = debug_swap->external_pdr_size;
-  pdr_ptr = ((char *) ecoff_data (abfd)->debug_info.external_pdr
-            + fdr_ptr->ipdFirst * external_pdr_size);
-  pdr_end = pdr_ptr + fdr_ptr->cpd * external_pdr_size;
-  (*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr);
-  if (offset < pdr.adr)
-    return false;
+  /* Check whether this file has stabs debugging information.  In a
+     file with stabs debugging information, the second local symbol is
+     named @stabs.  */
+  stabs = false;
+  if (fdr_ptr->csym >= 2)
+    {
+      char *sym_ptr;
+      SYMR sym;
 
-  /* The address of the first PDR is an offset which applies to the
-     addresses of all the PDR's.  */
-  first_off = pdr.adr;
+      sym_ptr = ((char *) debug_info->external_sym
+                + (fdr_ptr->isymBase + 1) * debug_swap->external_sym_size);
+      (*debug_swap->swap_sym_in) (abfd, sym_ptr, &sym);
+      if (strcmp (debug_info->ss + fdr_ptr->issBase + sym.iss,
+                 STABS_SYMBOL) == 0)
+       stabs = true;
+    }
 
-  for (pdr_ptr += external_pdr_size;
-       pdr_ptr < pdr_end;
-       pdr_ptr += external_pdr_size)
+  if (! stabs)
     {
+      bfd_size_type external_pdr_size;
+      char *pdr_ptr;
+      char *pdr_end;
+      PDR pdr;
+      bfd_vma first_off;
+      unsigned char *line_ptr;
+      unsigned char *line_end;
+      int lineno;
+
+      /* This file uses ECOFF debugging information.  Each FDR has a
+        list of procedure descriptors (PDR).  PDR's also have an
+        address, which is relative to the FDR address, and are also
+        stored in increasing memory order.  */
+      offset -= fdr_ptr->adr;
+      external_pdr_size = debug_swap->external_pdr_size;
+      pdr_ptr = ((char *) debug_info->external_pdr
+                + fdr_ptr->ipdFirst * external_pdr_size);
+      pdr_end = pdr_ptr + fdr_ptr->cpd * external_pdr_size;
       (*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr);
       if (offset < pdr.adr)
-       break;
-    }
+       return false;
 
-  /* Now we can look for the actual line number.  The line numbers are
-     stored in a very funky format, which I won't try to describe.
-     Note that right here pdr_ptr and pdr hold the PDR *after* the one
-     we want; we need this to compute line_end.  */
-  line_end = ecoff_data (abfd)->debug_info.line;
-  if (pdr_ptr == pdr_end)
-    line_end += fdr_ptr->cbLineOffset + fdr_ptr->cbLine;
-  else
-    line_end += fdr_ptr->cbLineOffset + pdr.cbLineOffset;
-
-  /* Now change pdr and pdr_ptr to the one we want.  */
-  pdr_ptr -= external_pdr_size;
-  (*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr);
-
-  offset -= pdr.adr - first_off;
-  lineno = pdr.lnLow;
-  line_ptr = (ecoff_data (abfd)->debug_info.line
-             + fdr_ptr->cbLineOffset
-             + pdr.cbLineOffset);
-  while (line_ptr < line_end)
-    {
-      int delta;
-      int count;
-
-      delta = *line_ptr >> 4;
-      if (delta >= 0x8)
-       delta -= 0x10;
-      count = (*line_ptr & 0xf) + 1;
-      ++line_ptr;
-      if (delta == -8)
+      /* The address of the first PDR is an offset which applies to
+        the addresses of all the PDR's.  */
+      first_off = pdr.adr;
+
+      for (pdr_ptr += external_pdr_size;
+          pdr_ptr < pdr_end;
+          pdr_ptr += external_pdr_size)
        {
-         delta = (((line_ptr[0]) & 0xff) << 8) + ((line_ptr[1]) & 0xff);
-         if (delta >= 0x8000)
-           delta -= 0x10000;
-         line_ptr += 2;
+         (*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr);
+         if (offset < pdr.adr)
+           break;
        }
-      lineno += delta;
-      if (offset < count * 4)
-       break;
-      offset -= count * 4;
-    }
 
-  /* If fdr_ptr->rss is -1, then this file does not have full symbols,
-     at least according to gdb/mipsread.c.  */
-  if (fdr_ptr->rss == -1)
-    {
-      *filename_ptr = NULL;
-      if (pdr.isym == -1)
-       *functionname_ptr = NULL;
+      /* Now we can look for the actual line number.  The line numbers
+        are stored in a very funky format, which I won't try to
+        describe.  Note that right here pdr_ptr and pdr hold the PDR
+        *after* the one we want; we need this to compute line_end.  */
+      line_end = debug_info->line;
+      if (pdr_ptr == pdr_end)
+       line_end += fdr_ptr->cbLineOffset + fdr_ptr->cbLine;
+      else
+       line_end += fdr_ptr->cbLineOffset + pdr.cbLineOffset;
+
+      /* Now change pdr and pdr_ptr to the one we want.  */
+      pdr_ptr -= external_pdr_size;
+      (*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr);
+
+      offset -= pdr.adr - first_off;
+      lineno = pdr.lnLow;
+      line_ptr = debug_info->line + fdr_ptr->cbLineOffset + pdr.cbLineOffset;
+      while (line_ptr < line_end)
+       {
+         int delta;
+         int count;
+
+         delta = *line_ptr >> 4;
+         if (delta >= 0x8)
+           delta -= 0x10;
+         count = (*line_ptr & 0xf) + 1;
+         ++line_ptr;
+         if (delta == -8)
+           {
+             delta = (((line_ptr[0]) & 0xff) << 8) + ((line_ptr[1]) & 0xff);
+             if (delta >= 0x8000)
+               delta -= 0x10000;
+             line_ptr += 2;
+           }
+         lineno += delta;
+         if (offset < count * 4)
+           break;
+         offset -= count * 4;
+       }
+
+      /* If fdr_ptr->rss is -1, then this file does not have full
+        symbols, at least according to gdb/mipsread.c.  */
+      if (fdr_ptr->rss == -1)
+       {
+         *filename_ptr = NULL;
+         if (pdr.isym == -1)
+           *functionname_ptr = NULL;
+         else
+           {
+             EXTR proc_ext;
+
+             (*debug_swap->swap_ext_in)
+               (abfd,
+                ((char *) debug_info->external_ext
+                 + pdr.isym * debug_swap->external_ext_size),
+                &proc_ext);
+             *functionname_ptr = debug_info->ssext + proc_ext.asym.iss;
+           }
+       }
       else
        {
-         EXTR proc_ext;
+         SYMR proc_sym;
 
-         (*debug_swap->swap_ext_in)
+         *filename_ptr = debug_info->ss + fdr_ptr->issBase + fdr_ptr->rss;
+         (*debug_swap->swap_sym_in)
            (abfd,
-            ((char *) ecoff_data (abfd)->debug_info.external_ext
-             + pdr.isym * debug_swap->external_ext_size),
-            &proc_ext);
-         *functionname_ptr = (ecoff_data (abfd)->debug_info.ssext
-                              + proc_ext.asym.iss);
+            ((char *) debug_info->external_sym
+             + (fdr_ptr->isymBase + pdr.isym) * debug_swap->external_sym_size),
+            &proc_sym);
+         *functionname_ptr = debug_info->ss + fdr_ptr->issBase + proc_sym.iss;
        }
+      if (lineno == ilineNil)
+       lineno = 0;
+      *retline_ptr = lineno;
     }
   else
     {
-      SYMR proc_sym;
-
-      *filename_ptr = (ecoff_data (abfd)->debug_info.ss
-                      + fdr_ptr->issBase
-                      + fdr_ptr->rss);
-      (*debug_swap->swap_sym_in)
-       (abfd,
-        ((char *) ecoff_data (abfd)->debug_info.external_sym
-         + (fdr_ptr->isymBase + pdr.isym) * debug_swap->external_sym_size),
-        &proc_sym);
-      *functionname_ptr = (ecoff_data (abfd)->debug_info.ss
-                          + fdr_ptr->issBase
-                          + proc_sym.iss);
+      bfd_size_type external_sym_size;
+      const char *directory_name;
+      const char *main_file_name;
+      const char *current_file_name;
+      const char *function_name;
+      const char *line_file_name;
+      bfd_vma low_func_vma;
+      bfd_vma low_line_vma;
+      char *sym_ptr, *sym_ptr_end;
+      size_t len, funclen;
+      char *buffer = NULL;
+
+      /* This file uses stabs debugging information.  */
+
+      *filename_ptr = NULL;
+      *functionname_ptr = NULL;
+      *retline_ptr = 0;
+
+      directory_name = NULL;
+      main_file_name = NULL;
+      current_file_name = NULL;
+      function_name = NULL;
+      line_file_name = NULL;
+      low_func_vma = 0;
+      low_line_vma = 0;
+
+      external_sym_size = debug_swap->external_sym_size;
+
+      sym_ptr = ((char *) debug_info->external_sym
+                + (fdr_ptr->isymBase + 2) * external_sym_size);
+      sym_ptr_end = sym_ptr + fdr_ptr->csym * external_sym_size;
+      for (; sym_ptr < sym_ptr_end; sym_ptr += external_sym_size)
+       {
+         SYMR sym;
+
+         (*debug_swap->swap_sym_in) (abfd, sym_ptr, &sym);
+
+         if (ECOFF_IS_STAB (&sym))
+           {
+             switch (ECOFF_UNMARK_STAB (sym.index))
+               {
+               case N_SO:
+                 main_file_name = current_file_name =
+                   debug_info->ss + fdr_ptr->issBase + sym.iss;
+
+                 /* Check the next symbol to see if it is also an
+                     N_SO symbol.  */
+                 if (sym_ptr + external_sym_size < sym_ptr_end)
+                   {
+                     SYMR nextsym;
+
+                     (*debug_swap->swap_sym_in) (abfd,
+                                                 sym_ptr + external_sym_size,
+                                                 &nextsym);
+                     if (ECOFF_IS_STAB (&nextsym)
+                         && ECOFF_UNMARK_STAB (nextsym.index) == N_SO)
+                       {
+                         directory_name = current_file_name;
+                         main_file_name = current_file_name =
+                           debug_info->ss + fdr_ptr->issBase + sym.iss;
+                         sym_ptr += external_sym_size;
+                       }
+                   }
+                 break;
+
+               case N_SOL:
+                 current_file_name =
+                   debug_info->ss + fdr_ptr->issBase + sym.iss;
+                 break;
+
+               case N_FUN:
+                 if (sym.value >= low_func_vma
+                     && sym.value <= offset + section->vma)
+                   {
+                     low_func_vma = sym.value;
+                     function_name =
+                       debug_info->ss + fdr_ptr->issBase + sym.iss;
+                   }
+                 break;
+               }
+           }
+         else if (sym.st == stLabel && sym.index != indexNil)
+           {
+             if (sym.value > offset + section->vma)
+               {
+                 /* We have passed the location in the file we are
+                     looking for, so we can get out of the loop.  */
+                 break;
+               }
+
+             if (sym.value >= low_line_vma)
+               {
+                 low_line_vma = sym.value;
+                 line_file_name = current_file_name;
+                 *retline_ptr = sym.index;
+               }
+           }
+       }
+
+      if (*retline_ptr != 0)
+       main_file_name = line_file_name;
+
+      /* We need to remove the stuff after the colon in the function
+         name.  We also need to put the directory name and the file
+         name together.  */
+      if (function_name == NULL)
+       len = funclen = 0;
+      else
+       len = funclen = strlen (function_name) + 1;
+
+      if (main_file_name != NULL
+         && directory_name != NULL
+         && main_file_name[0] != '/')
+       len += strlen (directory_name) + strlen (main_file_name) + 1;
+
+      if (len != 0)
+       {
+         if (ecoff_data (abfd)->find_buffer != NULL)
+           free (ecoff_data (abfd)->find_buffer);
+         buffer = (char *) malloc (len);
+         if (buffer == NULL)
+           {
+             bfd_set_error (bfd_error_no_memory);
+             return false;
+           }
+         ecoff_data (abfd)->find_buffer = buffer;
+       }
+
+      if (function_name != NULL)
+       {
+         char *colon;
+
+         strcpy (buffer, function_name);
+         colon = strchr (buffer, ':');
+         if (colon != NULL)
+           *colon = '\0';
+         *functionname_ptr = buffer;
+       }
+
+      if (main_file_name != NULL)
+       {
+         if (directory_name == NULL || main_file_name[0] == '/')
+           *filename_ptr = main_file_name;
+         else
+           {
+             sprintf (buffer + funclen, "%s%s", directory_name,
+                      main_file_name);
+             *filename_ptr = buffer + funclen;
+           }
+       }
     }
-  if (lineno == ilineNil)
-    lineno = 0;
-  *retline_ptr = lineno;
+
   return true;
 }
 \f
@@ -2617,7 +2803,7 @@ ecoff_get_extr (sym, esym)
      symbol.  */
   if ((esym->asym.sc == scUndefined
        || esym->asym.sc == scSUndefined)
-      && bfd_get_section (sym) != &bfd_und_section)
+      && ! bfd_is_und_section (bfd_get_section (sym)))
     esym->asym.sc = scAbs;
 
   /* Adjust the FDR index for the symbol by that used for the input
@@ -4099,10 +4285,10 @@ ecoff_link_add_externals (abfd, info, external_ext, ssext)
          value -= section->vma;
          break;
        case scAbs:
-         section = &bfd_abs_section;
+         section = bfd_abs_section_ptr;
          break;
        case scUndefined:
-         section = &bfd_und_section;
+         section = bfd_und_section_ptr;
          break;
        case scSData:
          section = bfd_make_section_old_way (abfd, ".sdata");
@@ -4119,7 +4305,7 @@ ecoff_link_add_externals (abfd, info, external_ext, ssext)
        case scCommon:
          if (value > ecoff_data (abfd)->gp_size)
            {
-             section = &bfd_com_section;
+             section = bfd_com_section_ptr;
              break;
            }
          /* Fall through.  */
@@ -4140,7 +4326,7 @@ ecoff_link_add_externals (abfd, info, external_ext, ssext)
          section = &ecoff_scom_section;
          break;
        case scSUndefined:
-         section = &bfd_und_section;
+         section = bfd_und_section_ptr;
          break;
        case scInit:
          section = bfd_make_section_old_way (abfd, ".init");
@@ -4171,7 +4357,7 @@ ecoff_link_add_externals (abfd, info, external_ext, ssext)
       if (info->hash->creator->flavour == bfd_get_flavour (abfd))
        {
          if (h->abfd == (bfd *) NULL
-             || (section != &bfd_und_section
+             || (! bfd_is_und_section (section)
                  && (! bfd_is_com_section (section)
                      || h->root.type != bfd_link_hash_defined)))
            {