* Makefile.am (TOOL_PROGS): Use an explicit $(EXEEXT).
[deliverable/binutils-gdb.git] / binutils / stabs.c
index be9fce0a6f21cdfd42f0a61100e22aab7858c5d1..f931ff2820b64ae119bf083c439d13fabf18695b 100644 (file)
 
 struct stab_handle
 {
+  /* The BFD.  */
+  bfd *abfd;
   /* True if this is stabs in sections.  */
   boolean sections;
-  /* The type of the last stab symbol, so that we can detect N_SO
-     pairs.  */
-  int last_type;
+  /* The symbol table.  */
+  asymbol **syms;
+  /* The number of symbols.  */
+  long symcount;
+  /* The accumulated file name string.  */
+  char *so_string;
+  /* The value of the last N_SO symbol.  */
+  bfd_vma so_value;
   /* The value of the start of the file, so that we can handle file
      relative N_LBRAC and N_RBRAC symbols.  */
   bfd_vma file_start_offset;
@@ -72,6 +79,10 @@ struct stab_handle
   struct bincl_file *bincl_stack;
   /* Whether we are inside a function or not.  */
   boolean within_function;
+  /* The address of the end of the function, used if we have seen an
+     N_FUN symbol while in a function.  This is -1 if we have not seen
+     an N_FUN (the normal case).  */
+  bfd_vma function_end;
   /* The depth of block nesting.  */
   int block_depth;
   /* List of pending variable definitions.  */
@@ -341,18 +352,25 @@ warn_stab (p, err)
 
 /*ARGSUSED*/
 PTR
-start_stab (dhandle, sections)
+start_stab (dhandle, abfd, sections, syms, symcount)
      PTR dhandle;
+     bfd *abfd;
      boolean sections;
+     asymbol **syms;
+     long symcount;
 {
   struct stab_handle *ret;
 
   ret = (struct stab_handle *) xmalloc (sizeof *ret);
   memset (ret, 0, sizeof *ret);
+  ret->abfd = abfd;
   ret->sections = sections;
+  ret->syms = syms;
+  ret->symcount = symcount;
   ret->files = 1;
   ret->file_types = (struct stab_types **) xmalloc (sizeof *ret->file_types);
   ret->file_types[0] = NULL;
+  ret->function_end = (bfd_vma) -1;
   return (PTR) ret;
 }
 
@@ -369,9 +387,11 @@ finish_stab (dhandle, handle)
 
   if (info->within_function)
     {
-      if (! debug_end_function (dhandle, (bfd_vma) -1))
+      if (! stab_emit_pending_vars (dhandle, info)
+         || ! debug_end_function (dhandle, info->function_end))
        return false;
       info->within_function = false;
+      info->function_end = (bfd_vma) -1;
     }
 
   for (st = info->tags; st != NULL; st = st->next)
@@ -386,9 +406,6 @@ finish_stab (dhandle, handle)
        return false;
     }
 
-  if (info->pending)
-    fprintf (stderr, "Left over pending variables in stabs debugging\n");
-
   return true;
 }
 
@@ -405,6 +422,38 @@ parse_stab (dhandle, handle, type, desc, value, string)
 {
   struct stab_handle *info = (struct stab_handle *) handle;
 
+  /* gcc will emit two N_SO strings per compilation unit, one for the
+     directory name and one for the file name.  We just collect N_SO
+     strings as we see them, and start the new compilation unit when
+     we see a non N_SO symbol.  */
+  if (info->so_string != NULL
+      && (type != N_SO || *string == '\0' || value != info->so_value))
+    {
+      if (! debug_set_filename (dhandle, info->so_string))
+       return false;
+      info->main_filename = info->so_string;
+
+      info->gcc_compiled = 0;
+      info->n_opt_found = false;
+
+      /* Generally, for stabs in the symbol table, the N_LBRAC and
+        N_RBRAC symbols are relative to the N_SO symbol value.  */
+      if (! info->sections)
+       info->file_start_offset = info->so_value;
+
+      /* We need to reset the mapping from type numbers to types.  We
+        can't free the old mapping, because of the use of
+        debug_make_indirect_type.  */
+      info->files = 1;
+      info->file_types = ((struct stab_types **)
+                         xmalloc (sizeof *info->file_types));
+      info->file_types[0] = NULL;
+
+      info->so_string = NULL;
+
+      /* Now process whatever type we just got.  */
+    }
+
   switch (type)
     {
     case N_FN:
@@ -463,58 +512,48 @@ parse_stab (dhandle, handle, type, desc, value, string)
       break;
 
     case N_SO:
-      /* Start a file.  If we get two in a row, the first is the
-         directory name.  An empty string is emitted by gcc at the end
-         of a compilation unit.  */
-      if (*string == '\0')
-       {
-         if (info->within_function)
-           {
-             if (! debug_end_function (dhandle, value))
-               return false;
-             info->within_function = false;
-           }
-         return true;
-       }
-      info->gcc_compiled = 0;
-      info->n_opt_found = false;
-      if (info->last_type == N_SO)
+      /* This always ends a function.  */
+      if (info->within_function)
        {
-         char *o;
-
-         if (! debug_append_filename (dhandle, string))
+         bfd_vma endval;
+
+         endval = value;
+         if (*string != '\0'
+             && info->function_end != (bfd_vma) -1
+             && info->function_end < endval)
+           endval = info->function_end;
+         if (! stab_emit_pending_vars (dhandle, info)
+             || ! debug_end_function (dhandle, endval))
            return false;
-         o = info->main_filename;
-         info->main_filename = concat (o, string, (const char *) NULL);
-         free (o);
+         info->within_function = false;
+         info->function_end = (bfd_vma) -1;
        }
+
+      /* An empty string is emitted by gcc at the end of a compilation
+         unit.  */
+      if (*string == '\0')
+       return true;
+
+      /* Just accumulate strings until we see a non N_SO symbol.  If
+         the string starts with '/', we discard the previously
+         accumulated strings.  */
+      if (info->so_string == NULL)
+       info->so_string = xstrdup (string);
       else
        {
-         if (info->within_function)
-           {
-             if (! debug_end_function (dhandle, value))
-               return false;
-             info->within_function = false;
-           }
-         if (! debug_set_filename (dhandle, string))
-           return false;
-         if (info->main_filename != NULL)
-           free (info->main_filename);
-         info->main_filename = xstrdup (string);
-
-         /* Generally, for stabs in the symbol table, the N_LBRAC and
-             N_RBRAC symbols are relative to the N_SO symbol value.  */
-         if (! info->sections)
-           info->file_start_offset = value;
-
-         /* We need to reset the mapping from type numbers to types.
-             We can't free the old mapping, because of the use of
-             debug_make_indirect_type.  */
-         info->files = 1;
-         info->file_types = ((struct stab_types **)
-                             xmalloc (sizeof *info->file_types));
-         info->file_types[0] = NULL;
+         char *f;
+
+         f = info->so_string;
+         if (*string == '/')
+           info->so_string = xstrdup (string);
+         else
+           info->so_string = concat (info->so_string, string,
+                                     (const char *) NULL);
+         free (f);
        }
+
+      info->so_value = value;
+
       break;
 
     case N_SOL:
@@ -563,10 +602,40 @@ parse_stab (dhandle, handle, type, desc, value, string)
        return false;
       break;
 
+    case N_FUN:
+      if (*string == '\0')
+       {
+         if (info->within_function)
+           {
+             /* This always marks the end of a function; we don't
+                 need to worry about info->function_end.  */
+             if (info->sections)
+               value += info->function_start_offset;
+             if (! stab_emit_pending_vars (dhandle, info)
+                 || ! debug_end_function (dhandle, value))
+               return false;
+             info->within_function = false;
+             info->function_end = (bfd_vma) -1;
+           }
+         break;
+       }
+
+      /* A const static symbol in the .text section will have an N_FUN
+         entry.  We need to use these to mark the end of the function,
+         in case we are looking at gcc output before it was changed to
+         always emit an empty N_FUN.  We can't call debug_end_function
+         here, because it might be a local static symbol.  */
+      if (info->within_function
+         && (info->function_end == (bfd_vma) -1
+             || value < info->function_end))
+       info->function_end = value;
+
+      /* Fall through.  */
       /* FIXME: gdb checks the string for N_STSYM, N_LCSYM or N_ROSYM
          symbols, and if it does not start with :S, gdb relocates the
          value to the start of the section.  gcc always seems to use
          :S, so we don't worry about this.  */
+      /* Fall through.  */
     default:
       {
        const char *colon;
@@ -577,8 +646,16 @@ parse_stab (dhandle, handle, type, desc, value, string)
          {
            if (info->within_function)
              {
-               if (! debug_end_function (dhandle, value))
+               bfd_vma endval;
+
+               endval = value;
+               if (info->function_end != (bfd_vma) -1
+                   && info->function_end < endval)
+                 endval = info->function_end;
+               if (! stab_emit_pending_vars (dhandle, info)
+                   || ! debug_end_function (dhandle, endval))
                  return false;
+               info->function_end = (bfd_vma) -1;
              }
            /* For stabs in sections, line numbers and block addresses
                are offsets from the start of the function.  */
@@ -607,8 +684,6 @@ parse_stab (dhandle, handle, type, desc, value, string)
       break;
     }
 
-  info->last_type = type;
-
   return true;
 }
 
@@ -788,15 +863,34 @@ parse_stab_string (dhandle, info, stabtype, desc, value, string)
       break;
 
     case 'G':
-      /* A global symbol.  The value must be extracted from the symbol
-         table.  */
-      dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
-                              (debug_type **) NULL);
-      if (dtype == DEBUG_TYPE_NULL)
-       return false;
-      if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_GLOBAL,
-                                 (bfd_vma) -1))
-       return false;
+      {
+       char leading;
+       long c;
+       asymbol **ps;
+
+       /* A global symbol.  The value must be extracted from the
+          symbol table.  */
+       dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
+                                (debug_type **) NULL);
+       if (dtype == DEBUG_TYPE_NULL)
+         return false;
+       leading = bfd_get_symbol_leading_char (info->abfd);
+       for (c = info->symcount, ps = info->syms; c > 0; --c, ++ps)
+         {
+           const char *n;
+
+           n = bfd_asymbol_name (*ps);
+           if (leading != '\0' && *n == leading)
+             ++n;
+           if (*n == *name && strcmp (n, name) == 0)
+             break;
+         }
+       if (c > 0)
+         value = bfd_asymbol_value (*ps);
+       if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_GLOBAL,
+                                   value))
+         return false;
+      }
       break;
 
       /* This case is faked by a conditional above, when there is no
@@ -1631,6 +1725,11 @@ parse_stab_range_type (dhandle, info, typename, pp, typenums)
       if (self_subrange && n2 == 0 && n3 == 0)
        return debug_make_void_type (dhandle);
 
+      /* A type defined as a subrange of itself, with n2 positive and
+        n3 zero, is a complex type, and n2 is the number of bytes.  */
+      if (self_subrange && n3 == 0 && n2 > 0)
+       return debug_make_complex_type (dhandle, n2);
+
       /* If n3 is zero and n2 is positive, this is a floating point
          type, and n2 is the number of bytes.  */
       if (n3 == 0 && n2 > 0)
@@ -2492,6 +2591,7 @@ parse_stab_members (dhandle, info, tagname, pp, typenums, retp)
       do
        {
          debug_type type;
+         boolean stub;
          char *argtypes;
          enum debug_visibility visibility;
          boolean constp, volatilep, staticp;
@@ -2527,6 +2627,11 @@ parse_stab_members (dhandle, info, tagname, pp, typenums, retp)
              return false;
            }
 
+         stub = false;
+         if (debug_get_type_kind (dhandle, type) == DEBUG_KIND_METHOD
+             && debug_get_parameter_types (dhandle, type, &varargs) == NULL)
+           stub = true;
+
          argtypes = savestring (*pp, p - *pp);
          *pp = p + 1;
 
@@ -2583,12 +2688,8 @@ parse_stab_members (dhandle, info, tagname, pp, typenums, retp)
            {
            case '*':
              /* virtual member function, followed by index.  The sign
-                bit is set to distinguish pointers-to-methods from
-                virtual function indicies.  Since the array is in
-                words, the quantity must be shifted left by 1 on 16
-                bit machine, and by 2 on 32 bit machine, forcing the
-                sign bit out, and usable as a valid index into the
-                array.  Remove the sign bit here.  */
+                bit is supposedly set to distinguish
+                pointers-to-methods from virtual function indicies.  */
              ++*pp;
              voffset = parse_number (pp, (boolean *) NULL);
              if (**pp != ';')
@@ -2598,7 +2699,6 @@ parse_stab_members (dhandle, info, tagname, pp, typenums, retp)
                }
              ++*pp;
              voffset &= 0x7fffffff;
-             voffset += 2;
 
              if (**pp == ';' || *pp == '\0')
                {
@@ -2617,6 +2717,7 @@ parse_stab_members (dhandle, info, tagname, pp, typenums, retp)
                    if (**pp == ':')
                      {
                        /* g++ version 1 overloaded methods.  */
+                       context = DEBUG_TYPE_NULL;
                      }
                    else
                      {
@@ -2638,6 +2739,8 @@ parse_stab_members (dhandle, info, tagname, pp, typenums, retp)
              staticp = true;
              voffset = 0;
              context = DEBUG_TYPE_NULL;
+             if (strncmp (argtypes, name, strlen (name)) != 0)
+               stub = true;
              break;
 
            default:
@@ -2653,15 +2756,12 @@ parse_stab_members (dhandle, info, tagname, pp, typenums, retp)
              break;
            }
 
-         /* If this is a method type which is not a stub--that is,
-            the argument types are fully specified--then the argtypes
-            string is actually the physical name of the function.
-            Otherwise, the argtypes string is the mangled from of the
-            argument types, and the physical name of the function,
-            and the argument types, must be deduced from it.  */
-
-         if (debug_get_type_kind (dhandle, type) == DEBUG_KIND_METHOD
-             && debug_get_parameter_types (dhandle, type, &varargs) != NULL)
+         /* If the type is not a stub, then the argtypes string is
+             the physical name of the function.  Otherwise the
+             argtypes string is the mangled form of the argument
+             types, and the full type and the physical name must be
+             extracted from them.  */
+         if (! stub)
            physname = argtypes;
          else
            {
@@ -2952,6 +3052,8 @@ parse_stab_array_type (dhandle, info, pp, stringp)
      boolean stringp;
 {
   const char *orig;
+  const char *p;
+  int typenums[2];
   debug_type index_type;
   boolean adjustable;
   bfd_signed_vma lower, upper;
@@ -2968,8 +3070,27 @@ parse_stab_array_type (dhandle, info, pp, stringp)
 
   /* FIXME: gdb checks os9k_stabs here.  */
 
-  index_type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
-                               (debug_type **) NULL);
+  /* If the index type is type 0, we take it as int.  */
+  p = *pp;
+  if (! parse_stab_type_number (&p, typenums))
+    return false;
+  if (typenums[0] == 0 && typenums[1] == 0 && **pp != '=')
+    {
+      index_type = debug_find_named_type (dhandle, "int");
+      if (index_type == DEBUG_TYPE_NULL)
+       {
+         index_type = debug_make_int_type (dhandle, 4, false);
+         if (index_type == DEBUG_TYPE_NULL)
+           return false;
+       }
+      *pp = p;
+    }
+  else
+    {
+      index_type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
+                                   (debug_type **) NULL);
+    }
+
   if (**pp != ';')
     {
       bad_stab (orig);
@@ -4153,7 +4274,7 @@ stab_demangle_template (minfo, pp)
                  done = true;
                  break;
                default:
-                 /* Assume it's a uder defined integral type.  */
+                 /* Assume it's a user defined integral type.  */
                  integralp = true;
                  done = true;
                  break;
@@ -4854,7 +4975,20 @@ stab_demangle_fund_type (minfo, pp, ptype)
     case 't':
       if (! stab_demangle_template (minfo, pp))
        return false;
-      abort ();
+      if (ptype != NULL)
+       {
+         debug_type t;
+
+         /* FIXME: I really don't know how a template should be
+             represented in the current type system.  Perhaps the
+             template should be demangled into a string, and the type
+             should be represented as a named type.  However, I don't
+             know what the base type of the named type should be.  */
+         t = debug_make_void_type (minfo->dhandle);
+         t = debug_make_pointer_type (minfo->dhandle, t);
+         t = debug_name_type (minfo->dhandle, "TEMPLATE", t);
+         *ptype = t;
+       }
       break;
 
     default:
This page took 0.029496 seconds and 4 git commands to generate.