* i386b-nat.c: Comment changes.
[deliverable/binutils-gdb.git] / gdb / dwarfread.c
index 6844813fb0486aeff15e35fbdd7b80f0e8c22556..2b13ad6d334bf0d67035c987575dab3c2b823977 100644 (file)
@@ -41,10 +41,6 @@ other things to work on, if you get bored. :-)
 */
 
 #include "defs.h"
-#include <varargs.h>
-#include <fcntl.h>
-#include <string.h>
-
 #include "bfd.h"
 #include "symtab.h"
 #include "gdbtypes.h"
@@ -55,6 +51,18 @@ other things to work on, if you get bored. :-)
 #include "buildsym.h"
 #include "demangle.h"
 
+#include <varargs.h>
+#include <fcntl.h>
+#include <string.h>
+#ifndef        NO_SYS_FILE
+#include <sys/file.h>
+#endif
+
+/* FIXME -- convert this to SEEK_SET a la POSIX, move to config files.  */
+#ifndef L_SET
+#define L_SET 0
+#endif
+
 #ifdef MAINTENANCE     /* Define to 1 to compile in some maintenance stuff */
 #define SQUAWK(stuff) dwarfwarn stuff
 #else
@@ -212,6 +220,7 @@ 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 */
@@ -252,10 +261,10 @@ static struct section_offsets *base_section_offsets;
  */
 
 struct dwfinfo {
-  int dbfoff;          /* Absolute file offset to start of .debug section */
+  file_ptr dbfoff;     /* Absolute file offset to start of .debug section */
   int dbroff;          /* Relative offset from start of .debug section */
   int dblength;                /* Size of the chunk of DIE's being examined */
-  int lnfoff;          /* Absolute file offset to line table fragment */
+  file_ptr lnfoff;     /* Absolute file offset to line table fragment */
 };
 
 #define DBFOFF(p) (((struct dwfinfo *)((p)->read_symtab_private))->dbfoff)
@@ -300,6 +309,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.  */
 
@@ -332,8 +350,8 @@ static void
 scan_partial_symbols PARAMS ((char *, char *, struct objfile *));
 
 static void
-scan_compilation_units PARAMS ((char *, char *, char *, unsigned int,
-                               unsigned int, struct objfile *));
+scan_compilation_units PARAMS ((char *, char *, file_ptr,
+                               file_ptr, struct objfile *));
 
 static void
 add_partial_symbol PARAMS ((struct dieinfo *, struct objfile *));
@@ -417,6 +435,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 *));
 
@@ -424,6 +446,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
@@ -432,18 +506,17 @@ GLOBAL FUNCTION
 
 SYNOPSIS
 
-       void dwarf_build_psymtabs (int desc, char *filename, 
+       void dwarf_build_psymtabs (struct objfile *objfile,
             struct section_offsets *section_offsets,
-            int mainline, unsigned int dbfoff, unsigned int dbsize,
-            unsigned int lnoffset, unsigned int lnsize,
-            struct objfile *objfile)
+            int mainline, file_ptr dbfoff, unsigned int dbfsize,
+            file_ptr lnoffset, unsigned int lnsize)
 
 DESCRIPTION
 
        This function is called upon to build partial symtabs from files
        containing DIE's (Dwarf Information Entries) and DWARF line numbers.
 
-       It is passed a file descriptor for an open file containing the DIES
+       It is passed a bfd* containing the DIES
        and line number information, the corresponding filename for that
        file, a base address for relocating the symbols, a flag indicating
        whether or not this debugging information is from a "main symbol
@@ -458,28 +531,28 @@ RETURNS
  */
 
 void
-dwarf_build_psymtabs (desc, filename, section_offsets, mainline, dbfoff, dbsize,
-                     lnoffset, lnsize, objfile)
-     int desc;
-     char *filename;
+dwarf_build_psymtabs (objfile, section_offsets, mainline, dbfoff, dbfsize,
+                     lnoffset, lnsize)
+     struct objfile *objfile;
      struct section_offsets *section_offsets;
      int mainline;
-     unsigned int dbfoff;
-     unsigned int dbsize;
-     unsigned int lnoffset;
+     file_ptr dbfoff;
+     unsigned int dbfsize;
+     file_ptr lnoffset;
      unsigned int lnsize;
-     struct objfile *objfile;
 {
+  bfd *abfd = objfile->obfd;
   struct cleanup *back_to;
   
   current_objfile = objfile;
+  dbsize = dbfsize;
   dbbase = xmalloc (dbsize);
   dbroff = 0;
-  if ((lseek (desc, dbfoff, 0) != dbfoff) ||
-      (read (desc, dbbase, dbsize) != dbsize))
+  if ((bfd_seek (abfd, dbfoff, L_SET) != 0) ||
+      (bfd_read (dbbase, dbsize, 1, abfd) != dbsize))
     {
       free (dbbase);
-      error ("can't read DWARF data from '%s'", filename);
+      error ("can't read DWARF data from '%s'", bfd_get_filename (abfd));
     }
   back_to = make_cleanup (free, dbbase);
   
@@ -502,8 +575,7 @@ dwarf_build_psymtabs (desc, filename, section_offsets, mainline, dbfoff, dbsize,
      table entry for each one.  Save enough information about each compilation
      unit to locate the full DWARF information later. */
   
-  scan_compilation_units (filename, dbbase, dbbase + dbsize,
-                         dbfoff, lnoffset, objfile);
+  scan_compilation_units (dbbase, dbbase + dbsize, dbfoff, lnoffset, objfile);
   
   do_cleanups (back_to);
   current_objfile = NULL;
@@ -818,6 +890,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";
@@ -830,7 +906,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
@@ -935,8 +1011,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)
        {
@@ -993,9 +1068,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);
+           }
        }
     }
 }
@@ -1372,9 +1452,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);
+       }
     }
 }
 
@@ -1650,6 +1735,7 @@ 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)
     {
       handle_producer (dip -> at_producer);
@@ -1664,19 +1750,7 @@ read_file_scope (dip, thisdie, enddie, objfile)
   symtab = end_symtab (dip -> at_high_pc, 0, 0, objfile);
   if (symtab != NULL)
     {
-      /* FIXME:  The following may need to be expanded for other languages */
-      switch (dip -> at_language)
-       {
-         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;
@@ -1746,6 +1820,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);
@@ -2013,7 +2088,7 @@ read_ofile_symtab (pst)
 {
   struct cleanup *back_to;
   unsigned long lnsize;
-  int foffset;
+  file_ptr foffset;
   bfd *abfd;
   char lnsizedata[SIZEOF_LINETBL_LENGTH];
 
@@ -2024,13 +2099,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;
   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)))
+  if (bfd_seek (abfd, foffset, L_SET) ||
+      (bfd_read (dbbase, dbsize, 1, abfd) != dbsize))
     {
       free (dbbase);
       error ("can't read DWARF data");
@@ -2045,7 +2121,7 @@ read_ofile_symtab (pst)
   lnbase = NULL;
   if (LNFOFF (pst))
     {
-      if (bfd_seek (abfd, LNFOFF (pst), 0) ||
+      if (bfd_seek (abfd, LNFOFF (pst), L_SET) ||
          (bfd_read ((PTR) lnsizedata, sizeof (lnsizedata), 1, abfd) !=
           sizeof (lnsizedata)))
        {
@@ -2054,7 +2130,7 @@ read_ofile_symtab (pst)
       lnsize = target_to_host (lnsizedata, SIZEOF_LINETBL_LENGTH,
                               GET_UNSIGNED, pst -> objfile);
       lnbase = xmalloc (lnsize);
-      if (bfd_seek (abfd, LNFOFF (pst), 0) ||
+      if (bfd_seek (abfd, LNFOFF (pst), L_SET) ||
          (bfd_read (lnbase, lnsize, 1, abfd) != lnsize))
        {
          free (lnbase);
@@ -2063,7 +2139,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);
@@ -2312,6 +2388,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
@@ -2355,22 +2434,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;
     }
 }
@@ -2496,6 +2575,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);
@@ -2506,7 +2586,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;
            }
        }
@@ -2558,12 +2642,11 @@ RETURNS
  */
 
 static void
-scan_compilation_units (filename, thisdie, enddie, dbfoff, lnoffset, objfile)
-     char *filename;
+scan_compilation_units (thisdie, enddie, dbfoff, lnoffset, objfile)
      char *thisdie;
      char *enddie;
-     unsigned int dbfoff;
-     unsigned int lnoffset;
+     file_ptr dbfoff;
+     file_ptr lnoffset;
      struct objfile *objfile;
 {
   char *nextdie;
@@ -2571,7 +2654,7 @@ scan_compilation_units (filename, thisdie, enddie, dbfoff, lnoffset, objfile)
   struct partial_symtab *pst;
   int culength;
   int curoff;
-  int curlnoffset;
+  file_ptr curlnoffset;
 
   while (thisdie < enddie)
     {
@@ -2587,6 +2670,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;
@@ -2601,8 +2685,8 @@ scan_compilation_units (filename, thisdie, enddie, dbfoff, lnoffset, objfile)
 
          /* First allocate a new partial symbol table structure */
 
-         pst = start_psymtab_common (objfile, base_section_offsets, 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);
 
@@ -2664,7 +2748,8 @@ new_symbol (dip, objfile)
       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_NAME (sym) = create_name (dip -> at_name,
+                                      &objfile->symbol_obstack);
       /* default assumptions */
       SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
       SYMBOL_CLASS (sym) = LOC_STATIC;
@@ -2737,6 +2822,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:
@@ -2761,6 +2847,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
@@ -3171,6 +3301,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
@@ -3185,9 +3321,11 @@ basicdieinfo (dip, diep, objfile)
   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))
     {
This page took 0.03227 seconds and 4 git commands to generate.