* dwarfread.c (dbsize): New variable to hold size of dwarf info.
[deliverable/binutils-gdb.git] / gdb / dwarfread.c
index 161fc7890e0edbaee932acf5409a3814a46bc319..d89deba80da7bd4f2aafe59c053858326a1d5338 100644 (file)
@@ -53,6 +53,7 @@ other things to work on, if you get bored. :-)
 #include "libbfd.h"    /* FIXME Secret Internal BFD stuff (bfd_read) */
 #include "elf/dwarf.h"
 #include "buildsym.h"
+#include "demangle.h"
 
 #ifdef MAINTENANCE     /* Define to 1 to compile in some maintenance stuff */
 #define SQUAWK(stuff) dwarfwarn stuff
@@ -70,6 +71,18 @@ typedef unsigned int DIE_REF;        /* Reference to a DIE */
 #define GCC_PRODUCER "GNU C "
 #endif
 
+#ifndef GPLUS_PRODUCER
+#define GPLUS_PRODUCER "GNU C++ "
+#endif
+
+#ifndef LCC_PRODUCER
+#define LCC_PRODUCER "NCR C/C++"
+#endif
+
+#ifndef CFRONT_PRODUCER
+#define CFRONT_PRODUCER "CFRONT "      /* A wild a** guess... */
+#endif
+
 #define STREQ(a,b)             (strcmp(a,b)==0)
 #define STREQN(a,b,n)          (strncmp(a,b,n)==0)
 
@@ -103,15 +116,15 @@ typedef unsigned int DIE_REF;     /* Reference to a DIE */
 /* Macros that return the sizes of various types of data in the target
    environment.
 
-   FIXME:  They currently just return the sizes in the host environment.
-   They need to be able to get the right size either from the bfd or possibly
-   from the DWARF info.  It would be nice if the DWARF producer inserted DIES
-   that describe the fundamental types in the target environment into the
-   DWARF info, similar to the way dbx stabs producers produce information
-   about their fundamental types. */
+   FIXME:  Currently these are just compile time constants (as they are in
+   other parts of gdb as well).  They need to be able to get the right size
+   either from the bfd or possibly from the DWARF info.  It would be nice if
+   the DWARF producer inserted DIES that describe the fundamental types in
+   the target environment into the DWARF info, similar to the way dbx stabs
+   producers produce information about their fundamental types. */
 
-#define TARGET_FT_POINTER_SIZE(objfile)        sizeof (PTR)    /* FIXME */
-#define TARGET_FT_LONG_SIZE(objfile)   sizeof (long)   /* FIXME */
+#define TARGET_FT_POINTER_SIZE(objfile)        (TARGET_PTR_BIT / TARGET_CHAR_BIT)
+#define TARGET_FT_LONG_SIZE(objfile)   (TARGET_LONG_BIT / TARGET_CHAR_BIT)
 
 /* The Amiga SVR4 header file <dwarf.h> defines AT_element_list as a
    FORM_BLOCK2, and this is the value emitted by the AT&T compiler.
@@ -182,18 +195,16 @@ struct dieinfo {
   unsigned long                at_member;
   unsigned long                at_discr;
   BLOCK *              at_discr_value;
-  unsigned short       at_visibility;
-  unsigned long                at_import;
   BLOCK *              at_string_length;
   char *               at_comp_dir;
   char *               at_producer;
-  unsigned long                at_frame_base;
   unsigned long                at_start_scope;
   unsigned long                at_stride_size;
   unsigned long                at_src_info;
   char *               at_prototyped;
   unsigned int         has_at_low_pc:1;
   unsigned int         has_at_stmt_list:1;
+  unsigned int         has_at_byte_size:1;
   unsigned int         short_element_list:1;
 };
 
@@ -201,13 +212,20 @@ static int diecount;      /* Approximate count of dies for compilation unit */
 static struct dieinfo *curdie; /* For warnings and such */
 
 static char *dbbase;   /* Base pointer to dwarf info */
+static int dbsize;     /* Size of dwarf info in bytes */
 static int dbroff;     /* Relative offset from start of .debug section */
 static char *lnbase;   /* Base pointer to line section */
 static int isreg;      /* Kludge to identify register variables */
 static int offreg;     /* Kludge to identify basereg references */
 
+/* This value is added to each symbol value.  FIXME:  Generalize to 
+   the section_offsets structure used by dbxread.  */
 static CORE_ADDR baseaddr;     /* Add to each symbol value */
 
+/* The section offsets used in the current psymtab or symtab.  FIXME,
+   only used to pass one value (baseaddr) at the moment.  */
+static struct section_offsets *base_section_offsets;
+
 /* Each partial symbol table entry contains a pointer to private data for the
    read_symtab() function to use when expanding a partial symbol table entry
    to a full symbol table entry.  For DWARF debugging info, this data is
@@ -283,6 +301,15 @@ struct pending **list_in_scope = &file_symbols;
 static struct type **utypes;   /* Pointer to array of user type pointers */
 static int numutypes;          /* Max number of user type pointers */
 
+/* Record the language for the compilation unit which is currently being
+   processed.  We know it once we have seen the TAG_compile_unit DIE,
+   and we need it while processing the DIE's for that compilation unit.
+   It is eventually saved in the symtab structure, but we don't finalize
+   the symtab struct until we have processed all the DIE's for the
+   compilation unit. */
+
+static enum language cu_language;
+
 /* Forward declarations of static functions so we don't have to worry
    about ordering within this file.  */
 
@@ -295,6 +322,9 @@ target_to_host PARAMS ((char *, int, int, struct objfile *));
 static void
 add_enum_psymbol PARAMS ((struct dieinfo *, struct objfile *));
 
+static void
+handle_producer PARAMS ((char *));
+
 static void
 read_file_scope PARAMS ((struct dieinfo *, char *, char *, struct objfile *));
 
@@ -380,7 +410,7 @@ static struct type *
 decode_mod_u_d_type PARAMS ((char *));
 
 static struct type *
-decode_modified_type PARAMS ((unsigned char *, unsigned int, int));
+decode_modified_type PARAMS ((char *, unsigned int, int));
 
 static struct type *
 decode_fund_type PARAMS ((unsigned int));
@@ -397,6 +427,10 @@ alloc_utype PARAMS ((DIE_REF, struct type *));
 static struct symbol *
 new_symbol PARAMS ((struct dieinfo *, struct objfile *));
 
+static void
+synthesize_typedef PARAMS ((struct dieinfo *, struct objfile *,
+                           struct type *));
+
 static int
 locval PARAMS ((char *));
 
@@ -404,6 +438,58 @@ static void
 record_minimal_symbol PARAMS ((char *, CORE_ADDR, enum minimal_symbol_type,
                               struct objfile *));
 
+static void
+set_cu_language PARAMS ((struct dieinfo *));
+
+/*
+
+LOCAL FUNCTION
+
+       set_cu_language -- set local copy of language for compilation unit
+
+SYNOPSIS
+
+       void
+       set_cu_language (struct dieinfo *dip)
+
+DESCRIPTION
+
+       Decode the language attribute for a compilation unit DIE and
+       remember what the language was.  We use this at various times
+       when processing DIE's for a given compilation unit.
+
+RETURNS
+
+       No return value.
+
+ */
+
+static void
+set_cu_language (dip)
+     struct dieinfo *dip;
+{
+  switch (dip -> at_language)
+    {
+      case LANG_C89:
+      case LANG_C:
+        cu_language = language_c;
+       break;
+      case LANG_C_PLUS_PLUS:
+       cu_language = language_cplus;
+       break;
+      case LANG_ADA83:
+      case LANG_COBOL74:
+      case LANG_COBOL85:
+      case LANG_FORTRAN77:
+      case LANG_FORTRAN90:
+      case LANG_PASCAL83:
+      case LANG_MODULA2:
+      default:
+       cu_language = language_unknown;
+       break;
+    }
+}
+
 /*
 
 GLOBAL FUNCTION
@@ -412,8 +498,9 @@ GLOBAL FUNCTION
 
 SYNOPSIS
 
-       void dwarf_build_psymtabs (int desc, char *filename, CORE_ADDR addr,
-            int mainline, unsigned int dbfoff, unsigned int dbsize,
+       void dwarf_build_psymtabs (int desc, char *filename, 
+            struct section_offsets *section_offsets,
+            int mainline, unsigned int dbfoff, unsigned int dbfsize,
             unsigned int lnoffset, unsigned int lnsize,
             struct objfile *objfile)
 
@@ -437,14 +524,14 @@ RETURNS
  */
 
 void
-dwarf_build_psymtabs (desc, filename, addr, mainline, dbfoff, dbsize,
+dwarf_build_psymtabs (desc, filename, section_offsets, mainline, dbfoff, dbfsize,
                      lnoffset, lnsize, objfile)
      int desc;
      char *filename;
-     CORE_ADDR addr;
+     struct section_offsets *section_offsets;
      int mainline;
      unsigned int dbfoff;
-     unsigned int dbsize;
+     unsigned int dbfsize;
      unsigned int lnoffset;
      unsigned int lnsize;
      struct objfile *objfile;
@@ -452,6 +539,7 @@ dwarf_build_psymtabs (desc, filename, addr, mainline, dbfoff, dbsize,
   struct cleanup *back_to;
   
   current_objfile = objfile;
+  dbsize = dbfsize;
   dbbase = xmalloc (dbsize);
   dbroff = 0;
   if ((lseek (desc, dbfoff, 0) != dbfoff) ||
@@ -474,7 +562,8 @@ dwarf_build_psymtabs (desc, filename, addr, mainline, dbfoff, dbsize,
   
   /* Save the relocation factor where everybody can see it.  */
 
-  baseaddr = addr;
+  base_section_offsets = section_offsets;
+  baseaddr = ANOFFSET (section_offsets, 0);
 
   /* Follow the compilation unit sibling chain, building a partial symbol
      table entry for each one.  Save enough information about each compilation
@@ -596,7 +685,7 @@ read_lexical_block_scope (dip, thisdie, enddie, objfile)
 {
   register struct context_stack *new;
 
-  (void) push_context (0, dip -> at_low_pc);
+  push_context (0, dip -> at_low_pc);
   process_dies (thisdie + dip -> die_length, enddie, objfile);
   new = pop_context ();
   if (local_symbols != NULL)
@@ -691,11 +780,7 @@ alloc_utype (die_ref, utypep)
     {
       if (utypep == NULL)
        {
-         utypep = (struct type *)
-           obstack_alloc (&current_objfile -> type_obstack,
-                          sizeof (struct type));
-         (void) memset (utypep, 0, sizeof (struct type));
-         TYPE_OBJFILE (utypep) = current_objfile;
+         utypep = alloc_type (current_objfile);
        }
       *typep = utypep;
     }
@@ -790,6 +875,7 @@ struct_type (dip, thisdie, enddie, objfile)
   char *tpart1;
   struct dieinfo mbr;
   char *nextdie;
+  int anonymous_size;
   
   if ((type = lookup_utype (dip -> die_ref)) == NULL)
     {
@@ -799,6 +885,10 @@ struct_type (dip, thisdie, enddie, objfile)
   INIT_CPLUS_SPECIFIC(type);
   switch (dip -> die_tag)
     {
+      case TAG_class_type:
+        TYPE_CODE (type) = TYPE_CODE_CLASS;
+       tpart1 = "class";
+       break;
       case TAG_structure_type:
         TYPE_CODE (type) = TYPE_CODE_STRUCT;
        tpart1 = "struct";
@@ -811,7 +901,7 @@ struct_type (dip, thisdie, enddie, objfile)
        /* Should never happen */
        TYPE_CODE (type) = TYPE_CODE_UNDEF;
        tpart1 = "???";
-       SQUAWK (("missing structure or union tag"));
+       SQUAWK (("missing class, structure, or union tag"));
        break;
     }
   /* Some compilers try to be helpful by inventing "fake" names for
@@ -824,10 +914,12 @@ struct_type (dip, thisdie, enddie, objfile)
       TYPE_NAME (type) = obconcat (&objfile -> type_obstack,
                                   tpart1, " ", dip -> at_name);
     }
-  if (dip -> at_byte_size != 0)
-    {
-      TYPE_LENGTH (type) = dip -> at_byte_size;
-    }
+  /* Use whatever size is known.  Zero is a valid size.  We might however
+     wish to check has_at_byte_size to make sure that some byte size was
+     given explicitly, but DWARF doesn't specify that explicit sizes of
+     zero have to present, so complaining about missing sizes should 
+     probably not be the default. */
+  TYPE_LENGTH (type) = dip -> at_byte_size;
   thisdie += dip -> die_length;
   while (thisdie < enddie)
     {
@@ -853,10 +945,46 @@ struct_type (dip, thisdie, enddie, objfile)
          new -> next = list;
          list = new;
          /* Save the data.  */
-         list -> field.name = savestring (mbr.at_name, strlen (mbr.at_name));
+         list -> field.name =
+             obsavestring (mbr.at_name, strlen (mbr.at_name),
+                           &objfile -> type_obstack);
          list -> field.type = decode_die_type (&mbr);
          list -> field.bitpos = 8 * locval (mbr.at_location);
-         list -> field.bitsize = 0;
+         /* Handle bit fields. */
+         list -> field.bitsize = mbr.at_bit_size;
+#if BITS_BIG_ENDIAN
+         /* For big endian bits, the at_bit_offset gives the additional
+            bit offset from the MSB of the containing anonymous object to
+            the MSB of the field.  We don't have to do anything special
+            since we don't need to know the size of the anonymous object. */
+         list -> field.bitpos += mbr.at_bit_offset;
+#else
+         /* For little endian bits, we need to have a non-zero at_bit_size,
+            so that we know we are in fact dealing with a bitfield.  Compute
+            the bit offset to the MSB of the anonymous object, subtract off
+            the number of bits from the MSB of the field to the MSB of the
+            object, and then subtract off the number of bits of the field
+            itself.  The result is the bit offset of the LSB of the field. */
+         if (mbr.at_bit_size > 0)
+           {
+             if (mbr.has_at_byte_size)
+               {
+                 /* The size of the anonymous object containing the bit field
+                    is explicit, so use the indicated size (in bytes). */
+                 anonymous_size = mbr.at_byte_size;
+               }
+             else
+               {
+                 /* The size of the anonymous object containing the bit field
+                    matches the size of an object of the bit field's type.
+                    DWARF allows at_byte_size to be left out in such cases,
+                    as a debug information size optimization. */
+                 anonymous_size = TYPE_LENGTH (list -> field.type);
+               }
+             list -> field.bitpos +=
+               anonymous_size * 8 - mbr.at_bit_offset - mbr.at_bit_size;
+           }
+#endif
          nfields++;
          break;
        default:
@@ -878,8 +1006,7 @@ struct_type (dip, thisdie, enddie, objfile)
     {
       TYPE_NFIELDS (type) = nfields;
       TYPE_FIELDS (type) = (struct field *)
-       obstack_alloc (&objfile -> type_obstack,
-                      sizeof (struct field) * nfields);
+       TYPE_ALLOC (type, sizeof (struct field) * nfields);
       /* Copy the saved-up fields into the field vector.  */
       for (n = nfields; list; list = list -> next)
        {
@@ -936,9 +1063,14 @@ read_structure_scope (dip, thisdie, enddie, objfile)
   type = struct_type (dip, thisdie, enddie, objfile);
   if (!(TYPE_FLAGS (type) & TYPE_FLAG_STUB))
     {
-      if ((sym = new_symbol (dip, objfile)) != NULL)
+      sym = new_symbol (dip, objfile);
+      if (sym != NULL)
        {
          SYMBOL_TYPE (sym) = type;
+         if (cu_language == language_cplus)
+           {
+             synthesize_typedef (dip, objfile, type);
+           }
        }
     }
 }
@@ -1087,14 +1219,10 @@ decode_subscr_data (scan, end)
          nexttype = decode_subscr_data (scan, end);
          if (nexttype != NULL)
            {
-             typep = (struct type *)
-               obstack_alloc (&current_objfile -> type_obstack,
-                              sizeof (struct type));
-             (void) memset (typep, 0, sizeof (struct type));
-             TYPE_OBJFILE (typep) = current_objfile;
+             typep = alloc_type (current_objfile);
              TYPE_CODE (typep) = TYPE_CODE_ARRAY;
              TYPE_LENGTH (typep) = TYPE_LENGTH (nexttype);
-             TYPE_LENGTH (typep) *= lowbound + highbound + 1;
+             TYPE_LENGTH (typep) *= (highbound - lowbound) + 1;
              TYPE_TARGET_TYPE (typep) = nexttype;
            }               
        }
@@ -1169,7 +1297,7 @@ dwarf_read_array_type (dip)
        {
          if ((utype = lookup_utype (dip -> die_ref)) == NULL)
            {
-             (void) alloc_utype (dip -> die_ref, type);
+             alloc_utype (dip -> die_ref, type);
            }
          else
            {
@@ -1208,7 +1336,7 @@ read_tag_pointer_type (dip)
   if ((utype = lookup_utype (dip -> die_ref)) == NULL)
     {
       utype = lookup_pointer_type (type);
-      (void) alloc_utype (dip -> die_ref, utype);
+      alloc_utype (dip -> die_ref, utype);
     }
   else
     {
@@ -1272,7 +1400,7 @@ read_subroutine_type (dip, thisdie, enddie)
       /* This is the first reference to one of these types.  Make
         a new one and place it in the user defined types. */
       ftype = lookup_function_type (type);
-      (void) alloc_utype (dip -> die_ref, ftype);
+      alloc_utype (dip -> die_ref, ftype);
     }
   else
     {
@@ -1319,9 +1447,14 @@ read_enumeration (dip, thisdie, enddie, objfile)
   struct symbol *sym;
   
   type = enum_type (dip, objfile);
-  if ((sym = new_symbol (dip, objfile)) != NULL)
+  sym = new_symbol (dip, objfile);
+  if (sym != NULL)
     {
       SYMBOL_TYPE (sym) = type;
+      if (cu_language == language_cplus)
+       {
+         synthesize_typedef (dip, objfile, type);
+       }
     }
 }
 
@@ -1420,13 +1553,14 @@ enum_type (dip, objfile)
            target_to_host (scan, TARGET_FT_LONG_SIZE (objfile), GET_SIGNED,
                            objfile);
          scan += TARGET_FT_LONG_SIZE (objfile);
-         list -> field.name = savestring (scan, strlen (scan));
+         list -> field.name = obsavestring (scan, strlen (scan),
+                                            &objfile -> type_obstack);
          scan += strlen (scan) + 1;
          nfields++;
          /* Handcraft a new symbol for this enum member. */
          sym = (struct symbol *) obstack_alloc (&objfile->symbol_obstack,
                                                 sizeof (struct symbol));
-         (void) memset (sym, 0, sizeof (struct symbol));
+         memset (sym, 0, sizeof (struct symbol));
          SYMBOL_NAME (sym) = create_name (list -> field.name,
                                           &objfile->symbol_obstack);
          SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
@@ -1436,7 +1570,7 @@ enum_type (dip, objfile)
          add_symbol_to_list (sym, list_in_scope);
        }
       /* Now create the vector of fields, and record how big it is. This is
-        where we reverse the order, by pulling the members of the list in
+        where we reverse the order, by pulling the members off the list in
         reverse order from how they were inserted.  If we have no fields
         (this is apparently possible in C++) then skip building a field
         vector. */
@@ -1507,6 +1641,57 @@ read_func_scope (dip, thisdie, enddie, objfile)
   list_in_scope = &file_symbols;
 }
 
+
+/*
+
+LOCAL FUNCTION
+
+       handle_producer -- process the AT_producer attribute
+
+DESCRIPTION
+
+       Perform any operations that depend on finding a particular
+       AT_producer attribute.
+
+ */
+
+static void
+handle_producer (producer)
+     char *producer;
+{
+
+  /* If this compilation unit was compiled with g++ or gcc, then set the
+     processing_gcc_compilation flag. */
+
+  processing_gcc_compilation =
+    STREQN (producer, GPLUS_PRODUCER, strlen (GPLUS_PRODUCER))
+      || STREQN (producer, GCC_PRODUCER, strlen (GCC_PRODUCER));
+
+  /* Select a demangling style if we can identify the producer and if
+     the current style is auto.  We leave the current style alone if it
+     is not auto.  We also leave the demangling style alone if we find a
+     gcc (cc1) producer, as opposed to a g++ (cc1plus) producer. */
+
+#if 1 /* Works, but is experimental.  -fnf */
+  if (AUTO_DEMANGLING)
+    {
+      if (STREQN (producer, GPLUS_PRODUCER, strlen (GPLUS_PRODUCER)))
+       {
+         set_demangling_style (GNU_DEMANGLING_STYLE_STRING);
+       }
+      else if (STREQN (producer, LCC_PRODUCER, strlen (LCC_PRODUCER)))
+       {
+         set_demangling_style (LUCID_DEMANGLING_STYLE_STRING);
+       }
+      else if (STREQN (producer, CFRONT_PRODUCER, strlen (CFRONT_PRODUCER)))
+       {
+         set_demangling_style (CFRONT_DEMANGLING_STYLE_STRING);
+       }
+    }
+#endif
+}
+
+
 /*
 
 LOCAL FUNCTION
@@ -1545,32 +1730,23 @@ read_file_scope (dip, thisdie, enddie, objfile)
       objfile -> ei.entry_file_lowpc = dip -> at_low_pc;
       objfile -> ei.entry_file_highpc = dip -> at_high_pc;
     }
+  set_cu_language (dip);
   if (dip -> at_producer != NULL)
     {
-      processing_gcc_compilation =
-       STREQN (dip -> at_producer, GCC_PRODUCER, strlen (GCC_PRODUCER));
+      handle_producer (dip -> at_producer);
     }
   numutypes = (enddie - thisdie) / 4;
   utypes = (struct type **) xmalloc (numutypes * sizeof (struct type *));
   back_to = make_cleanup (free, utypes);
-  (void) memset (utypes, 0, numutypes * sizeof (struct type *));
-  start_symtab (dip -> at_name, NULL, dip -> at_low_pc);
+  memset (utypes, 0, numutypes * sizeof (struct type *));
+  start_symtab (dip -> at_name, dip -> at_comp_dir, dip -> at_low_pc);
   decode_line_numbers (lnbase);
   process_dies (thisdie + dip -> die_length, enddie, objfile);
   symtab = end_symtab (dip -> at_high_pc, 0, 0, objfile);
-  /* FIXME:  The following may need to be expanded for other languages */
-  switch (dip -> at_language)
+  if (symtab != NULL)
     {
-      case LANG_C89:
-      case LANG_C:
-       symtab -> language = language_c;
-       break;
-      case LANG_C_PLUS_PLUS:
-       symtab -> language = language_cplus;
-       break;
-      default:
-       ;
-    }
+      symtab -> language = cu_language;
+    }      
   do_cleanups (back_to);
   utypes = NULL;
   numutypes = 0;
@@ -1639,6 +1815,7 @@ process_dies (thisdie, enddie, objfile)
            case TAG_lexical_block:
              read_lexical_block_scope (&di, thisdie, nextdie, objfile);
              break;
+           case TAG_class_type:
            case TAG_structure_type:
            case TAG_union_type:
              read_structure_scope (&di, thisdie, nextdie, objfile);
@@ -1656,7 +1833,7 @@ process_dies (thisdie, enddie, objfile)
              read_tag_pointer_type (&di);
              break;
            default:
-             (void) new_symbol (&di, objfile);
+             new_symbol (&di, objfile);
              break;
            }
        }
@@ -1917,12 +2094,14 @@ read_ofile_symtab (pst)
      unit, seek to the location in the file, and read in all the DIE's. */
 
   diecount = 0;
-  dbbase = xmalloc (DBLENGTH(pst));
+  dbsize = DBLENGTH (pst);
+  dbbase = xmalloc (dbsize);
   dbroff = DBROFF(pst);
   foffset = DBFOFF(pst) + dbroff;
-  baseaddr = pst -> addr;
+  base_section_offsets = pst->section_offsets;
+  baseaddr = ANOFFSET (pst->section_offsets, 0);
   if (bfd_seek (abfd, foffset, 0) ||
-      (bfd_read (dbbase, DBLENGTH(pst), 1, abfd) != DBLENGTH(pst)))
+      (bfd_read (dbbase, dbsize, 1, abfd) != dbsize))
     {
       free (dbbase);
       error ("can't read DWARF data");
@@ -1955,7 +2134,7 @@ read_ofile_symtab (pst)
       make_cleanup (free, lnbase);
     }
 
-  process_dies (dbbase, dbbase + DBLENGTH(pst), pst -> objfile);
+  process_dies (dbbase, dbbase + dbsize, pst -> objfile);
   do_cleanups (back_to);
   current_objfile = NULL;
   return (pst -> objfile -> symtabs);
@@ -1983,6 +2162,7 @@ psymtab_to_symtab_1 (pst)
      struct partial_symtab *pst;
 {
   int i;
+  struct cleanup *old_chain;
   
   if (pst != NULL)
     {
@@ -2015,6 +2195,8 @@ psymtab_to_symtab_1 (pst)
            }     
          if (DBLENGTH (pst))           /* Otherwise it's a dummy */
            {
+             buildsym_init ();
+             old_chain = make_cleanup (really_free_pendings, 0);
              pst -> symtab = read_ofile_symtab (pst);
              if (info_verbose)
                {
@@ -2023,6 +2205,7 @@ psymtab_to_symtab_1 (pst)
                  fflush (stdout);
                }
              sort_symtab_syms (pst -> symtab);
+             do_cleanups (old_chain);
            }
          pst -> readin = 1;
        }
@@ -2200,6 +2383,9 @@ DESCRIPTION
        add to a partial symbol table, finish filling in the die info
        and then add a partial symbol table entry for it.
 
+NOTES
+
+       The caller must ensure that the DIE has a valid name attribute.
 */
 
 static void
@@ -2243,22 +2429,22 @@ add_partial_symbol (dip, objfile)
                           objfile -> static_psymbols,
                           0);
       break;
+    case TAG_class_type:
     case TAG_structure_type:
     case TAG_union_type:
+    case TAG_enumeration_type:
       ADD_PSYMBOL_TO_LIST (dip -> at_name, strlen (dip -> at_name),
                           STRUCT_NAMESPACE, LOC_TYPEDEF,
                           objfile -> static_psymbols,
                           0);
-      break;
-    case TAG_enumeration_type:
-      if (dip -> at_name)
+      if (cu_language == language_cplus)
        {
+         /* For C++, these implicitly act as typedefs as well. */
          ADD_PSYMBOL_TO_LIST (dip -> at_name, strlen (dip -> at_name),
-                              STRUCT_NAMESPACE, LOC_TYPEDEF,
+                              VAR_NAMESPACE, LOC_TYPEDEF,
                               objfile -> static_psymbols,
                               0);
        }
-      add_enum_psymbol (dip, objfile);
       break;
     }
 }
@@ -2273,15 +2459,50 @@ DESCRIPTION
 
        Process the DIE's within a single compilation unit, looking for
        interesting DIE's that contribute to the partial symbol table entry
-       for this compilation unit.  Since we cannot follow any sibling
-       chains without reading the complete DIE info for every DIE,
-       it is probably faster to just sequentially check each one to
-       see if it is one of the types we are interested in, and if so,
-       then extract all the attributes info and generate a partial
-       symbol table entry.
+       for this compilation unit.
 
 NOTES
 
+       There are some DIE's that may appear both at file scope and within
+       the scope of a function.  We are only interested in the ones at file
+       scope, and the only way to tell them apart is to keep track of the
+       scope.  For example, consider the test case:
+
+               static int i;
+               main () { int j; }
+
+       for which the relevant DWARF segment has the structure:
+       
+               0x51:
+               0x23   global subrtn   sibling     0x9b
+                                      name        main
+                                      fund_type   FT_integer
+                                      low_pc      0x800004cc
+                                      high_pc     0x800004d4
+                                           
+               0x74:
+               0x23   local var       sibling     0x97
+                                      name        j
+                                      fund_type   FT_integer
+                                      location    OP_BASEREG 0xe
+                                                  OP_CONST 0xfffffffc
+                                                  OP_ADD
+               0x97:
+               0x4         
+               
+               0x9b:
+               0x1d   local var       sibling     0xb8
+                                      name        i
+                                      fund_type   FT_integer
+                                      location    OP_ADDR 0x800025dc
+                                           
+               0xb8:
+               0x4         
+
+       We want to include the symbol 'i' in the partial symbol table, but
+       not the symbol 'j'.  In essence, we want to skip all the dies within
+       the scope of a TAG_global_subroutine DIE.
+
        Don't attempt to add anonymous structures or unions since they have
        no name.  Anonymous enumerations however are processed, because we
        want to extract their member names (the check for a tag name is
@@ -2299,6 +2520,7 @@ scan_partial_symbols (thisdie, enddie, objfile)
      struct objfile *objfile;
 {
   char *nextdie;
+  char *temp;
   struct dieinfo di;
   
   while (thisdie < enddie)
@@ -2317,6 +2539,28 @@ scan_partial_symbols (thisdie, enddie, objfile)
            {
            case TAG_global_subroutine:
            case TAG_subroutine:
+             completedieinfo (&di, objfile);
+             if (di.at_name && (di.has_at_low_pc || di.at_location))
+               {
+                 add_partial_symbol (&di, objfile);
+                 /* If there is a sibling attribute, adjust the nextdie
+                    pointer to skip the entire scope of the subroutine.
+                    Apply some sanity checking to make sure we don't 
+                    overrun or underrun the range of remaining DIE's */
+                 if (di.at_sibling != 0)
+                   {
+                     temp = dbbase + di.at_sibling - dbroff;
+                     if ((temp < thisdie) || (temp >= enddie))
+                       {
+                         dwarfwarn ("reference to DIE (0x%x) outside compilation unit", di.at_sibling);
+                       }
+                     else
+                       {
+                         nextdie = temp;
+                       }
+                   }
+               }
+             break;
            case TAG_global_variable:
            case TAG_local_variable:
              completedieinfo (&di, objfile);
@@ -2326,6 +2570,7 @@ scan_partial_symbols (thisdie, enddie, objfile)
                }
              break;
            case TAG_typedef:
+           case TAG_class_type:
            case TAG_structure_type:
            case TAG_union_type:
              completedieinfo (&di, objfile);
@@ -2336,7 +2581,11 @@ scan_partial_symbols (thisdie, enddie, objfile)
              break;
            case TAG_enumeration_type:
              completedieinfo (&di, objfile);
-             add_partial_symbol (&di, objfile);
+             if (di.at_name)
+               {
+                 add_partial_symbol (&di, objfile);
+               }
+             add_enum_psymbol (&di, objfile);
              break;
            }
        }
@@ -2417,6 +2666,7 @@ scan_compilation_units (filename, thisdie, enddie, dbfoff, lnoffset, objfile)
       else
        {
          completedieinfo (&di, objfile);
+         set_cu_language (&di);
          if (di.at_sibling != 0)
            {
              nextdie = dbbase + di.at_sibling - dbroff;
@@ -2431,8 +2681,8 @@ scan_compilation_units (filename, thisdie, enddie, dbfoff, lnoffset, objfile)
 
          /* First allocate a new partial symbol table structure */
 
-         pst = start_psymtab_common (objfile, baseaddr, di.at_name,
-                                     di.at_low_pc,
+         pst = start_psymtab_common (objfile, base_section_offsets,
+                                     di.at_name, di.at_low_pc,
                                      objfile -> global_psymbols.next,
                                      objfile -> static_psymbols.next);
 
@@ -2493,8 +2743,9 @@ new_symbol (dip, objfile)
     {
       sym = (struct symbol *) obstack_alloc (&objfile -> symbol_obstack,
                                             sizeof (struct symbol));
-      (void) memset (sym, 0, sizeof (struct symbol));
-      SYMBOL_NAME (sym) = create_name (dip -> at_name, &objfile->symbol_obstack);
+      memset (sym, 0, sizeof (struct symbol));
+      SYMBOL_NAME (sym) = create_name (dip -> at_name,
+                                      &objfile->symbol_obstack);
       /* default assumptions */
       SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
       SYMBOL_CLASS (sym) = LOC_STATIC;
@@ -2567,6 +2818,7 @@ new_symbol (dip, objfile)
          /* From varargs functions; gdb doesn't seem to have any interest in
             this information, so just ignore it for now. (FIXME?) */
          break;
+       case TAG_class_type:
        case TAG_structure_type:
        case TAG_union_type:
        case TAG_enumeration_type:
@@ -2591,6 +2843,50 @@ new_symbol (dip, objfile)
 
 /*
 
+LOCAL FUNCTION
+
+       synthesize_typedef -- make a symbol table entry for a "fake" typedef
+
+SYNOPSIS
+
+       static void synthesize_typedef (struct dieinfo *dip,
+                                       struct objfile *objfile,
+                                       struct type *type);
+
+DESCRIPTION
+
+       Given a pointer to a DWARF information entry, synthesize a typedef
+       for the name in the DIE, using the specified type.
+
+       This is used for C++ class, structs, unions, and enumerations to
+       set up the tag name as a type.
+
+ */
+
+static void
+synthesize_typedef (dip, objfile, type)
+     struct dieinfo *dip;
+     struct objfile *objfile;
+     struct type *type;
+{
+  struct symbol *sym = NULL;
+  
+  if (dip -> at_name != NULL)
+    {
+      sym = (struct symbol *)
+       obstack_alloc (&objfile -> symbol_obstack, sizeof (struct symbol));
+      memset (sym, 0, sizeof (struct symbol));
+      SYMBOL_NAME (sym) = create_name (dip -> at_name,
+                                      &objfile->symbol_obstack);
+      SYMBOL_TYPE (sym) = type;
+      SYMBOL_CLASS (sym) = LOC_TYPEDEF;
+      SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+      add_symbol_to_list (sym, list_in_scope);
+    }
+}
+
+/*
+
 LOCAL FUNCTION
 
        decode_mod_fund_type -- decode a modified fundamental type
@@ -2691,7 +2987,7 @@ LOCAL FUNCTION
 
 SYNOPSIS
 
-       static struct type *decode_modified_type (unsigned char *modifiers,
+       static struct type *decode_modified_type (char *modifiers,
            unsigned short modcount, int mtype)
 
 DESCRIPTION
@@ -2725,14 +3021,14 @@ BUGS
 
 static struct type *
 decode_modified_type (modifiers, modcount, mtype)
-     unsigned char *modifiers;
+     char *modifiers;
      unsigned int modcount;
      int mtype;
 {
   struct type *typep = NULL;
   unsigned short fundtype;
   DIE_REF die_ref;
-  unsigned char modifier;
+  char modifier;
   int nbytes;
   
   if (modcount == 0)
@@ -2779,9 +3075,11 @@ decode_modified_type (modifiers, modcount, mtype)
            SQUAWK (("type modifier 'volatile' ignored"));      /* FIXME */
            break;
          default:
-           if (!(MOD_lo_user <= modifier && modifier <= MOD_hi_user))
+           if (!(MOD_lo_user <= (unsigned char) modifier
+                 && (unsigned char) modifier <= MOD_hi_user))
              {
-               SQUAWK (("unknown type modifier %u", modifier));
+               SQUAWK (("unknown type modifier %u",
+                        (unsigned char) modifier));
              }
            break;
        }
@@ -2949,7 +3247,7 @@ create_name (name, obstackp)
 
   length = strlen (name) + 1;
   newname = (char *) obstack_alloc (obstackp, length);
-  (void) strcpy (newname, name);
+  strcpy (newname, name);
   return (newname);
 }
 
@@ -2999,6 +3297,12 @@ NOTES
        that if a padding DIE is used for alignment and the amount needed is
        less than SIZEOF_DIE_LENGTH, then the padding DIE has to be big
        enough to align to the next alignment boundry.
+
+       We do some basic sanity checking here, such as verifying that the
+       length of the die would not cause it to overrun the recorded end of
+       the buffer holding the DIE info.  If we find a DIE that is either
+       too small or too large, we force it's length to zero which should
+       cause the caller to take appropriate action.
  */
 
 static void
@@ -3008,14 +3312,16 @@ basicdieinfo (dip, diep, objfile)
      struct objfile *objfile;
 {
   curdie = dip;
-  (void) memset (dip, 0, sizeof (struct dieinfo));
+  memset (dip, 0, sizeof (struct dieinfo));
   dip -> die = diep;
   dip -> die_ref = dbroff + (diep - dbbase);
   dip -> die_length = target_to_host (diep, SIZEOF_DIE_LENGTH, GET_UNSIGNED,
                                      objfile);
-  if (dip -> die_length < SIZEOF_DIE_LENGTH)
+  if ((dip -> die_length < SIZEOF_DIE_LENGTH) ||
+      ((diep + dip -> die_length) > (dbbase + dbsize)))
     {
       dwarfwarn ("malformed DIE, bad length (%d bytes)", dip -> die_length);
+      dip -> die_length = 0;
     }
   else if (dip -> die_length < (SIZEOF_DIE_LENGTH + SIZEOF_DIE_TAG))
     {
@@ -3100,10 +3406,6 @@ completedieinfo (dip, objfile)
          dip -> at_bit_offset = target_to_host (diep, nbytes, GET_UNSIGNED,
                                                 objfile);
          break;
-       case AT_visibility:
-         dip -> at_visibility = target_to_host (diep, nbytes, GET_UNSIGNED,
-                                                objfile);
-         break;
        case AT_sibling:
          dip -> at_sibling = target_to_host (diep, nbytes, GET_UNSIGNED,
                                              objfile);
@@ -3135,6 +3437,7 @@ completedieinfo (dip, objfile)
        case AT_byte_size:
          dip -> at_byte_size = target_to_host (diep, nbytes, GET_UNSIGNED,
                                                objfile);
+         dip -> has_at_byte_size = 1;
          break;
        case AT_bit_size:
          dip -> at_bit_size = target_to_host (diep, nbytes, GET_UNSIGNED,
@@ -3148,10 +3451,6 @@ completedieinfo (dip, objfile)
          dip -> at_discr = target_to_host (diep, nbytes, GET_UNSIGNED,
                                            objfile);
          break;
-       case AT_import:
-         dip -> at_import = target_to_host (diep, nbytes, GET_UNSIGNED,
-                                            objfile);
-         break;
        case AT_location:
          dip -> at_location = diep;
          break;
@@ -3182,15 +3481,21 @@ completedieinfo (dip, objfile)
          dip -> at_name = diep;
          break;
        case AT_comp_dir:
-         dip -> at_comp_dir = diep;
+         /* For now, ignore any "hostname:" portion, since gdb doesn't
+            know how to deal with it.  (FIXME). */
+         dip -> at_comp_dir = strrchr (diep, ':');
+         if (dip -> at_comp_dir != NULL)
+           {
+             dip -> at_comp_dir++;
+           }
+         else
+           {
+             dip -> at_comp_dir = diep;
+           }
          break;
        case AT_producer:
          dip -> at_producer = diep;
          break;
-       case AT_frame_base:
-         dip -> at_frame_base = target_to_host (diep, nbytes, GET_UNSIGNED,
-                                                objfile);
-         break;
        case AT_start_scope:
          dip -> at_start_scope = target_to_host (diep, nbytes, GET_UNSIGNED,
                                                  objfile);
This page took 0.035351 seconds and 4 git commands to generate.