OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.0/] [gdb/] [dwarf2read.c] - Diff between revs 105 and 1765

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 105 Rev 1765
/* DWARF 2 debugging format support for GDB.
/* DWARF 2 debugging format support for GDB.
   Copyright 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
   Copyright 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
 
 
   Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology,
   Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology,
   Inc.  with support from Florida State University (under contract
   Inc.  with support from Florida State University (under contract
   with the Ada Joint Program Office), and Silicon Graphics, Inc.
   with the Ada Joint Program Office), and Silicon Graphics, Inc.
   Initial contribution by Brent Benson, Harris Computer Systems, Inc.,
   Initial contribution by Brent Benson, Harris Computer Systems, Inc.,
   based on Fred Fish's (Cygnus Support) implementation of DWARF 1
   based on Fred Fish's (Cygnus Support) implementation of DWARF 1
   support in dwarfread.c
   support in dwarfread.c
 
 
   This file is part of GDB.
   This file is part of GDB.
 
 
   This program is free software; you can redistribute it and/or modify
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or (at
   the Free Software Foundation; either version 2 of the License, or (at
   your option) any later version.
   your option) any later version.
 
 
   This program is distributed in the hope that it will be useful, but
   This program is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   General Public License for more details.
   General Public License for more details.
 
 
   You should have received a copy of the GNU General Public License
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330,
   Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.  */
   Boston, MA 02111-1307, USA.  */
 
 
#include "defs.h"
#include "defs.h"
#include "bfd.h"
#include "bfd.h"
#include "symtab.h"
#include "symtab.h"
#include "gdbtypes.h"
#include "gdbtypes.h"
#include "symfile.h"
#include "symfile.h"
#include "objfiles.h"
#include "objfiles.h"
#include "elf/dwarf2.h"
#include "elf/dwarf2.h"
#include "buildsym.h"
#include "buildsym.h"
#include "demangle.h"
#include "demangle.h"
#include "expression.h"
#include "expression.h"
#include "language.h"
#include "language.h"
#include "complaints.h"
#include "complaints.h"
 
 
#include <fcntl.h>
#include <fcntl.h>
#include "gdb_string.h"
#include "gdb_string.h"
#include <sys/types.h>
#include <sys/types.h>
 
 
/* .debug_info header for a compilation unit
/* .debug_info header for a compilation unit
   Because of alignment constraints, this structure has padding and cannot
   Because of alignment constraints, this structure has padding and cannot
   be mapped directly onto the beginning of the .debug_info section.  */
   be mapped directly onto the beginning of the .debug_info section.  */
typedef struct comp_unit_header
typedef struct comp_unit_header
  {
  {
    unsigned int length;        /* length of the .debug_info
    unsigned int length;        /* length of the .debug_info
                                   contribution */
                                   contribution */
    unsigned short version;     /* version number -- 2 for DWARF
    unsigned short version;     /* version number -- 2 for DWARF
                                   version 2 */
                                   version 2 */
    unsigned int abbrev_offset; /* offset into .debug_abbrev section */
    unsigned int abbrev_offset; /* offset into .debug_abbrev section */
    unsigned char addr_size;    /* byte size of an address -- 4 */
    unsigned char addr_size;    /* byte size of an address -- 4 */
  }
  }
_COMP_UNIT_HEADER;
_COMP_UNIT_HEADER;
#define _ACTUAL_COMP_UNIT_HEADER_SIZE 11
#define _ACTUAL_COMP_UNIT_HEADER_SIZE 11
 
 
/* .debug_pubnames header
/* .debug_pubnames header
   Because of alignment constraints, this structure has padding and cannot
   Because of alignment constraints, this structure has padding and cannot
   be mapped directly onto the beginning of the .debug_info section.  */
   be mapped directly onto the beginning of the .debug_info section.  */
typedef struct pubnames_header
typedef struct pubnames_header
  {
  {
    unsigned int length;        /* length of the .debug_pubnames
    unsigned int length;        /* length of the .debug_pubnames
                                   contribution  */
                                   contribution  */
    unsigned char version;      /* version number -- 2 for DWARF
    unsigned char version;      /* version number -- 2 for DWARF
                                   version 2 */
                                   version 2 */
    unsigned int info_offset;   /* offset into .debug_info section */
    unsigned int info_offset;   /* offset into .debug_info section */
    unsigned int info_size;     /* byte size of .debug_info section
    unsigned int info_size;     /* byte size of .debug_info section
                                   portion */
                                   portion */
  }
  }
_PUBNAMES_HEADER;
_PUBNAMES_HEADER;
#define _ACTUAL_PUBNAMES_HEADER_SIZE 13
#define _ACTUAL_PUBNAMES_HEADER_SIZE 13
 
 
/* .debug_pubnames header
/* .debug_pubnames header
   Because of alignment constraints, this structure has padding and cannot
   Because of alignment constraints, this structure has padding and cannot
   be mapped directly onto the beginning of the .debug_info section.  */
   be mapped directly onto the beginning of the .debug_info section.  */
typedef struct aranges_header
typedef struct aranges_header
  {
  {
    unsigned int length;        /* byte len of the .debug_aranges
    unsigned int length;        /* byte len of the .debug_aranges
                                   contribution */
                                   contribution */
    unsigned short version;     /* version number -- 2 for DWARF
    unsigned short version;     /* version number -- 2 for DWARF
                                   version 2 */
                                   version 2 */
    unsigned int info_offset;   /* offset into .debug_info section */
    unsigned int info_offset;   /* offset into .debug_info section */
    unsigned char addr_size;    /* byte size of an address */
    unsigned char addr_size;    /* byte size of an address */
    unsigned char seg_size;     /* byte size of segment descriptor */
    unsigned char seg_size;     /* byte size of segment descriptor */
  }
  }
_ARANGES_HEADER;
_ARANGES_HEADER;
#define _ACTUAL_ARANGES_HEADER_SIZE 12
#define _ACTUAL_ARANGES_HEADER_SIZE 12
 
 
/* .debug_line statement program prologue
/* .debug_line statement program prologue
   Because of alignment constraints, this structure has padding and cannot
   Because of alignment constraints, this structure has padding and cannot
   be mapped directly onto the beginning of the .debug_info section.  */
   be mapped directly onto the beginning of the .debug_info section.  */
typedef struct statement_prologue
typedef struct statement_prologue
  {
  {
    unsigned int total_length;  /* byte length of the statement
    unsigned int total_length;  /* byte length of the statement
                                   information */
                                   information */
    unsigned short version;     /* version number -- 2 for DWARF
    unsigned short version;     /* version number -- 2 for DWARF
                                   version 2 */
                                   version 2 */
    unsigned int prologue_length;       /* # bytes between prologue &
    unsigned int prologue_length;       /* # bytes between prologue &
                                           stmt program */
                                           stmt program */
    unsigned char minimum_instruction_length;   /* byte size of
    unsigned char minimum_instruction_length;   /* byte size of
                                                   smallest instr */
                                                   smallest instr */
    unsigned char default_is_stmt;      /* initial value of is_stmt
    unsigned char default_is_stmt;      /* initial value of is_stmt
                                           register */
                                           register */
    char line_base;
    char line_base;
    unsigned char line_range;
    unsigned char line_range;
    unsigned char opcode_base;  /* number assigned to first special
    unsigned char opcode_base;  /* number assigned to first special
                                   opcode */
                                   opcode */
    unsigned char *standard_opcode_lengths;
    unsigned char *standard_opcode_lengths;
  }
  }
_STATEMENT_PROLOGUE;
_STATEMENT_PROLOGUE;
 
 
/* offsets and sizes of debugging sections */
/* offsets and sizes of debugging sections */
 
 
static file_ptr dwarf_info_offset;
static file_ptr dwarf_info_offset;
static file_ptr dwarf_abbrev_offset;
static file_ptr dwarf_abbrev_offset;
static file_ptr dwarf_line_offset;
static file_ptr dwarf_line_offset;
static file_ptr dwarf_pubnames_offset;
static file_ptr dwarf_pubnames_offset;
static file_ptr dwarf_aranges_offset;
static file_ptr dwarf_aranges_offset;
static file_ptr dwarf_loc_offset;
static file_ptr dwarf_loc_offset;
static file_ptr dwarf_macinfo_offset;
static file_ptr dwarf_macinfo_offset;
static file_ptr dwarf_str_offset;
static file_ptr dwarf_str_offset;
 
 
static unsigned int dwarf_info_size;
static unsigned int dwarf_info_size;
static unsigned int dwarf_abbrev_size;
static unsigned int dwarf_abbrev_size;
static unsigned int dwarf_line_size;
static unsigned int dwarf_line_size;
static unsigned int dwarf_pubnames_size;
static unsigned int dwarf_pubnames_size;
static unsigned int dwarf_aranges_size;
static unsigned int dwarf_aranges_size;
static unsigned int dwarf_loc_size;
static unsigned int dwarf_loc_size;
static unsigned int dwarf_macinfo_size;
static unsigned int dwarf_macinfo_size;
static unsigned int dwarf_str_size;
static unsigned int dwarf_str_size;
 
 
/* names of the debugging sections */
/* names of the debugging sections */
 
 
#define INFO_SECTION     ".debug_info"
#define INFO_SECTION     ".debug_info"
#define ABBREV_SECTION   ".debug_abbrev"
#define ABBREV_SECTION   ".debug_abbrev"
#define LINE_SECTION     ".debug_line"
#define LINE_SECTION     ".debug_line"
#define PUBNAMES_SECTION ".debug_pubnames"
#define PUBNAMES_SECTION ".debug_pubnames"
#define ARANGES_SECTION  ".debug_aranges"
#define ARANGES_SECTION  ".debug_aranges"
#define LOC_SECTION      ".debug_loc"
#define LOC_SECTION      ".debug_loc"
#define MACINFO_SECTION  ".debug_macinfo"
#define MACINFO_SECTION  ".debug_macinfo"
#define STR_SECTION      ".debug_str"
#define STR_SECTION      ".debug_str"
 
 
/* local data types */
/* local data types */
 
 
/* The data in a compilation unit header looks like this.  */
/* The data in a compilation unit header looks like this.  */
struct comp_unit_head
struct comp_unit_head
  {
  {
    unsigned int length;
    unsigned int length;
    short version;
    short version;
    unsigned int abbrev_offset;
    unsigned int abbrev_offset;
    unsigned char addr_size;
    unsigned char addr_size;
  };
  };
 
 
/* The data in the .debug_line statement prologue looks like this.  */
/* The data in the .debug_line statement prologue looks like this.  */
struct line_head
struct line_head
  {
  {
    unsigned int total_length;
    unsigned int total_length;
    unsigned short version;
    unsigned short version;
    unsigned int prologue_length;
    unsigned int prologue_length;
    unsigned char minimum_instruction_length;
    unsigned char minimum_instruction_length;
    unsigned char default_is_stmt;
    unsigned char default_is_stmt;
    int line_base;
    int line_base;
    unsigned char line_range;
    unsigned char line_range;
    unsigned char opcode_base;
    unsigned char opcode_base;
    unsigned char *standard_opcode_lengths;
    unsigned char *standard_opcode_lengths;
  };
  };
 
 
/* When we construct a partial symbol table entry we only
/* When we construct a partial symbol table entry we only
   need this much information. */
   need this much information. */
struct partial_die_info
struct partial_die_info
  {
  {
    enum dwarf_tag tag;
    enum dwarf_tag tag;
    unsigned char has_children;
    unsigned char has_children;
    unsigned char is_external;
    unsigned char is_external;
    unsigned char is_declaration;
    unsigned char is_declaration;
    unsigned char has_type;
    unsigned char has_type;
    unsigned int offset;
    unsigned int offset;
    unsigned int abbrev;
    unsigned int abbrev;
    char *name;
    char *name;
    CORE_ADDR lowpc;
    CORE_ADDR lowpc;
    CORE_ADDR highpc;
    CORE_ADDR highpc;
    struct dwarf_block *locdesc;
    struct dwarf_block *locdesc;
    unsigned int language;
    unsigned int language;
    char *sibling;
    char *sibling;
  };
  };
 
 
/* This data structure holds the information of an abbrev. */
/* This data structure holds the information of an abbrev. */
struct abbrev_info
struct abbrev_info
  {
  {
    unsigned int number;        /* number identifying abbrev */
    unsigned int number;        /* number identifying abbrev */
    enum dwarf_tag tag;         /* dwarf tag */
    enum dwarf_tag tag;         /* dwarf tag */
    int has_children;           /* boolean */
    int has_children;           /* boolean */
    unsigned int num_attrs;     /* number of attributes */
    unsigned int num_attrs;     /* number of attributes */
    struct attr_abbrev *attrs;  /* an array of attribute descriptions */
    struct attr_abbrev *attrs;  /* an array of attribute descriptions */
    struct abbrev_info *next;   /* next in chain */
    struct abbrev_info *next;   /* next in chain */
  };
  };
 
 
struct attr_abbrev
struct attr_abbrev
  {
  {
    enum dwarf_attribute name;
    enum dwarf_attribute name;
    enum dwarf_form form;
    enum dwarf_form form;
  };
  };
 
 
/* This data structure holds a complete die structure. */
/* This data structure holds a complete die structure. */
struct die_info
struct die_info
  {
  {
    enum dwarf_tag tag;         /* Tag indicating type of die */
    enum dwarf_tag tag;         /* Tag indicating type of die */
    unsigned short has_children;        /* Does the die have children */
    unsigned short has_children;        /* Does the die have children */
    unsigned int abbrev;        /* Abbrev number */
    unsigned int abbrev;        /* Abbrev number */
    unsigned int offset;        /* Offset in .debug_info section */
    unsigned int offset;        /* Offset in .debug_info section */
    unsigned int num_attrs;     /* Number of attributes */
    unsigned int num_attrs;     /* Number of attributes */
    struct attribute *attrs;    /* An array of attributes */
    struct attribute *attrs;    /* An array of attributes */
    struct die_info *next_ref;  /* Next die in ref hash table */
    struct die_info *next_ref;  /* Next die in ref hash table */
    struct die_info *next;      /* Next die in linked list */
    struct die_info *next;      /* Next die in linked list */
    struct type *type;          /* Cached type information */
    struct type *type;          /* Cached type information */
  };
  };
 
 
/* Attributes have a name and a value */
/* Attributes have a name and a value */
struct attribute
struct attribute
  {
  {
    enum dwarf_attribute name;
    enum dwarf_attribute name;
    enum dwarf_form form;
    enum dwarf_form form;
    union
    union
      {
      {
        char *str;
        char *str;
        struct dwarf_block *blk;
        struct dwarf_block *blk;
        unsigned int unsnd;
        unsigned int unsnd;
        int snd;
        int snd;
        CORE_ADDR addr;
        CORE_ADDR addr;
      }
      }
    u;
    u;
  };
  };
 
 
/* Get at parts of an attribute structure */
/* Get at parts of an attribute structure */
 
 
#define DW_STRING(attr)    ((attr)->u.str)
#define DW_STRING(attr)    ((attr)->u.str)
#define DW_UNSND(attr)     ((attr)->u.unsnd)
#define DW_UNSND(attr)     ((attr)->u.unsnd)
#define DW_BLOCK(attr)     ((attr)->u.blk)
#define DW_BLOCK(attr)     ((attr)->u.blk)
#define DW_SND(attr)       ((attr)->u.snd)
#define DW_SND(attr)       ((attr)->u.snd)
#define DW_ADDR(attr)      ((attr)->u.addr)
#define DW_ADDR(attr)      ((attr)->u.addr)
 
 
/* Blocks are a bunch of untyped bytes. */
/* Blocks are a bunch of untyped bytes. */
struct dwarf_block
struct dwarf_block
  {
  {
    unsigned int size;
    unsigned int size;
    char *data;
    char *data;
  };
  };
 
 
/* We only hold one compilation unit's abbrevs in
/* We only hold one compilation unit's abbrevs in
   memory at any one time.  */
   memory at any one time.  */
#ifndef ABBREV_HASH_SIZE
#ifndef ABBREV_HASH_SIZE
#define ABBREV_HASH_SIZE 121
#define ABBREV_HASH_SIZE 121
#endif
#endif
#ifndef ATTR_ALLOC_CHUNK
#ifndef ATTR_ALLOC_CHUNK
#define ATTR_ALLOC_CHUNK 4
#define ATTR_ALLOC_CHUNK 4
#endif
#endif
 
 
static struct abbrev_info *dwarf2_abbrevs[ABBREV_HASH_SIZE];
static struct abbrev_info *dwarf2_abbrevs[ABBREV_HASH_SIZE];
 
 
/* A hash table of die offsets for following references.  */
/* A hash table of die offsets for following references.  */
#ifndef REF_HASH_SIZE
#ifndef REF_HASH_SIZE
#define REF_HASH_SIZE 1021
#define REF_HASH_SIZE 1021
#endif
#endif
 
 
static struct die_info *die_ref_table[REF_HASH_SIZE];
static struct die_info *die_ref_table[REF_HASH_SIZE];
 
 
/* Obstack for allocating temporary storage used during symbol reading.  */
/* Obstack for allocating temporary storage used during symbol reading.  */
static struct obstack dwarf2_tmp_obstack;
static struct obstack dwarf2_tmp_obstack;
 
 
/* Offset to the first byte of the current compilation unit header,
/* Offset to the first byte of the current compilation unit header,
   for resolving relative reference dies. */
   for resolving relative reference dies. */
static unsigned int cu_header_offset;
static unsigned int cu_header_offset;
 
 
/* Allocate fields for structs, unions and enums in this size.  */
/* Allocate fields for structs, unions and enums in this size.  */
#ifndef DW_FIELD_ALLOC_CHUNK
#ifndef DW_FIELD_ALLOC_CHUNK
#define DW_FIELD_ALLOC_CHUNK 4
#define DW_FIELD_ALLOC_CHUNK 4
#endif
#endif
 
 
/* The language we are debugging.  */
/* The language we are debugging.  */
static enum language cu_language;
static enum language cu_language;
static const struct language_defn *cu_language_defn;
static const struct language_defn *cu_language_defn;
 
 
/* Actually data from the sections.  */
/* Actually data from the sections.  */
static char *dwarf_info_buffer;
static char *dwarf_info_buffer;
static char *dwarf_abbrev_buffer;
static char *dwarf_abbrev_buffer;
static char *dwarf_line_buffer;
static char *dwarf_line_buffer;
 
 
/* A zeroed version of a partial die for initialization purposes.  */
/* A zeroed version of a partial die for initialization purposes.  */
static struct partial_die_info zeroed_partial_die;
static struct partial_die_info zeroed_partial_die;
 
 
/* The generic symbol table building routines have separate lists for
/* The generic symbol table building routines have separate lists for
   file scope symbols and all all other scopes (local scopes).  So
   file scope symbols and all all other scopes (local scopes).  So
   we need to select the right one to pass to add_symbol_to_list().
   we need to select the right one to pass to add_symbol_to_list().
   We do it by keeping a pointer to the correct list in list_in_scope.
   We do it by keeping a pointer to the correct list in list_in_scope.
 
 
   FIXME:  The original dwarf code just treated the file scope as the first
   FIXME:  The original dwarf code just treated the file scope as the first
   local scope, and all other local scopes as nested local scopes, and worked
   local scope, and all other local scopes as nested local scopes, and worked
   fine.  Check to see if we really need to distinguish these
   fine.  Check to see if we really need to distinguish these
   in buildsym.c.  */
   in buildsym.c.  */
static struct pending **list_in_scope = &file_symbols;
static struct pending **list_in_scope = &file_symbols;
 
 
/* FIXME: decode_locdesc sets these variables to describe the location
/* FIXME: decode_locdesc sets these variables to describe the location
   to the caller.  These ought to be a structure or something.   If
   to the caller.  These ought to be a structure or something.   If
   none of the flags are set, the object lives at the address returned
   none of the flags are set, the object lives at the address returned
   by decode_locdesc.  */
   by decode_locdesc.  */
 
 
static int optimized_out;       /* No ops in location in expression,
static int optimized_out;       /* No ops in location in expression,
                                   so object was optimized out.  */
                                   so object was optimized out.  */
static int isreg;               /* Object lives in register.
static int isreg;               /* Object lives in register.
                                   decode_locdesc's return value is
                                   decode_locdesc's return value is
                                   the register number.  */
                                   the register number.  */
static int offreg;              /* Object's address is the sum of the
static int offreg;              /* Object's address is the sum of the
                                   register specified by basereg, plus
                                   register specified by basereg, plus
                                   the offset returned.  */
                                   the offset returned.  */
static int basereg;             /* See `offreg'.  */
static int basereg;             /* See `offreg'.  */
static int isderef;             /* Value described by flags above is
static int isderef;             /* Value described by flags above is
                                   the address of a pointer to the object.  */
                                   the address of a pointer to the object.  */
static int islocal;             /* Variable is at the returned offset
static int islocal;             /* Variable is at the returned offset
                                   from the frame start, but there's
                                   from the frame start, but there's
                                   no identified frame pointer for
                                   no identified frame pointer for
                                   this function, so we can't say
                                   this function, so we can't say
                                   which register it's relative to;
                                   which register it's relative to;
                                   use LOC_LOCAL.  */
                                   use LOC_LOCAL.  */
 
 
/* DW_AT_frame_base values for the current function.
/* DW_AT_frame_base values for the current function.
   frame_base_reg is -1 if DW_AT_frame_base is missing, otherwise it
   frame_base_reg is -1 if DW_AT_frame_base is missing, otherwise it
   contains the register number for the frame register.
   contains the register number for the frame register.
   frame_base_offset is the offset from the frame register to the
   frame_base_offset is the offset from the frame register to the
   virtual stack frame. */
   virtual stack frame. */
static int frame_base_reg;
static int frame_base_reg;
static CORE_ADDR frame_base_offset;
static CORE_ADDR frame_base_offset;
 
 
/* This value is added to each symbol value.  FIXME:  Generalize to
/* This value is added to each symbol value.  FIXME:  Generalize to
   the section_offsets structure used by dbxread (once this is done,
   the section_offsets structure used by dbxread (once this is done,
   pass the appropriate section number to end_symtab).  */
   pass the appropriate section number to end_symtab).  */
static CORE_ADDR baseaddr;      /* Add to each symbol value */
static CORE_ADDR baseaddr;      /* Add to each symbol value */
 
 
/* We put a pointer to this structure in the read_symtab_private field
/* We put a pointer to this structure in the read_symtab_private field
   of the psymtab.
   of the psymtab.
   The complete dwarf information for an objfile is kept in the
   The complete dwarf information for an objfile is kept in the
   psymbol_obstack, so that absolute die references can be handled.
   psymbol_obstack, so that absolute die references can be handled.
   Most of the information in this structure is related to an entire
   Most of the information in this structure is related to an entire
   object file and could be passed via the sym_private field of the objfile.
   object file and could be passed via the sym_private field of the objfile.
   It is however conceivable that dwarf2 might not be the only type
   It is however conceivable that dwarf2 might not be the only type
   of symbols read from an object file.  */
   of symbols read from an object file.  */
 
 
struct dwarf2_pinfo
struct dwarf2_pinfo
  {
  {
    /* Pointer to start of dwarf info buffer for the objfile.  */
    /* Pointer to start of dwarf info buffer for the objfile.  */
 
 
    char *dwarf_info_buffer;
    char *dwarf_info_buffer;
 
 
    /* Offset in dwarf_info_buffer for this compilation unit. */
    /* Offset in dwarf_info_buffer for this compilation unit. */
 
 
    unsigned long dwarf_info_offset;
    unsigned long dwarf_info_offset;
 
 
    /* Pointer to start of dwarf abbreviation buffer for the objfile.  */
    /* Pointer to start of dwarf abbreviation buffer for the objfile.  */
 
 
    char *dwarf_abbrev_buffer;
    char *dwarf_abbrev_buffer;
 
 
    /* Size of dwarf abbreviation section for the objfile.  */
    /* Size of dwarf abbreviation section for the objfile.  */
 
 
    unsigned int dwarf_abbrev_size;
    unsigned int dwarf_abbrev_size;
 
 
    /* Pointer to start of dwarf line buffer for the objfile.  */
    /* Pointer to start of dwarf line buffer for the objfile.  */
 
 
    char *dwarf_line_buffer;
    char *dwarf_line_buffer;
  };
  };
 
 
#define PST_PRIVATE(p) ((struct dwarf2_pinfo *)(p)->read_symtab_private)
#define PST_PRIVATE(p) ((struct dwarf2_pinfo *)(p)->read_symtab_private)
#define DWARF_INFO_BUFFER(p) (PST_PRIVATE(p)->dwarf_info_buffer)
#define DWARF_INFO_BUFFER(p) (PST_PRIVATE(p)->dwarf_info_buffer)
#define DWARF_INFO_OFFSET(p) (PST_PRIVATE(p)->dwarf_info_offset)
#define DWARF_INFO_OFFSET(p) (PST_PRIVATE(p)->dwarf_info_offset)
#define DWARF_ABBREV_BUFFER(p) (PST_PRIVATE(p)->dwarf_abbrev_buffer)
#define DWARF_ABBREV_BUFFER(p) (PST_PRIVATE(p)->dwarf_abbrev_buffer)
#define DWARF_ABBREV_SIZE(p) (PST_PRIVATE(p)->dwarf_abbrev_size)
#define DWARF_ABBREV_SIZE(p) (PST_PRIVATE(p)->dwarf_abbrev_size)
#define DWARF_LINE_BUFFER(p) (PST_PRIVATE(p)->dwarf_line_buffer)
#define DWARF_LINE_BUFFER(p) (PST_PRIVATE(p)->dwarf_line_buffer)
 
 
/* Maintain an array of referenced fundamental types for the current
/* Maintain an array of referenced fundamental types for the current
   compilation unit being read.  For DWARF version 1, we have to construct
   compilation unit being read.  For DWARF version 1, we have to construct
   the fundamental types on the fly, since no information about the
   the fundamental types on the fly, since no information about the
   fundamental types is supplied.  Each such fundamental type is created by
   fundamental types is supplied.  Each such fundamental type is created by
   calling a language dependent routine to create the type, and then a
   calling a language dependent routine to create the type, and then a
   pointer to that type is then placed in the array at the index specified
   pointer to that type is then placed in the array at the index specified
   by it's FT_<TYPENAME> value.  The array has a fixed size set by the
   by it's FT_<TYPENAME> value.  The array has a fixed size set by the
   FT_NUM_MEMBERS compile time constant, which is the number of predefined
   FT_NUM_MEMBERS compile time constant, which is the number of predefined
   fundamental types gdb knows how to construct.  */
   fundamental types gdb knows how to construct.  */
static struct type *ftypes[FT_NUM_MEMBERS];     /* Fundamental types */
static struct type *ftypes[FT_NUM_MEMBERS];     /* Fundamental types */
 
 
/* FIXME: We might want to set this from BFD via bfd_arch_bits_per_byte,
/* FIXME: We might want to set this from BFD via bfd_arch_bits_per_byte,
   but this would require a corresponding change in unpack_field_as_long
   but this would require a corresponding change in unpack_field_as_long
   and friends.  */
   and friends.  */
static int bits_per_byte = 8;
static int bits_per_byte = 8;
 
 
/* The routines that read and process dies for a C struct or C++ class
/* The routines that read and process dies for a C struct or C++ class
   pass lists of data member fields and lists of member function fields
   pass lists of data member fields and lists of member function fields
   in an instance of a field_info structure, as defined below.  */
   in an instance of a field_info structure, as defined below.  */
struct field_info
struct field_info
  {
  {
    /* List of data member and baseclasses fields. */
    /* List of data member and baseclasses fields. */
    struct nextfield
    struct nextfield
      {
      {
        struct nextfield *next;
        struct nextfield *next;
        int accessibility;
        int accessibility;
        int virtuality;
        int virtuality;
        struct field field;
        struct field field;
      }
      }
     *fields;
     *fields;
 
 
    /* Number of fields.  */
    /* Number of fields.  */
    int nfields;
    int nfields;
 
 
    /* Number of baseclasses.  */
    /* Number of baseclasses.  */
    int nbaseclasses;
    int nbaseclasses;
 
 
    /* Set if the accesibility of one of the fields is not public.  */
    /* Set if the accesibility of one of the fields is not public.  */
    int non_public_fields;
    int non_public_fields;
 
 
    /* Member function fields array, entries are allocated in the order they
    /* Member function fields array, entries are allocated in the order they
       are encountered in the object file.  */
       are encountered in the object file.  */
    struct nextfnfield
    struct nextfnfield
      {
      {
        struct nextfnfield *next;
        struct nextfnfield *next;
        struct fn_field fnfield;
        struct fn_field fnfield;
      }
      }
     *fnfields;
     *fnfields;
 
 
    /* Member function fieldlist array, contains name of possibly overloaded
    /* Member function fieldlist array, contains name of possibly overloaded
       member function, number of overloaded member functions and a pointer
       member function, number of overloaded member functions and a pointer
       to the head of the member function field chain.  */
       to the head of the member function field chain.  */
    struct fnfieldlist
    struct fnfieldlist
      {
      {
        char *name;
        char *name;
        int length;
        int length;
        struct nextfnfield *head;
        struct nextfnfield *head;
      }
      }
     *fnfieldlists;
     *fnfieldlists;
 
 
    /* Number of entries in the fnfieldlists array.  */
    /* Number of entries in the fnfieldlists array.  */
    int nfnfields;
    int nfnfields;
  };
  };
 
 
/* FIXME: Kludge to mark a varargs function type for C++ member function
/* FIXME: Kludge to mark a varargs function type for C++ member function
   argument processing.  */
   argument processing.  */
#define TYPE_FLAG_VARARGS       (1 << 10)
#define TYPE_FLAG_VARARGS       (1 << 10)
 
 
/* Dwarf2 has no clean way to discern C++ static and non-static member
/* Dwarf2 has no clean way to discern C++ static and non-static member
   functions. G++ helps GDB by marking the first parameter for non-static
   functions. G++ helps GDB by marking the first parameter for non-static
   member functions (which is the this pointer) as artificial.
   member functions (which is the this pointer) as artificial.
   We pass this information between dwarf2_add_member_fn and
   We pass this information between dwarf2_add_member_fn and
   read_subroutine_type via TYPE_FIELD_ARTIFICIAL.  */
   read_subroutine_type via TYPE_FIELD_ARTIFICIAL.  */
#define TYPE_FIELD_ARTIFICIAL   TYPE_FIELD_BITPOS
#define TYPE_FIELD_ARTIFICIAL   TYPE_FIELD_BITPOS
 
 
/* Various complaints about symbol reading that don't abort the process */
/* Various complaints about symbol reading that don't abort the process */
 
 
static struct complaint dwarf2_const_ignored =
static struct complaint dwarf2_const_ignored =
{
{
  "type qualifier 'const' ignored", 0, 0
  "type qualifier 'const' ignored", 0, 0
};
};
static struct complaint dwarf2_volatile_ignored =
static struct complaint dwarf2_volatile_ignored =
{
{
  "type qualifier 'volatile' ignored", 0, 0
  "type qualifier 'volatile' ignored", 0, 0
};
};
static struct complaint dwarf2_non_const_array_bound_ignored =
static struct complaint dwarf2_non_const_array_bound_ignored =
{
{
  "non-constant array bounds form '%s' ignored", 0, 0
  "non-constant array bounds form '%s' ignored", 0, 0
};
};
static struct complaint dwarf2_missing_line_number_section =
static struct complaint dwarf2_missing_line_number_section =
{
{
  "missing .debug_line section", 0, 0
  "missing .debug_line section", 0, 0
};
};
static struct complaint dwarf2_mangled_line_number_section =
static struct complaint dwarf2_mangled_line_number_section =
{
{
  "mangled .debug_line section", 0, 0
  "mangled .debug_line section", 0, 0
};
};
static struct complaint dwarf2_unsupported_die_ref_attr =
static struct complaint dwarf2_unsupported_die_ref_attr =
{
{
  "unsupported die ref attribute form: '%s'", 0, 0
  "unsupported die ref attribute form: '%s'", 0, 0
};
};
static struct complaint dwarf2_unsupported_stack_op =
static struct complaint dwarf2_unsupported_stack_op =
{
{
  "unsupported stack op: '%s'", 0, 0
  "unsupported stack op: '%s'", 0, 0
};
};
static struct complaint dwarf2_complex_location_expr =
static struct complaint dwarf2_complex_location_expr =
{
{
  "location expression too complex", 0, 0
  "location expression too complex", 0, 0
};
};
static struct complaint dwarf2_unsupported_tag =
static struct complaint dwarf2_unsupported_tag =
{
{
  "unsupported tag: '%s'", 0, 0
  "unsupported tag: '%s'", 0, 0
};
};
static struct complaint dwarf2_unsupported_at_encoding =
static struct complaint dwarf2_unsupported_at_encoding =
{
{
  "unsupported DW_AT_encoding: '%s'", 0, 0
  "unsupported DW_AT_encoding: '%s'", 0, 0
};
};
static struct complaint dwarf2_unsupported_at_frame_base =
static struct complaint dwarf2_unsupported_at_frame_base =
{
{
  "unsupported DW_AT_frame_base for function '%s'", 0, 0
  "unsupported DW_AT_frame_base for function '%s'", 0, 0
};
};
static struct complaint dwarf2_unexpected_tag =
static struct complaint dwarf2_unexpected_tag =
{
{
  "unexepected tag in read_type_die: '%s'", 0, 0
  "unexepected tag in read_type_die: '%s'", 0, 0
};
};
static struct complaint dwarf2_missing_at_frame_base =
static struct complaint dwarf2_missing_at_frame_base =
{
{
  "DW_AT_frame_base missing for DW_OP_fbreg", 0, 0
  "DW_AT_frame_base missing for DW_OP_fbreg", 0, 0
};
};
static struct complaint dwarf2_bad_static_member_name =
static struct complaint dwarf2_bad_static_member_name =
{
{
  "unrecognized static data member name '%s'", 0, 0
  "unrecognized static data member name '%s'", 0, 0
};
};
static struct complaint dwarf2_unsupported_accessibility =
static struct complaint dwarf2_unsupported_accessibility =
{
{
  "unsupported accessibility %d", 0, 0
  "unsupported accessibility %d", 0, 0
};
};
static struct complaint dwarf2_bad_member_name_complaint =
static struct complaint dwarf2_bad_member_name_complaint =
{
{
  "cannot extract member name from '%s'", 0, 0
  "cannot extract member name from '%s'", 0, 0
};
};
static struct complaint dwarf2_missing_member_fn_type_complaint =
static struct complaint dwarf2_missing_member_fn_type_complaint =
{
{
  "member function type missing for '%s'", 0, 0
  "member function type missing for '%s'", 0, 0
};
};
static struct complaint dwarf2_vtbl_not_found_complaint =
static struct complaint dwarf2_vtbl_not_found_complaint =
{
{
  "virtual function table pointer not found when defining class '%s'", 0, 0
  "virtual function table pointer not found when defining class '%s'", 0, 0
};
};
static struct complaint dwarf2_absolute_sibling_complaint =
static struct complaint dwarf2_absolute_sibling_complaint =
{
{
  "ignoring absolute DW_AT_sibling", 0, 0
  "ignoring absolute DW_AT_sibling", 0, 0
};
};
static struct complaint dwarf2_const_value_length_mismatch =
static struct complaint dwarf2_const_value_length_mismatch =
{
{
  "const value length mismatch for '%s', got %d, expected %d", 0, 0
  "const value length mismatch for '%s', got %d, expected %d", 0, 0
};
};
static struct complaint dwarf2_unsupported_const_value_attr =
static struct complaint dwarf2_unsupported_const_value_attr =
{
{
  "unsupported const value attribute form: '%s'", 0, 0
  "unsupported const value attribute form: '%s'", 0, 0
};
};
 
 
/* Remember the addr_size read from the dwarf.
/* Remember the addr_size read from the dwarf.
   If a target expects to link compilation units with differing address
   If a target expects to link compilation units with differing address
   sizes, gdb needs to be sure that the appropriate size is here for
   sizes, gdb needs to be sure that the appropriate size is here for
   whatever scope is currently getting read. */
   whatever scope is currently getting read. */
static int address_size;
static int address_size;
 
 
/* Externals references.  */
/* Externals references.  */
extern int info_verbose;        /* From main.c; nonzero => verbose */
extern int info_verbose;        /* From main.c; nonzero => verbose */
 
 
/* local function prototypes */
/* local function prototypes */
 
 
static void dwarf2_locate_sections PARAMS ((bfd *, asection *, PTR));
static void dwarf2_locate_sections PARAMS ((bfd *, asection *, PTR));
 
 
#if 0
#if 0
static void dwarf2_build_psymtabs_easy PARAMS ((struct objfile *, int));
static void dwarf2_build_psymtabs_easy PARAMS ((struct objfile *, int));
#endif
#endif
 
 
static void dwarf2_build_psymtabs_hard PARAMS ((struct objfile *, int));
static void dwarf2_build_psymtabs_hard PARAMS ((struct objfile *, int));
 
 
static char *scan_partial_symbols PARAMS ((char *, struct objfile *,
static char *scan_partial_symbols PARAMS ((char *, struct objfile *,
                                           CORE_ADDR *, CORE_ADDR *));
                                           CORE_ADDR *, CORE_ADDR *));
 
 
static void add_partial_symbol PARAMS ((struct partial_die_info *,
static void add_partial_symbol PARAMS ((struct partial_die_info *,
                                        struct objfile *));
                                        struct objfile *));
 
 
static void dwarf2_psymtab_to_symtab PARAMS ((struct partial_symtab *));
static void dwarf2_psymtab_to_symtab PARAMS ((struct partial_symtab *));
 
 
static void psymtab_to_symtab_1 PARAMS ((struct partial_symtab *));
static void psymtab_to_symtab_1 PARAMS ((struct partial_symtab *));
 
 
static char *dwarf2_read_section PARAMS ((struct objfile *, file_ptr,
static char *dwarf2_read_section PARAMS ((struct objfile *, file_ptr,
                                          unsigned int));
                                          unsigned int));
 
 
static void dwarf2_read_abbrevs PARAMS ((bfd *, unsigned int));
static void dwarf2_read_abbrevs PARAMS ((bfd *, unsigned int));
 
 
static void dwarf2_empty_abbrev_table PARAMS ((PTR));
static void dwarf2_empty_abbrev_table PARAMS ((PTR));
 
 
static struct abbrev_info *dwarf2_lookup_abbrev PARAMS ((unsigned int));
static struct abbrev_info *dwarf2_lookup_abbrev PARAMS ((unsigned int));
 
 
static char *read_partial_die PARAMS ((struct partial_die_info *,
static char *read_partial_die PARAMS ((struct partial_die_info *,
                                       bfd *, char *, int *));
                                       bfd *, char *, int *));
 
 
static char *read_full_die PARAMS ((struct die_info **, bfd *, char *));
static char *read_full_die PARAMS ((struct die_info **, bfd *, char *));
 
 
static char *read_attribute PARAMS ((struct attribute *, struct attr_abbrev *,
static char *read_attribute PARAMS ((struct attribute *, struct attr_abbrev *,
                                     bfd *, char *));
                                     bfd *, char *));
 
 
static unsigned int read_1_byte PARAMS ((bfd *, char *));
static unsigned int read_1_byte PARAMS ((bfd *, char *));
 
 
static int read_1_signed_byte PARAMS ((bfd *, char *));
static int read_1_signed_byte PARAMS ((bfd *, char *));
 
 
static unsigned int read_2_bytes PARAMS ((bfd *, char *));
static unsigned int read_2_bytes PARAMS ((bfd *, char *));
 
 
static unsigned int read_4_bytes PARAMS ((bfd *, char *));
static unsigned int read_4_bytes PARAMS ((bfd *, char *));
 
 
static unsigned int read_8_bytes PARAMS ((bfd *, char *));
static unsigned int read_8_bytes PARAMS ((bfd *, char *));
 
 
static CORE_ADDR read_address PARAMS ((bfd *, char *));
static CORE_ADDR read_address PARAMS ((bfd *, char *));
 
 
static char *read_n_bytes PARAMS ((bfd *, char *, unsigned int));
static char *read_n_bytes PARAMS ((bfd *, char *, unsigned int));
 
 
static char *read_string PARAMS ((bfd *, char *, unsigned int *));
static char *read_string PARAMS ((bfd *, char *, unsigned int *));
 
 
static unsigned int read_unsigned_leb128 PARAMS ((bfd *, char *,
static unsigned int read_unsigned_leb128 PARAMS ((bfd *, char *,
                                                  unsigned int *));
                                                  unsigned int *));
 
 
static int read_signed_leb128 PARAMS ((bfd *, char *, unsigned int *));
static int read_signed_leb128 PARAMS ((bfd *, char *, unsigned int *));
 
 
static void set_cu_language PARAMS ((unsigned int));
static void set_cu_language PARAMS ((unsigned int));
 
 
static struct attribute *dwarf_attr PARAMS ((struct die_info *,
static struct attribute *dwarf_attr PARAMS ((struct die_info *,
                                             unsigned int));
                                             unsigned int));
 
 
static int die_is_declaration (struct die_info *);
static int die_is_declaration (struct die_info *);
 
 
static void dwarf_decode_lines PARAMS ((unsigned int, char *, bfd *));
static void dwarf_decode_lines PARAMS ((unsigned int, char *, bfd *));
 
 
static void dwarf2_start_subfile PARAMS ((char *, char *));
static void dwarf2_start_subfile PARAMS ((char *, char *));
 
 
static struct symbol *new_symbol PARAMS ((struct die_info *, struct type *,
static struct symbol *new_symbol PARAMS ((struct die_info *, struct type *,
                                          struct objfile *));
                                          struct objfile *));
 
 
static void dwarf2_const_value PARAMS ((struct attribute *, struct symbol *,
static void dwarf2_const_value PARAMS ((struct attribute *, struct symbol *,
                                        struct objfile *));
                                        struct objfile *));
 
 
static void dwarf2_const_value_data (struct attribute *attr,
static void dwarf2_const_value_data (struct attribute *attr,
                                     struct symbol *sym,
                                     struct symbol *sym,
                                     int bits);
                                     int bits);
 
 
static struct type *die_type PARAMS ((struct die_info *, struct objfile *));
static struct type *die_type PARAMS ((struct die_info *, struct objfile *));
 
 
static struct type *die_containing_type PARAMS ((struct die_info *,
static struct type *die_containing_type PARAMS ((struct die_info *,
                                                 struct objfile *));
                                                 struct objfile *));
 
 
#if 0
#if 0
static struct type *type_at_offset PARAMS ((unsigned int, struct objfile *));
static struct type *type_at_offset PARAMS ((unsigned int, struct objfile *));
#endif
#endif
 
 
static struct type *tag_type_to_type PARAMS ((struct die_info *,
static struct type *tag_type_to_type PARAMS ((struct die_info *,
                                              struct objfile *));
                                              struct objfile *));
 
 
static void read_type_die PARAMS ((struct die_info *, struct objfile *));
static void read_type_die PARAMS ((struct die_info *, struct objfile *));
 
 
static void read_typedef PARAMS ((struct die_info *, struct objfile *));
static void read_typedef PARAMS ((struct die_info *, struct objfile *));
 
 
static void read_base_type PARAMS ((struct die_info *, struct objfile *));
static void read_base_type PARAMS ((struct die_info *, struct objfile *));
 
 
static void read_file_scope PARAMS ((struct die_info *, struct objfile *));
static void read_file_scope PARAMS ((struct die_info *, struct objfile *));
 
 
static void read_func_scope PARAMS ((struct die_info *, struct objfile *));
static void read_func_scope PARAMS ((struct die_info *, struct objfile *));
 
 
static void read_lexical_block_scope PARAMS ((struct die_info *,
static void read_lexical_block_scope PARAMS ((struct die_info *,
                                              struct objfile *));
                                              struct objfile *));
 
 
static int dwarf2_get_pc_bounds PARAMS ((struct die_info *,
static int dwarf2_get_pc_bounds PARAMS ((struct die_info *,
                                         CORE_ADDR *, CORE_ADDR *,
                                         CORE_ADDR *, CORE_ADDR *,
                                         struct objfile *));
                                         struct objfile *));
 
 
static void dwarf2_add_field PARAMS ((struct field_info *, struct die_info *,
static void dwarf2_add_field PARAMS ((struct field_info *, struct die_info *,
                                      struct objfile *));
                                      struct objfile *));
 
 
static void dwarf2_attach_fields_to_type PARAMS ((struct field_info *,
static void dwarf2_attach_fields_to_type PARAMS ((struct field_info *,
                                                  struct type *,
                                                  struct type *,
                                                  struct objfile *));
                                                  struct objfile *));
 
 
static void dwarf2_add_member_fn PARAMS ((struct field_info *,
static void dwarf2_add_member_fn PARAMS ((struct field_info *,
                                          struct die_info *, struct type *,
                                          struct die_info *, struct type *,
                                          struct objfile * objfile));
                                          struct objfile * objfile));
 
 
static void dwarf2_attach_fn_fields_to_type PARAMS ((struct field_info *,
static void dwarf2_attach_fn_fields_to_type PARAMS ((struct field_info *,
                                                     struct type *,
                                                     struct type *,
                                                     struct objfile *));
                                                     struct objfile *));
 
 
static void read_structure_scope PARAMS ((struct die_info *, struct objfile *));
static void read_structure_scope PARAMS ((struct die_info *, struct objfile *));
 
 
static void read_common_block PARAMS ((struct die_info *, struct objfile *));
static void read_common_block PARAMS ((struct die_info *, struct objfile *));
 
 
static void read_enumeration PARAMS ((struct die_info *, struct objfile *));
static void read_enumeration PARAMS ((struct die_info *, struct objfile *));
 
 
static struct type *dwarf_base_type PARAMS ((int, int, struct objfile *));
static struct type *dwarf_base_type PARAMS ((int, int, struct objfile *));
 
 
static CORE_ADDR decode_locdesc PARAMS ((struct dwarf_block *,
static CORE_ADDR decode_locdesc PARAMS ((struct dwarf_block *,
                                         struct objfile *));
                                         struct objfile *));
 
 
static void read_array_type PARAMS ((struct die_info *, struct objfile *));
static void read_array_type PARAMS ((struct die_info *, struct objfile *));
 
 
static void read_tag_pointer_type PARAMS ((struct die_info *,
static void read_tag_pointer_type PARAMS ((struct die_info *,
                                           struct objfile *));
                                           struct objfile *));
 
 
static void read_tag_ptr_to_member_type PARAMS ((struct die_info *,
static void read_tag_ptr_to_member_type PARAMS ((struct die_info *,
                                                 struct objfile *));
                                                 struct objfile *));
 
 
static void read_tag_reference_type PARAMS ((struct die_info *,
static void read_tag_reference_type PARAMS ((struct die_info *,
                                             struct objfile *));
                                             struct objfile *));
 
 
static void read_tag_const_type PARAMS ((struct die_info *, struct objfile *));
static void read_tag_const_type PARAMS ((struct die_info *, struct objfile *));
 
 
static void read_tag_volatile_type PARAMS ((struct die_info *,
static void read_tag_volatile_type PARAMS ((struct die_info *,
                                            struct objfile *));
                                            struct objfile *));
 
 
static void read_tag_string_type PARAMS ((struct die_info *,
static void read_tag_string_type PARAMS ((struct die_info *,
                                          struct objfile *));
                                          struct objfile *));
 
 
static void read_subroutine_type PARAMS ((struct die_info *,
static void read_subroutine_type PARAMS ((struct die_info *,
                                          struct objfile *));
                                          struct objfile *));
 
 
struct die_info *read_comp_unit PARAMS ((char *, bfd *));
struct die_info *read_comp_unit PARAMS ((char *, bfd *));
 
 
static void free_die_list PARAMS ((struct die_info *));
static void free_die_list PARAMS ((struct die_info *));
 
 
static void process_die PARAMS ((struct die_info *, struct objfile *));
static void process_die PARAMS ((struct die_info *, struct objfile *));
 
 
static char *dwarf2_linkage_name PARAMS ((struct die_info *));
static char *dwarf2_linkage_name PARAMS ((struct die_info *));
 
 
static char *dwarf_tag_name PARAMS ((unsigned int));
static char *dwarf_tag_name PARAMS ((unsigned int));
 
 
static char *dwarf_attr_name PARAMS ((unsigned int));
static char *dwarf_attr_name PARAMS ((unsigned int));
 
 
static char *dwarf_form_name PARAMS ((unsigned int));
static char *dwarf_form_name PARAMS ((unsigned int));
 
 
static char *dwarf_stack_op_name PARAMS ((unsigned int));
static char *dwarf_stack_op_name PARAMS ((unsigned int));
 
 
static char *dwarf_bool_name PARAMS ((unsigned int));
static char *dwarf_bool_name PARAMS ((unsigned int));
 
 
static char *dwarf_type_encoding_name PARAMS ((unsigned int));
static char *dwarf_type_encoding_name PARAMS ((unsigned int));
 
 
#if 0
#if 0
static char *dwarf_cfi_name PARAMS ((unsigned int));
static char *dwarf_cfi_name PARAMS ((unsigned int));
 
 
struct die_info *copy_die PARAMS ((struct die_info *));
struct die_info *copy_die PARAMS ((struct die_info *));
#endif
#endif
 
 
struct die_info *sibling_die PARAMS ((struct die_info *));
struct die_info *sibling_die PARAMS ((struct die_info *));
 
 
void dump_die PARAMS ((struct die_info *));
void dump_die PARAMS ((struct die_info *));
 
 
void dump_die_list PARAMS ((struct die_info *));
void dump_die_list PARAMS ((struct die_info *));
 
 
void store_in_ref_table PARAMS ((unsigned int, struct die_info *));
void store_in_ref_table PARAMS ((unsigned int, struct die_info *));
 
 
static void dwarf2_empty_die_ref_table PARAMS ((void));
static void dwarf2_empty_die_ref_table PARAMS ((void));
 
 
static unsigned int dwarf2_get_ref_die_offset PARAMS ((struct attribute *));
static unsigned int dwarf2_get_ref_die_offset PARAMS ((struct attribute *));
 
 
struct die_info *follow_die_ref PARAMS ((unsigned int));
struct die_info *follow_die_ref PARAMS ((unsigned int));
 
 
static struct type *dwarf2_fundamental_type PARAMS ((struct objfile *, int));
static struct type *dwarf2_fundamental_type PARAMS ((struct objfile *, int));
 
 
/* memory allocation interface */
/* memory allocation interface */
 
 
static void dwarf2_free_tmp_obstack PARAMS ((PTR));
static void dwarf2_free_tmp_obstack PARAMS ((PTR));
 
 
static struct dwarf_block *dwarf_alloc_block PARAMS ((void));
static struct dwarf_block *dwarf_alloc_block PARAMS ((void));
 
 
static struct abbrev_info *dwarf_alloc_abbrev PARAMS ((void));
static struct abbrev_info *dwarf_alloc_abbrev PARAMS ((void));
 
 
static struct die_info *dwarf_alloc_die PARAMS ((void));
static struct die_info *dwarf_alloc_die PARAMS ((void));
 
 
/* Try to locate the sections we need for DWARF 2 debugging
/* Try to locate the sections we need for DWARF 2 debugging
   information and return true if we have enough to do something.  */
   information and return true if we have enough to do something.  */
 
 
int
int
dwarf2_has_info (abfd)
dwarf2_has_info (abfd)
     bfd *abfd;
     bfd *abfd;
{
{
  dwarf_info_offset = dwarf_abbrev_offset = dwarf_line_offset = 0;
  dwarf_info_offset = dwarf_abbrev_offset = dwarf_line_offset = 0;
  bfd_map_over_sections (abfd, dwarf2_locate_sections, NULL);
  bfd_map_over_sections (abfd, dwarf2_locate_sections, NULL);
  if (dwarf_info_offset && dwarf_abbrev_offset)
  if (dwarf_info_offset && dwarf_abbrev_offset)
    {
    {
      return 1;
      return 1;
    }
    }
  else
  else
    {
    {
      return 0;
      return 0;
    }
    }
}
}
 
 
/* This function is mapped across the sections and remembers the
/* This function is mapped across the sections and remembers the
   offset and size of each of the debugging sections we are interested
   offset and size of each of the debugging sections we are interested
   in.  */
   in.  */
 
 
static void
static void
dwarf2_locate_sections (ignore_abfd, sectp, ignore_ptr)
dwarf2_locate_sections (ignore_abfd, sectp, ignore_ptr)
     bfd *ignore_abfd;
     bfd *ignore_abfd;
     asection *sectp;
     asection *sectp;
     PTR ignore_ptr;
     PTR ignore_ptr;
{
{
  if (STREQ (sectp->name, INFO_SECTION))
  if (STREQ (sectp->name, INFO_SECTION))
    {
    {
      dwarf_info_offset = sectp->filepos;
      dwarf_info_offset = sectp->filepos;
      dwarf_info_size = bfd_get_section_size_before_reloc (sectp);
      dwarf_info_size = bfd_get_section_size_before_reloc (sectp);
    }
    }
  else if (STREQ (sectp->name, ABBREV_SECTION))
  else if (STREQ (sectp->name, ABBREV_SECTION))
    {
    {
      dwarf_abbrev_offset = sectp->filepos;
      dwarf_abbrev_offset = sectp->filepos;
      dwarf_abbrev_size = bfd_get_section_size_before_reloc (sectp);
      dwarf_abbrev_size = bfd_get_section_size_before_reloc (sectp);
    }
    }
  else if (STREQ (sectp->name, LINE_SECTION))
  else if (STREQ (sectp->name, LINE_SECTION))
    {
    {
      dwarf_line_offset = sectp->filepos;
      dwarf_line_offset = sectp->filepos;
      dwarf_line_size = bfd_get_section_size_before_reloc (sectp);
      dwarf_line_size = bfd_get_section_size_before_reloc (sectp);
    }
    }
  else if (STREQ (sectp->name, PUBNAMES_SECTION))
  else if (STREQ (sectp->name, PUBNAMES_SECTION))
    {
    {
      dwarf_pubnames_offset = sectp->filepos;
      dwarf_pubnames_offset = sectp->filepos;
      dwarf_pubnames_size = bfd_get_section_size_before_reloc (sectp);
      dwarf_pubnames_size = bfd_get_section_size_before_reloc (sectp);
    }
    }
  else if (STREQ (sectp->name, ARANGES_SECTION))
  else if (STREQ (sectp->name, ARANGES_SECTION))
    {
    {
      dwarf_aranges_offset = sectp->filepos;
      dwarf_aranges_offset = sectp->filepos;
      dwarf_aranges_size = bfd_get_section_size_before_reloc (sectp);
      dwarf_aranges_size = bfd_get_section_size_before_reloc (sectp);
    }
    }
  else if (STREQ (sectp->name, LOC_SECTION))
  else if (STREQ (sectp->name, LOC_SECTION))
    {
    {
      dwarf_loc_offset = sectp->filepos;
      dwarf_loc_offset = sectp->filepos;
      dwarf_loc_size = bfd_get_section_size_before_reloc (sectp);
      dwarf_loc_size = bfd_get_section_size_before_reloc (sectp);
    }
    }
  else if (STREQ (sectp->name, MACINFO_SECTION))
  else if (STREQ (sectp->name, MACINFO_SECTION))
    {
    {
      dwarf_macinfo_offset = sectp->filepos;
      dwarf_macinfo_offset = sectp->filepos;
      dwarf_macinfo_size = bfd_get_section_size_before_reloc (sectp);
      dwarf_macinfo_size = bfd_get_section_size_before_reloc (sectp);
    }
    }
  else if (STREQ (sectp->name, STR_SECTION))
  else if (STREQ (sectp->name, STR_SECTION))
    {
    {
      dwarf_str_offset = sectp->filepos;
      dwarf_str_offset = sectp->filepos;
      dwarf_str_size = bfd_get_section_size_before_reloc (sectp);
      dwarf_str_size = bfd_get_section_size_before_reloc (sectp);
    }
    }
}
}
 
 
/* Build a partial symbol table.  */
/* Build a partial symbol table.  */
 
 
void
void
dwarf2_build_psymtabs (objfile, mainline)
dwarf2_build_psymtabs (objfile, mainline)
     struct objfile *objfile;
     struct objfile *objfile;
     int mainline;
     int mainline;
{
{
 
 
  /* We definitely need the .debug_info and .debug_abbrev sections */
  /* We definitely need the .debug_info and .debug_abbrev sections */
 
 
  dwarf_info_buffer = dwarf2_read_section (objfile,
  dwarf_info_buffer = dwarf2_read_section (objfile,
                                           dwarf_info_offset,
                                           dwarf_info_offset,
                                           dwarf_info_size);
                                           dwarf_info_size);
  dwarf_abbrev_buffer = dwarf2_read_section (objfile,
  dwarf_abbrev_buffer = dwarf2_read_section (objfile,
                                             dwarf_abbrev_offset,
                                             dwarf_abbrev_offset,
                                             dwarf_abbrev_size);
                                             dwarf_abbrev_size);
  dwarf_line_buffer = dwarf2_read_section (objfile,
  dwarf_line_buffer = dwarf2_read_section (objfile,
                                           dwarf_line_offset,
                                           dwarf_line_offset,
                                           dwarf_line_size);
                                           dwarf_line_size);
 
 
  if (mainline || objfile->global_psymbols.size == 0 ||
  if (mainline || objfile->global_psymbols.size == 0 ||
      objfile->static_psymbols.size == 0)
      objfile->static_psymbols.size == 0)
    {
    {
      init_psymbol_list (objfile, 1024);
      init_psymbol_list (objfile, 1024);
    }
    }
 
 
#if 0
#if 0
  if (dwarf_aranges_offset && dwarf_pubnames_offset)
  if (dwarf_aranges_offset && dwarf_pubnames_offset)
    {
    {
      /* Things are significantly easier if we have .debug_aranges and
      /* Things are significantly easier if we have .debug_aranges and
         .debug_pubnames sections */
         .debug_pubnames sections */
 
 
      dwarf2_build_psymtabs_easy (objfile, mainline);
      dwarf2_build_psymtabs_easy (objfile, mainline);
    }
    }
  else
  else
#endif
#endif
    /* only test this case for now */
    /* only test this case for now */
    {
    {
      /* In this case we have to work a bit harder */
      /* In this case we have to work a bit harder */
      dwarf2_build_psymtabs_hard (objfile, mainline);
      dwarf2_build_psymtabs_hard (objfile, mainline);
    }
    }
}
}
 
 
#if 0
#if 0
/* Build the partial symbol table from the information in the
/* Build the partial symbol table from the information in the
   .debug_pubnames and .debug_aranges sections.  */
   .debug_pubnames and .debug_aranges sections.  */
 
 
static void
static void
dwarf2_build_psymtabs_easy (objfile, mainline)
dwarf2_build_psymtabs_easy (objfile, mainline)
     struct objfile *objfile;
     struct objfile *objfile;
     int mainline;
     int mainline;
{
{
  bfd *abfd = objfile->obfd;
  bfd *abfd = objfile->obfd;
  char *aranges_buffer, *pubnames_buffer;
  char *aranges_buffer, *pubnames_buffer;
  char *aranges_ptr, *pubnames_ptr;
  char *aranges_ptr, *pubnames_ptr;
  unsigned int entry_length, version, info_offset, info_size;
  unsigned int entry_length, version, info_offset, info_size;
 
 
  pubnames_buffer = dwarf2_read_section (objfile,
  pubnames_buffer = dwarf2_read_section (objfile,
                                         dwarf_pubnames_offset,
                                         dwarf_pubnames_offset,
                                         dwarf_pubnames_size);
                                         dwarf_pubnames_size);
  pubnames_ptr = pubnames_buffer;
  pubnames_ptr = pubnames_buffer;
  while ((pubnames_ptr - pubnames_buffer) < dwarf_pubnames_size)
  while ((pubnames_ptr - pubnames_buffer) < dwarf_pubnames_size)
    {
    {
      entry_length = read_4_bytes (abfd, pubnames_ptr);
      entry_length = read_4_bytes (abfd, pubnames_ptr);
      pubnames_ptr += 4;
      pubnames_ptr += 4;
      version = read_1_byte (abfd, pubnames_ptr);
      version = read_1_byte (abfd, pubnames_ptr);
      pubnames_ptr += 1;
      pubnames_ptr += 1;
      info_offset = read_4_bytes (abfd, pubnames_ptr);
      info_offset = read_4_bytes (abfd, pubnames_ptr);
      pubnames_ptr += 4;
      pubnames_ptr += 4;
      info_size = read_4_bytes (abfd, pubnames_ptr);
      info_size = read_4_bytes (abfd, pubnames_ptr);
      pubnames_ptr += 4;
      pubnames_ptr += 4;
    }
    }
 
 
  aranges_buffer = dwarf2_read_section (objfile,
  aranges_buffer = dwarf2_read_section (objfile,
                                        dwarf_aranges_offset,
                                        dwarf_aranges_offset,
                                        dwarf_aranges_size);
                                        dwarf_aranges_size);
 
 
}
}
#endif
#endif
 
 
/* Build the partial symbol table by doing a quick pass through the
/* Build the partial symbol table by doing a quick pass through the
   .debug_info and .debug_abbrev sections.  */
   .debug_info and .debug_abbrev sections.  */
 
 
static void
static void
dwarf2_build_psymtabs_hard (objfile, mainline)
dwarf2_build_psymtabs_hard (objfile, mainline)
     struct objfile *objfile;
     struct objfile *objfile;
     int mainline;
     int mainline;
{
{
  /* Instead of reading this into a big buffer, we should probably use
  /* Instead of reading this into a big buffer, we should probably use
     mmap()  on architectures that support it. (FIXME) */
     mmap()  on architectures that support it. (FIXME) */
  bfd *abfd = objfile->obfd;
  bfd *abfd = objfile->obfd;
  char *info_ptr, *abbrev_ptr;
  char *info_ptr, *abbrev_ptr;
  char *beg_of_comp_unit;
  char *beg_of_comp_unit;
  struct comp_unit_head cu_header;
  struct comp_unit_head cu_header;
  struct partial_die_info comp_unit_die;
  struct partial_die_info comp_unit_die;
  struct partial_symtab *pst;
  struct partial_symtab *pst;
  struct cleanup *back_to;
  struct cleanup *back_to;
  int comp_unit_has_pc_info;
  int comp_unit_has_pc_info;
  CORE_ADDR lowpc, highpc;
  CORE_ADDR lowpc, highpc;
 
 
  info_ptr = dwarf_info_buffer;
  info_ptr = dwarf_info_buffer;
  abbrev_ptr = dwarf_abbrev_buffer;
  abbrev_ptr = dwarf_abbrev_buffer;
 
 
  obstack_init (&dwarf2_tmp_obstack);
  obstack_init (&dwarf2_tmp_obstack);
  back_to = make_cleanup (dwarf2_free_tmp_obstack, NULL);
  back_to = make_cleanup (dwarf2_free_tmp_obstack, NULL);
 
 
  while ((unsigned int) (info_ptr - dwarf_info_buffer)
  while ((unsigned int) (info_ptr - dwarf_info_buffer)
         + ((info_ptr - dwarf_info_buffer) % 4) < dwarf_info_size)
         + ((info_ptr - dwarf_info_buffer) % 4) < dwarf_info_size)
    {
    {
      beg_of_comp_unit = info_ptr;
      beg_of_comp_unit = info_ptr;
      cu_header.length = read_4_bytes (abfd, info_ptr);
      cu_header.length = read_4_bytes (abfd, info_ptr);
      info_ptr += 4;
      info_ptr += 4;
      cu_header.version = read_2_bytes (abfd, info_ptr);
      cu_header.version = read_2_bytes (abfd, info_ptr);
      info_ptr += 2;
      info_ptr += 2;
      cu_header.abbrev_offset = read_4_bytes (abfd, info_ptr);
      cu_header.abbrev_offset = read_4_bytes (abfd, info_ptr);
      info_ptr += 4;
      info_ptr += 4;
      cu_header.addr_size = read_1_byte (abfd, info_ptr);
      cu_header.addr_size = read_1_byte (abfd, info_ptr);
      info_ptr += 1;
      info_ptr += 1;
      address_size = cu_header.addr_size;
      address_size = cu_header.addr_size;
 
 
      if (cu_header.version != 2)
      if (cu_header.version != 2)
        {
        {
          error ("Dwarf Error: wrong version in compilation unit header.");
          error ("Dwarf Error: wrong version in compilation unit header.");
          return;
          return;
        }
        }
      if (cu_header.abbrev_offset >= dwarf_abbrev_size)
      if (cu_header.abbrev_offset >= dwarf_abbrev_size)
        {
        {
          error ("Dwarf Error: bad offset (0x%lx) in compilation unit header (offset 0x%lx + 6).",
          error ("Dwarf Error: bad offset (0x%lx) in compilation unit header (offset 0x%lx + 6).",
                 (long) cu_header.abbrev_offset,
                 (long) cu_header.abbrev_offset,
                 (long) (beg_of_comp_unit - dwarf_info_buffer));
                 (long) (beg_of_comp_unit - dwarf_info_buffer));
          return;
          return;
        }
        }
      if (beg_of_comp_unit + cu_header.length + 4
      if (beg_of_comp_unit + cu_header.length + 4
          > dwarf_info_buffer + dwarf_info_size)
          > dwarf_info_buffer + dwarf_info_size)
        {
        {
          error ("Dwarf Error: bad length (0x%lx) in compilation unit header (offset 0x%lx + 0).",
          error ("Dwarf Error: bad length (0x%lx) in compilation unit header (offset 0x%lx + 0).",
                 (long) cu_header.length,
                 (long) cu_header.length,
                 (long) (beg_of_comp_unit - dwarf_info_buffer));
                 (long) (beg_of_comp_unit - dwarf_info_buffer));
          return;
          return;
        }
        }
      /* Read the abbrevs for this compilation unit into a table */
      /* Read the abbrevs for this compilation unit into a table */
      dwarf2_read_abbrevs (abfd, cu_header.abbrev_offset);
      dwarf2_read_abbrevs (abfd, cu_header.abbrev_offset);
      make_cleanup (dwarf2_empty_abbrev_table, NULL);
      make_cleanup (dwarf2_empty_abbrev_table, NULL);
 
 
      /* Read the compilation unit die */
      /* Read the compilation unit die */
      info_ptr = read_partial_die (&comp_unit_die, abfd,
      info_ptr = read_partial_die (&comp_unit_die, abfd,
                                   info_ptr, &comp_unit_has_pc_info);
                                   info_ptr, &comp_unit_has_pc_info);
 
 
      /* Set the language we're debugging */
      /* Set the language we're debugging */
      set_cu_language (comp_unit_die.language);
      set_cu_language (comp_unit_die.language);
 
 
      /* Allocate a new partial symbol table structure */
      /* Allocate a new partial symbol table structure */
      pst = start_psymtab_common (objfile, objfile->section_offsets,
      pst = start_psymtab_common (objfile, objfile->section_offsets,
                                  comp_unit_die.name ? comp_unit_die.name : "",
                                  comp_unit_die.name ? comp_unit_die.name : "",
                                  comp_unit_die.lowpc,
                                  comp_unit_die.lowpc,
                                  objfile->global_psymbols.next,
                                  objfile->global_psymbols.next,
                                  objfile->static_psymbols.next);
                                  objfile->static_psymbols.next);
 
 
      pst->read_symtab_private = (char *)
      pst->read_symtab_private = (char *)
        obstack_alloc (&objfile->psymbol_obstack, sizeof (struct dwarf2_pinfo));
        obstack_alloc (&objfile->psymbol_obstack, sizeof (struct dwarf2_pinfo));
      cu_header_offset = beg_of_comp_unit - dwarf_info_buffer;
      cu_header_offset = beg_of_comp_unit - dwarf_info_buffer;
      DWARF_INFO_BUFFER (pst) = dwarf_info_buffer;
      DWARF_INFO_BUFFER (pst) = dwarf_info_buffer;
      DWARF_INFO_OFFSET (pst) = beg_of_comp_unit - dwarf_info_buffer;
      DWARF_INFO_OFFSET (pst) = beg_of_comp_unit - dwarf_info_buffer;
      DWARF_ABBREV_BUFFER (pst) = dwarf_abbrev_buffer;
      DWARF_ABBREV_BUFFER (pst) = dwarf_abbrev_buffer;
      DWARF_ABBREV_SIZE (pst) = dwarf_abbrev_size;
      DWARF_ABBREV_SIZE (pst) = dwarf_abbrev_size;
      DWARF_LINE_BUFFER (pst) = dwarf_line_buffer;
      DWARF_LINE_BUFFER (pst) = dwarf_line_buffer;
      baseaddr = ANOFFSET (objfile->section_offsets, 0);
      baseaddr = ANOFFSET (objfile->section_offsets, 0);
 
 
      /* Store the function that reads in the rest of the symbol table */
      /* Store the function that reads in the rest of the symbol table */
      pst->read_symtab = dwarf2_psymtab_to_symtab;
      pst->read_symtab = dwarf2_psymtab_to_symtab;
 
 
      /* Check if comp unit has_children.
      /* Check if comp unit has_children.
         If so, read the rest of the partial symbols from this comp unit.
         If so, read the rest of the partial symbols from this comp unit.
         If not, there's no more debug_info for this comp unit. */
         If not, there's no more debug_info for this comp unit. */
      if (comp_unit_die.has_children)
      if (comp_unit_die.has_children)
        {
        {
          info_ptr = scan_partial_symbols (info_ptr, objfile, &lowpc, &highpc);
          info_ptr = scan_partial_symbols (info_ptr, objfile, &lowpc, &highpc);
 
 
          /* If the compilation unit didn't have an explicit address range,
          /* If the compilation unit didn't have an explicit address range,
             then use the information extracted from its child dies.  */
             then use the information extracted from its child dies.  */
          if (!comp_unit_has_pc_info)
          if (!comp_unit_has_pc_info)
            {
            {
              comp_unit_die.lowpc = lowpc;
              comp_unit_die.lowpc = lowpc;
              comp_unit_die.highpc = highpc;
              comp_unit_die.highpc = highpc;
            }
            }
        }
        }
      pst->textlow = comp_unit_die.lowpc + baseaddr;
      pst->textlow = comp_unit_die.lowpc + baseaddr;
      pst->texthigh = comp_unit_die.highpc + baseaddr;
      pst->texthigh = comp_unit_die.highpc + baseaddr;
 
 
      pst->n_global_syms = objfile->global_psymbols.next -
      pst->n_global_syms = objfile->global_psymbols.next -
        (objfile->global_psymbols.list + pst->globals_offset);
        (objfile->global_psymbols.list + pst->globals_offset);
      pst->n_static_syms = objfile->static_psymbols.next -
      pst->n_static_syms = objfile->static_psymbols.next -
        (objfile->static_psymbols.list + pst->statics_offset);
        (objfile->static_psymbols.list + pst->statics_offset);
      sort_pst_symbols (pst);
      sort_pst_symbols (pst);
 
 
      /* If there is already a psymtab or symtab for a file of this
      /* If there is already a psymtab or symtab for a file of this
         name, remove it. (If there is a symtab, more drastic things
         name, remove it. (If there is a symtab, more drastic things
         also happen.) This happens in VxWorks.  */
         also happen.) This happens in VxWorks.  */
      free_named_symtabs (pst->filename);
      free_named_symtabs (pst->filename);
 
 
      info_ptr = beg_of_comp_unit + cu_header.length + 4;
      info_ptr = beg_of_comp_unit + cu_header.length + 4;
    }
    }
  do_cleanups (back_to);
  do_cleanups (back_to);
}
}
 
 
/* Read in all interesting dies to the end of the compilation unit.  */
/* Read in all interesting dies to the end of the compilation unit.  */
 
 
static char *
static char *
scan_partial_symbols (info_ptr, objfile, lowpc, highpc)
scan_partial_symbols (info_ptr, objfile, lowpc, highpc)
     char *info_ptr;
     char *info_ptr;
     struct objfile *objfile;
     struct objfile *objfile;
     CORE_ADDR *lowpc;
     CORE_ADDR *lowpc;
     CORE_ADDR *highpc;
     CORE_ADDR *highpc;
{
{
  bfd *abfd = objfile->obfd;
  bfd *abfd = objfile->obfd;
  struct partial_die_info pdi;
  struct partial_die_info pdi;
 
 
  /* This function is called after we've read in the comp_unit_die in
  /* This function is called after we've read in the comp_unit_die in
     order to read its children.  We start the nesting level at 1 since
     order to read its children.  We start the nesting level at 1 since
     we have pushed 1 level down in order to read the comp unit's children.
     we have pushed 1 level down in order to read the comp unit's children.
     The comp unit itself is at level 0, so we stop reading when we pop
     The comp unit itself is at level 0, so we stop reading when we pop
     back to that level. */
     back to that level. */
 
 
  int nesting_level = 1;
  int nesting_level = 1;
  int has_pc_info;
  int has_pc_info;
 
 
  *lowpc = ((CORE_ADDR) -1);
  *lowpc = ((CORE_ADDR) -1);
  *highpc = ((CORE_ADDR) 0);
  *highpc = ((CORE_ADDR) 0);
 
 
  while (nesting_level)
  while (nesting_level)
    {
    {
      info_ptr = read_partial_die (&pdi, abfd, info_ptr, &has_pc_info);
      info_ptr = read_partial_die (&pdi, abfd, info_ptr, &has_pc_info);
 
 
      if (pdi.name)
      if (pdi.name)
        {
        {
          switch (pdi.tag)
          switch (pdi.tag)
            {
            {
            case DW_TAG_subprogram:
            case DW_TAG_subprogram:
              if (has_pc_info)
              if (has_pc_info)
                {
                {
                  if (pdi.lowpc < *lowpc)
                  if (pdi.lowpc < *lowpc)
                    {
                    {
                      *lowpc = pdi.lowpc;
                      *lowpc = pdi.lowpc;
                    }
                    }
                  if (pdi.highpc > *highpc)
                  if (pdi.highpc > *highpc)
                    {
                    {
                      *highpc = pdi.highpc;
                      *highpc = pdi.highpc;
                    }
                    }
                  if ((pdi.is_external || nesting_level == 1)
                  if ((pdi.is_external || nesting_level == 1)
                      && !pdi.is_declaration)
                      && !pdi.is_declaration)
                    {
                    {
                      add_partial_symbol (&pdi, objfile);
                      add_partial_symbol (&pdi, objfile);
                    }
                    }
                }
                }
              break;
              break;
            case DW_TAG_variable:
            case DW_TAG_variable:
            case DW_TAG_typedef:
            case DW_TAG_typedef:
            case DW_TAG_class_type:
            case DW_TAG_class_type:
            case DW_TAG_structure_type:
            case DW_TAG_structure_type:
            case DW_TAG_union_type:
            case DW_TAG_union_type:
            case DW_TAG_enumeration_type:
            case DW_TAG_enumeration_type:
              if ((pdi.is_external || nesting_level == 1)
              if ((pdi.is_external || nesting_level == 1)
                  && !pdi.is_declaration)
                  && !pdi.is_declaration)
                {
                {
                  add_partial_symbol (&pdi, objfile);
                  add_partial_symbol (&pdi, objfile);
                }
                }
              break;
              break;
            case DW_TAG_enumerator:
            case DW_TAG_enumerator:
              /* File scope enumerators are added to the partial symbol
              /* File scope enumerators are added to the partial symbol
                 table.  */
                 table.  */
              if (nesting_level == 2)
              if (nesting_level == 2)
                add_partial_symbol (&pdi, objfile);
                add_partial_symbol (&pdi, objfile);
              break;
              break;
            case DW_TAG_base_type:
            case DW_TAG_base_type:
              /* File scope base type definitions are added to the partial
              /* File scope base type definitions are added to the partial
                 symbol table.  */
                 symbol table.  */
              if (nesting_level == 1)
              if (nesting_level == 1)
                add_partial_symbol (&pdi, objfile);
                add_partial_symbol (&pdi, objfile);
              break;
              break;
            default:
            default:
              break;
              break;
            }
            }
        }
        }
 
 
      /* If the die has a sibling, skip to the sibling.
      /* If the die has a sibling, skip to the sibling.
         Do not skip enumeration types, we want to record their
         Do not skip enumeration types, we want to record their
         enumerators.  */
         enumerators.  */
      if (pdi.sibling && pdi.tag != DW_TAG_enumeration_type)
      if (pdi.sibling && pdi.tag != DW_TAG_enumeration_type)
        {
        {
          info_ptr = pdi.sibling;
          info_ptr = pdi.sibling;
        }
        }
      else if (pdi.has_children)
      else if (pdi.has_children)
        {
        {
          /* Die has children, but the optional DW_AT_sibling attribute
          /* Die has children, but the optional DW_AT_sibling attribute
             is missing.  */
             is missing.  */
          nesting_level++;
          nesting_level++;
        }
        }
 
 
      if (pdi.tag == 0)
      if (pdi.tag == 0)
        {
        {
          nesting_level--;
          nesting_level--;
        }
        }
    }
    }
 
 
  /* If we didn't find a lowpc, set it to highpc to avoid complaints
  /* If we didn't find a lowpc, set it to highpc to avoid complaints
     from `maint check'.  */
     from `maint check'.  */
  if (*lowpc == ((CORE_ADDR) -1))
  if (*lowpc == ((CORE_ADDR) -1))
    *lowpc = *highpc;
    *lowpc = *highpc;
  return info_ptr;
  return info_ptr;
}
}
 
 
static void
static void
add_partial_symbol (pdi, objfile)
add_partial_symbol (pdi, objfile)
     struct partial_die_info *pdi;
     struct partial_die_info *pdi;
     struct objfile *objfile;
     struct objfile *objfile;
{
{
  CORE_ADDR addr = 0;
  CORE_ADDR addr = 0;
 
 
  switch (pdi->tag)
  switch (pdi->tag)
    {
    {
    case DW_TAG_subprogram:
    case DW_TAG_subprogram:
      if (pdi->is_external)
      if (pdi->is_external)
        {
        {
          /*prim_record_minimal_symbol (pdi->name, pdi->lowpc + baseaddr,
          /*prim_record_minimal_symbol (pdi->name, pdi->lowpc + baseaddr,
             mst_text, objfile); */
             mst_text, objfile); */
          add_psymbol_to_list (pdi->name, strlen (pdi->name),
          add_psymbol_to_list (pdi->name, strlen (pdi->name),
                               VAR_NAMESPACE, LOC_BLOCK,
                               VAR_NAMESPACE, LOC_BLOCK,
                               &objfile->global_psymbols,
                               &objfile->global_psymbols,
                            0, pdi->lowpc + baseaddr, cu_language, objfile);
                            0, pdi->lowpc + baseaddr, cu_language, objfile);
        }
        }
      else
      else
        {
        {
          /*prim_record_minimal_symbol (pdi->name, pdi->lowpc + baseaddr,
          /*prim_record_minimal_symbol (pdi->name, pdi->lowpc + baseaddr,
             mst_file_text, objfile); */
             mst_file_text, objfile); */
          add_psymbol_to_list (pdi->name, strlen (pdi->name),
          add_psymbol_to_list (pdi->name, strlen (pdi->name),
                               VAR_NAMESPACE, LOC_BLOCK,
                               VAR_NAMESPACE, LOC_BLOCK,
                               &objfile->static_psymbols,
                               &objfile->static_psymbols,
                            0, pdi->lowpc + baseaddr, cu_language, objfile);
                            0, pdi->lowpc + baseaddr, cu_language, objfile);
        }
        }
      break;
      break;
    case DW_TAG_variable:
    case DW_TAG_variable:
      if (pdi->is_external)
      if (pdi->is_external)
        {
        {
          /* Global Variable.
          /* Global Variable.
             Don't enter into the minimal symbol tables as there is
             Don't enter into the minimal symbol tables as there is
             a minimal symbol table entry from the ELF symbols already.
             a minimal symbol table entry from the ELF symbols already.
             Enter into partial symbol table if it has a location
             Enter into partial symbol table if it has a location
             descriptor or a type.
             descriptor or a type.
             If the location descriptor is missing, new_symbol will create
             If the location descriptor is missing, new_symbol will create
             a LOC_UNRESOLVED symbol, the address of the variable will then
             a LOC_UNRESOLVED symbol, the address of the variable will then
             be determined from the minimal symbol table whenever the variable
             be determined from the minimal symbol table whenever the variable
             is referenced.
             is referenced.
             The address for the partial symbol table entry is not
             The address for the partial symbol table entry is not
             used by GDB, but it comes in handy for debugging partial symbol
             used by GDB, but it comes in handy for debugging partial symbol
             table building.  */
             table building.  */
 
 
          if (pdi->locdesc)
          if (pdi->locdesc)
            addr = decode_locdesc (pdi->locdesc, objfile);
            addr = decode_locdesc (pdi->locdesc, objfile);
          if (pdi->locdesc || pdi->has_type)
          if (pdi->locdesc || pdi->has_type)
            add_psymbol_to_list (pdi->name, strlen (pdi->name),
            add_psymbol_to_list (pdi->name, strlen (pdi->name),
                                 VAR_NAMESPACE, LOC_STATIC,
                                 VAR_NAMESPACE, LOC_STATIC,
                                 &objfile->global_psymbols,
                                 &objfile->global_psymbols,
                                 0, addr + baseaddr, cu_language, objfile);
                                 0, addr + baseaddr, cu_language, objfile);
        }
        }
      else
      else
        {
        {
          /* Static Variable. Skip symbols without location descriptors.  */
          /* Static Variable. Skip symbols without location descriptors.  */
          if (pdi->locdesc == NULL)
          if (pdi->locdesc == NULL)
            return;
            return;
          addr = decode_locdesc (pdi->locdesc, objfile);
          addr = decode_locdesc (pdi->locdesc, objfile);
          /*prim_record_minimal_symbol (pdi->name, addr + baseaddr,
          /*prim_record_minimal_symbol (pdi->name, addr + baseaddr,
             mst_file_data, objfile); */
             mst_file_data, objfile); */
          add_psymbol_to_list (pdi->name, strlen (pdi->name),
          add_psymbol_to_list (pdi->name, strlen (pdi->name),
                               VAR_NAMESPACE, LOC_STATIC,
                               VAR_NAMESPACE, LOC_STATIC,
                               &objfile->static_psymbols,
                               &objfile->static_psymbols,
                               0, addr + baseaddr, cu_language, objfile);
                               0, addr + baseaddr, cu_language, objfile);
        }
        }
      break;
      break;
    case DW_TAG_typedef:
    case DW_TAG_typedef:
    case DW_TAG_base_type:
    case DW_TAG_base_type:
      add_psymbol_to_list (pdi->name, strlen (pdi->name),
      add_psymbol_to_list (pdi->name, strlen (pdi->name),
                           VAR_NAMESPACE, LOC_TYPEDEF,
                           VAR_NAMESPACE, LOC_TYPEDEF,
                           &objfile->static_psymbols,
                           &objfile->static_psymbols,
                           0, (CORE_ADDR) 0, cu_language, objfile);
                           0, (CORE_ADDR) 0, cu_language, objfile);
      break;
      break;
    case DW_TAG_class_type:
    case DW_TAG_class_type:
    case DW_TAG_structure_type:
    case DW_TAG_structure_type:
    case DW_TAG_union_type:
    case DW_TAG_union_type:
    case DW_TAG_enumeration_type:
    case DW_TAG_enumeration_type:
      /* Skip aggregate types without children, these are external
      /* Skip aggregate types without children, these are external
         references.  */
         references.  */
      if (pdi->has_children == 0)
      if (pdi->has_children == 0)
        return;
        return;
      add_psymbol_to_list (pdi->name, strlen (pdi->name),
      add_psymbol_to_list (pdi->name, strlen (pdi->name),
                           STRUCT_NAMESPACE, LOC_TYPEDEF,
                           STRUCT_NAMESPACE, LOC_TYPEDEF,
                           &objfile->static_psymbols,
                           &objfile->static_psymbols,
                           0, (CORE_ADDR) 0, cu_language, objfile);
                           0, (CORE_ADDR) 0, cu_language, objfile);
 
 
      if (cu_language == language_cplus)
      if (cu_language == language_cplus)
        {
        {
          /* For C++, these implicitly act as typedefs as well. */
          /* For C++, these implicitly act as typedefs as well. */
          add_psymbol_to_list (pdi->name, strlen (pdi->name),
          add_psymbol_to_list (pdi->name, strlen (pdi->name),
                               VAR_NAMESPACE, LOC_TYPEDEF,
                               VAR_NAMESPACE, LOC_TYPEDEF,
                               &objfile->static_psymbols,
                               &objfile->static_psymbols,
                               0, (CORE_ADDR) 0, cu_language, objfile);
                               0, (CORE_ADDR) 0, cu_language, objfile);
        }
        }
      break;
      break;
    case DW_TAG_enumerator:
    case DW_TAG_enumerator:
      add_psymbol_to_list (pdi->name, strlen (pdi->name),
      add_psymbol_to_list (pdi->name, strlen (pdi->name),
                           VAR_NAMESPACE, LOC_CONST,
                           VAR_NAMESPACE, LOC_CONST,
                           &objfile->static_psymbols,
                           &objfile->static_psymbols,
                           0, (CORE_ADDR) 0, cu_language, objfile);
                           0, (CORE_ADDR) 0, cu_language, objfile);
      break;
      break;
    default:
    default:
      break;
      break;
    }
    }
}
}
 
 
/* Expand this partial symbol table into a full symbol table.  */
/* Expand this partial symbol table into a full symbol table.  */
 
 
static void
static void
dwarf2_psymtab_to_symtab (pst)
dwarf2_psymtab_to_symtab (pst)
     struct partial_symtab *pst;
     struct partial_symtab *pst;
{
{
  /* FIXME: This is barely more than a stub.  */
  /* FIXME: This is barely more than a stub.  */
  if (pst != NULL)
  if (pst != NULL)
    {
    {
      if (pst->readin)
      if (pst->readin)
        {
        {
          warning ("bug: psymtab for %s is already read in.", pst->filename);
          warning ("bug: psymtab for %s is already read in.", pst->filename);
        }
        }
      else
      else
        {
        {
          if (info_verbose)
          if (info_verbose)
            {
            {
              printf_filtered ("Reading in symbols for %s...", pst->filename);
              printf_filtered ("Reading in symbols for %s...", pst->filename);
              gdb_flush (gdb_stdout);
              gdb_flush (gdb_stdout);
            }
            }
 
 
          psymtab_to_symtab_1 (pst);
          psymtab_to_symtab_1 (pst);
 
 
          /* Finish up the debug error message.  */
          /* Finish up the debug error message.  */
          if (info_verbose)
          if (info_verbose)
            printf_filtered ("done.\n");
            printf_filtered ("done.\n");
        }
        }
    }
    }
}
}
 
 
static void
static void
psymtab_to_symtab_1 (pst)
psymtab_to_symtab_1 (pst)
     struct partial_symtab *pst;
     struct partial_symtab *pst;
{
{
  struct objfile *objfile = pst->objfile;
  struct objfile *objfile = pst->objfile;
  bfd *abfd = objfile->obfd;
  bfd *abfd = objfile->obfd;
  struct comp_unit_head cu_header;
  struct comp_unit_head cu_header;
  struct die_info *dies;
  struct die_info *dies;
  unsigned long offset;
  unsigned long offset;
  CORE_ADDR lowpc, highpc;
  CORE_ADDR lowpc, highpc;
  struct die_info *child_die;
  struct die_info *child_die;
  char *info_ptr;
  char *info_ptr;
  struct symtab *symtab;
  struct symtab *symtab;
  struct cleanup *back_to;
  struct cleanup *back_to;
 
 
  /* Set local variables from the partial symbol table info.  */
  /* Set local variables from the partial symbol table info.  */
  offset = DWARF_INFO_OFFSET (pst);
  offset = DWARF_INFO_OFFSET (pst);
  dwarf_info_buffer = DWARF_INFO_BUFFER (pst);
  dwarf_info_buffer = DWARF_INFO_BUFFER (pst);
  dwarf_abbrev_buffer = DWARF_ABBREV_BUFFER (pst);
  dwarf_abbrev_buffer = DWARF_ABBREV_BUFFER (pst);
  dwarf_abbrev_size = DWARF_ABBREV_SIZE (pst);
  dwarf_abbrev_size = DWARF_ABBREV_SIZE (pst);
  dwarf_line_buffer = DWARF_LINE_BUFFER (pst);
  dwarf_line_buffer = DWARF_LINE_BUFFER (pst);
  baseaddr = ANOFFSET (pst->section_offsets, 0);
  baseaddr = ANOFFSET (pst->section_offsets, 0);
  cu_header_offset = offset;
  cu_header_offset = offset;
  info_ptr = dwarf_info_buffer + offset;
  info_ptr = dwarf_info_buffer + offset;
 
 
  obstack_init (&dwarf2_tmp_obstack);
  obstack_init (&dwarf2_tmp_obstack);
  back_to = make_cleanup (dwarf2_free_tmp_obstack, NULL);
  back_to = make_cleanup (dwarf2_free_tmp_obstack, NULL);
 
 
  buildsym_init ();
  buildsym_init ();
  make_cleanup (really_free_pendings, NULL);
  make_cleanup (really_free_pendings, NULL);
 
 
  /* read in the comp_unit header  */
  /* read in the comp_unit header  */
  cu_header.length = read_4_bytes (abfd, info_ptr);
  cu_header.length = read_4_bytes (abfd, info_ptr);
  info_ptr += 4;
  info_ptr += 4;
  cu_header.version = read_2_bytes (abfd, info_ptr);
  cu_header.version = read_2_bytes (abfd, info_ptr);
  info_ptr += 2;
  info_ptr += 2;
  cu_header.abbrev_offset = read_4_bytes (abfd, info_ptr);
  cu_header.abbrev_offset = read_4_bytes (abfd, info_ptr);
  info_ptr += 4;
  info_ptr += 4;
  cu_header.addr_size = read_1_byte (abfd, info_ptr);
  cu_header.addr_size = read_1_byte (abfd, info_ptr);
  info_ptr += 1;
  info_ptr += 1;
 
 
  /* Read the abbrevs for this compilation unit  */
  /* Read the abbrevs for this compilation unit  */
  dwarf2_read_abbrevs (abfd, cu_header.abbrev_offset);
  dwarf2_read_abbrevs (abfd, cu_header.abbrev_offset);
  make_cleanup (dwarf2_empty_abbrev_table, NULL);
  make_cleanup (dwarf2_empty_abbrev_table, NULL);
 
 
  dies = read_comp_unit (info_ptr, abfd);
  dies = read_comp_unit (info_ptr, abfd);
 
 
  make_cleanup ((make_cleanup_func) free_die_list, dies);
  make_cleanup ((make_cleanup_func) free_die_list, dies);
 
 
  /* Do line number decoding in read_file_scope () */
  /* Do line number decoding in read_file_scope () */
  process_die (dies, objfile);
  process_die (dies, objfile);
 
 
  if (!dwarf2_get_pc_bounds (dies, &lowpc, &highpc, objfile))
  if (!dwarf2_get_pc_bounds (dies, &lowpc, &highpc, objfile))
    {
    {
      /* Some compilers don't define a DW_AT_high_pc attribute for
      /* Some compilers don't define a DW_AT_high_pc attribute for
         the compilation unit.   If the DW_AT_high_pc is missing,
         the compilation unit.   If the DW_AT_high_pc is missing,
         synthesize it, by scanning the DIE's below the compilation unit.  */
         synthesize it, by scanning the DIE's below the compilation unit.  */
      highpc = 0;
      highpc = 0;
      if (dies->has_children)
      if (dies->has_children)
        {
        {
          child_die = dies->next;
          child_die = dies->next;
          while (child_die && child_die->tag)
          while (child_die && child_die->tag)
            {
            {
              if (child_die->tag == DW_TAG_subprogram)
              if (child_die->tag == DW_TAG_subprogram)
                {
                {
                  CORE_ADDR low, high;
                  CORE_ADDR low, high;
 
 
                  if (dwarf2_get_pc_bounds (child_die, &low, &high, objfile))
                  if (dwarf2_get_pc_bounds (child_die, &low, &high, objfile))
                    {
                    {
                      highpc = max (highpc, high);
                      highpc = max (highpc, high);
                    }
                    }
                }
                }
              child_die = sibling_die (child_die);
              child_die = sibling_die (child_die);
            }
            }
        }
        }
    }
    }
  symtab = end_symtab (highpc + baseaddr, objfile, 0);
  symtab = end_symtab (highpc + baseaddr, objfile, 0);
 
 
  /* Set symtab language to language from DW_AT_language.
  /* Set symtab language to language from DW_AT_language.
     If the compilation is from a C file generated by language preprocessors,
     If the compilation is from a C file generated by language preprocessors,
     do not set the language if it was already deduced by start_subfile.  */
     do not set the language if it was already deduced by start_subfile.  */
  if (symtab != NULL
  if (symtab != NULL
      && !(cu_language == language_c && symtab->language != language_c))
      && !(cu_language == language_c && symtab->language != language_c))
    {
    {
      symtab->language = cu_language;
      symtab->language = cu_language;
    }
    }
  pst->symtab = symtab;
  pst->symtab = symtab;
  pst->readin = 1;
  pst->readin = 1;
  sort_symtab_syms (pst->symtab);
  sort_symtab_syms (pst->symtab);
 
 
  do_cleanups (back_to);
  do_cleanups (back_to);
}
}
 
 
/* Process a die and its children.  */
/* Process a die and its children.  */
 
 
static void
static void
process_die (die, objfile)
process_die (die, objfile)
     struct die_info *die;
     struct die_info *die;
     struct objfile *objfile;
     struct objfile *objfile;
{
{
  switch (die->tag)
  switch (die->tag)
    {
    {
    case DW_TAG_padding:
    case DW_TAG_padding:
      break;
      break;
    case DW_TAG_compile_unit:
    case DW_TAG_compile_unit:
      read_file_scope (die, objfile);
      read_file_scope (die, objfile);
      break;
      break;
    case DW_TAG_subprogram:
    case DW_TAG_subprogram:
      read_subroutine_type (die, objfile);
      read_subroutine_type (die, objfile);
      read_func_scope (die, objfile);
      read_func_scope (die, objfile);
      break;
      break;
    case DW_TAG_inlined_subroutine:
    case DW_TAG_inlined_subroutine:
      /* FIXME:  These are ignored for now.
      /* FIXME:  These are ignored for now.
         They could be used to set breakpoints on all inlined instances
         They could be used to set breakpoints on all inlined instances
         of a function and make GDB `next' properly over inlined functions.  */
         of a function and make GDB `next' properly over inlined functions.  */
      break;
      break;
    case DW_TAG_lexical_block:
    case DW_TAG_lexical_block:
      read_lexical_block_scope (die, objfile);
      read_lexical_block_scope (die, objfile);
      break;
      break;
    case DW_TAG_class_type:
    case DW_TAG_class_type:
    case DW_TAG_structure_type:
    case DW_TAG_structure_type:
    case DW_TAG_union_type:
    case DW_TAG_union_type:
      read_structure_scope (die, objfile);
      read_structure_scope (die, objfile);
      break;
      break;
    case DW_TAG_enumeration_type:
    case DW_TAG_enumeration_type:
      read_enumeration (die, objfile);
      read_enumeration (die, objfile);
      break;
      break;
    case DW_TAG_subroutine_type:
    case DW_TAG_subroutine_type:
      read_subroutine_type (die, objfile);
      read_subroutine_type (die, objfile);
      break;
      break;
    case DW_TAG_array_type:
    case DW_TAG_array_type:
      read_array_type (die, objfile);
      read_array_type (die, objfile);
      break;
      break;
    case DW_TAG_pointer_type:
    case DW_TAG_pointer_type:
      read_tag_pointer_type (die, objfile);
      read_tag_pointer_type (die, objfile);
      break;
      break;
    case DW_TAG_ptr_to_member_type:
    case DW_TAG_ptr_to_member_type:
      read_tag_ptr_to_member_type (die, objfile);
      read_tag_ptr_to_member_type (die, objfile);
      break;
      break;
    case DW_TAG_reference_type:
    case DW_TAG_reference_type:
      read_tag_reference_type (die, objfile);
      read_tag_reference_type (die, objfile);
      break;
      break;
    case DW_TAG_string_type:
    case DW_TAG_string_type:
      read_tag_string_type (die, objfile);
      read_tag_string_type (die, objfile);
      break;
      break;
    case DW_TAG_base_type:
    case DW_TAG_base_type:
      read_base_type (die, objfile);
      read_base_type (die, objfile);
      if (dwarf_attr (die, DW_AT_name))
      if (dwarf_attr (die, DW_AT_name))
        {
        {
          /* Add a typedef symbol for the base type definition.  */
          /* Add a typedef symbol for the base type definition.  */
          new_symbol (die, die->type, objfile);
          new_symbol (die, die->type, objfile);
        }
        }
      break;
      break;
    case DW_TAG_common_block:
    case DW_TAG_common_block:
      read_common_block (die, objfile);
      read_common_block (die, objfile);
      break;
      break;
    case DW_TAG_common_inclusion:
    case DW_TAG_common_inclusion:
      break;
      break;
    default:
    default:
      new_symbol (die, NULL, objfile);
      new_symbol (die, NULL, objfile);
      break;
      break;
    }
    }
}
}
 
 
static void
static void
read_file_scope (die, objfile)
read_file_scope (die, objfile)
     struct die_info *die;
     struct die_info *die;
     struct objfile *objfile;
     struct objfile *objfile;
{
{
  unsigned int line_offset = 0;
  unsigned int line_offset = 0;
  CORE_ADDR lowpc = ((CORE_ADDR) -1);
  CORE_ADDR lowpc = ((CORE_ADDR) -1);
  CORE_ADDR highpc = ((CORE_ADDR) 0);
  CORE_ADDR highpc = ((CORE_ADDR) 0);
  struct attribute *attr;
  struct attribute *attr;
  char *name = "<unknown>";
  char *name = "<unknown>";
  char *comp_dir = NULL;
  char *comp_dir = NULL;
  struct die_info *child_die;
  struct die_info *child_die;
  bfd *abfd = objfile->obfd;
  bfd *abfd = objfile->obfd;
 
 
  if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile))
  if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile))
    {
    {
      if (die->has_children)
      if (die->has_children)
        {
        {
          child_die = die->next;
          child_die = die->next;
          while (child_die && child_die->tag)
          while (child_die && child_die->tag)
            {
            {
              if (child_die->tag == DW_TAG_subprogram)
              if (child_die->tag == DW_TAG_subprogram)
                {
                {
                  CORE_ADDR low, high;
                  CORE_ADDR low, high;
 
 
                  if (dwarf2_get_pc_bounds (child_die, &low, &high, objfile))
                  if (dwarf2_get_pc_bounds (child_die, &low, &high, objfile))
                    {
                    {
                      lowpc = min (lowpc, low);
                      lowpc = min (lowpc, low);
                      highpc = max (highpc, high);
                      highpc = max (highpc, high);
                    }
                    }
                }
                }
              child_die = sibling_die (child_die);
              child_die = sibling_die (child_die);
            }
            }
        }
        }
    }
    }
 
 
  /* If we didn't find a lowpc, set it to highpc to avoid complaints
  /* If we didn't find a lowpc, set it to highpc to avoid complaints
     from finish_block.  */
     from finish_block.  */
  if (lowpc == ((CORE_ADDR) -1))
  if (lowpc == ((CORE_ADDR) -1))
    lowpc = highpc;
    lowpc = highpc;
  lowpc += baseaddr;
  lowpc += baseaddr;
  highpc += baseaddr;
  highpc += baseaddr;
 
 
  attr = dwarf_attr (die, DW_AT_name);
  attr = dwarf_attr (die, DW_AT_name);
  if (attr)
  if (attr)
    {
    {
      name = DW_STRING (attr);
      name = DW_STRING (attr);
    }
    }
  attr = dwarf_attr (die, DW_AT_comp_dir);
  attr = dwarf_attr (die, DW_AT_comp_dir);
  if (attr)
  if (attr)
    {
    {
      comp_dir = DW_STRING (attr);
      comp_dir = DW_STRING (attr);
      if (comp_dir)
      if (comp_dir)
        {
        {
          /* Irix 6.2 native cc prepends <machine>.: to the compilation
          /* Irix 6.2 native cc prepends <machine>.: to the compilation
             directory, get rid of it.  */
             directory, get rid of it.  */
          char *cp = strchr (comp_dir, ':');
          char *cp = strchr (comp_dir, ':');
 
 
          if (cp && cp != comp_dir && cp[-1] == '.' && cp[1] == '/')
          if (cp && cp != comp_dir && cp[-1] == '.' && cp[1] == '/')
            comp_dir = cp + 1;
            comp_dir = cp + 1;
        }
        }
    }
    }
 
 
  if (objfile->ei.entry_point >= lowpc &&
  if (objfile->ei.entry_point >= lowpc &&
      objfile->ei.entry_point < highpc)
      objfile->ei.entry_point < highpc)
    {
    {
      objfile->ei.entry_file_lowpc = lowpc;
      objfile->ei.entry_file_lowpc = lowpc;
      objfile->ei.entry_file_highpc = highpc;
      objfile->ei.entry_file_highpc = highpc;
    }
    }
 
 
  attr = dwarf_attr (die, DW_AT_language);
  attr = dwarf_attr (die, DW_AT_language);
  if (attr)
  if (attr)
    {
    {
      set_cu_language (DW_UNSND (attr));
      set_cu_language (DW_UNSND (attr));
    }
    }
 
 
  /* We assume that we're processing GCC output. */
  /* We assume that we're processing GCC output. */
  processing_gcc_compilation = 2;
  processing_gcc_compilation = 2;
#if 0
#if 0
  /* FIXME:Do something here.  */
  /* FIXME:Do something here.  */
  if (dip->at_producer != NULL)
  if (dip->at_producer != NULL)
    {
    {
      handle_producer (dip->at_producer);
      handle_producer (dip->at_producer);
    }
    }
#endif
#endif
 
 
  /* The compilation unit may be in a different language or objfile,
  /* The compilation unit may be in a different language or objfile,
     zero out all remembered fundamental types.  */
     zero out all remembered fundamental types.  */
  memset (ftypes, 0, FT_NUM_MEMBERS * sizeof (struct type *));
  memset (ftypes, 0, FT_NUM_MEMBERS * sizeof (struct type *));
 
 
  start_symtab (name, comp_dir, lowpc);
  start_symtab (name, comp_dir, lowpc);
  record_debugformat ("DWARF 2");
  record_debugformat ("DWARF 2");
 
 
  /* Decode line number information if present.  */
  /* Decode line number information if present.  */
  attr = dwarf_attr (die, DW_AT_stmt_list);
  attr = dwarf_attr (die, DW_AT_stmt_list);
  if (attr)
  if (attr)
    {
    {
      line_offset = DW_UNSND (attr);
      line_offset = DW_UNSND (attr);
      dwarf_decode_lines (line_offset, comp_dir, abfd);
      dwarf_decode_lines (line_offset, comp_dir, abfd);
    }
    }
 
 
  /* Process all dies in compilation unit.  */
  /* Process all dies in compilation unit.  */
  if (die->has_children)
  if (die->has_children)
    {
    {
      child_die = die->next;
      child_die = die->next;
      while (child_die && child_die->tag)
      while (child_die && child_die->tag)
        {
        {
          process_die (child_die, objfile);
          process_die (child_die, objfile);
          child_die = sibling_die (child_die);
          child_die = sibling_die (child_die);
        }
        }
    }
    }
}
}
 
 
static void
static void
read_func_scope (die, objfile)
read_func_scope (die, objfile)
     struct die_info *die;
     struct die_info *die;
     struct objfile *objfile;
     struct objfile *objfile;
{
{
  register struct context_stack *new;
  register struct context_stack *new;
  CORE_ADDR lowpc;
  CORE_ADDR lowpc;
  CORE_ADDR highpc;
  CORE_ADDR highpc;
  struct die_info *child_die;
  struct die_info *child_die;
  struct attribute *attr;
  struct attribute *attr;
  char *name;
  char *name;
 
 
  name = dwarf2_linkage_name (die);
  name = dwarf2_linkage_name (die);
 
 
  /* Ignore functions with missing or empty names and functions with
  /* Ignore functions with missing or empty names and functions with
     missing or invalid low and high pc attributes.  */
     missing or invalid low and high pc attributes.  */
  if (name == NULL || !dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile))
  if (name == NULL || !dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile))
    return;
    return;
 
 
  lowpc += baseaddr;
  lowpc += baseaddr;
  highpc += baseaddr;
  highpc += baseaddr;
 
 
  if (objfile->ei.entry_point >= lowpc &&
  if (objfile->ei.entry_point >= lowpc &&
      objfile->ei.entry_point < highpc)
      objfile->ei.entry_point < highpc)
    {
    {
      objfile->ei.entry_func_lowpc = lowpc;
      objfile->ei.entry_func_lowpc = lowpc;
      objfile->ei.entry_func_highpc = highpc;
      objfile->ei.entry_func_highpc = highpc;
    }
    }
 
 
  /* Decode DW_AT_frame_base location descriptor if present, keep result
  /* Decode DW_AT_frame_base location descriptor if present, keep result
     for DW_OP_fbreg operands in decode_locdesc.  */
     for DW_OP_fbreg operands in decode_locdesc.  */
  frame_base_reg = -1;
  frame_base_reg = -1;
  frame_base_offset = 0;
  frame_base_offset = 0;
  attr = dwarf_attr (die, DW_AT_frame_base);
  attr = dwarf_attr (die, DW_AT_frame_base);
  if (attr)
  if (attr)
    {
    {
      CORE_ADDR addr = decode_locdesc (DW_BLOCK (attr), objfile);
      CORE_ADDR addr = decode_locdesc (DW_BLOCK (attr), objfile);
      if (isderef)
      if (isderef)
        complain (&dwarf2_unsupported_at_frame_base, name);
        complain (&dwarf2_unsupported_at_frame_base, name);
      else if (isreg)
      else if (isreg)
        frame_base_reg = addr;
        frame_base_reg = addr;
      else if (offreg)
      else if (offreg)
        {
        {
          frame_base_reg = basereg;
          frame_base_reg = basereg;
          frame_base_offset = addr;
          frame_base_offset = addr;
        }
        }
      else
      else
        complain (&dwarf2_unsupported_at_frame_base, name);
        complain (&dwarf2_unsupported_at_frame_base, name);
    }
    }
 
 
  new = push_context (0, lowpc);
  new = push_context (0, lowpc);
  new->name = new_symbol (die, die->type, objfile);
  new->name = new_symbol (die, die->type, objfile);
  list_in_scope = &local_symbols;
  list_in_scope = &local_symbols;
 
 
  if (die->has_children)
  if (die->has_children)
    {
    {
      child_die = die->next;
      child_die = die->next;
      while (child_die && child_die->tag)
      while (child_die && child_die->tag)
        {
        {
          process_die (child_die, objfile);
          process_die (child_die, objfile);
          child_die = sibling_die (child_die);
          child_die = sibling_die (child_die);
        }
        }
    }
    }
 
 
  new = pop_context ();
  new = pop_context ();
  /* Make a block for the local symbols within.  */
  /* Make a block for the local symbols within.  */
  finish_block (new->name, &local_symbols, new->old_blocks,
  finish_block (new->name, &local_symbols, new->old_blocks,
                lowpc, highpc, objfile);
                lowpc, highpc, objfile);
  list_in_scope = &file_symbols;
  list_in_scope = &file_symbols;
}
}
 
 
/* Process all the DIES contained within a lexical block scope.  Start
/* Process all the DIES contained within a lexical block scope.  Start
   a new scope, process the dies, and then close the scope.  */
   a new scope, process the dies, and then close the scope.  */
 
 
static void
static void
read_lexical_block_scope (die, objfile)
read_lexical_block_scope (die, objfile)
     struct die_info *die;
     struct die_info *die;
     struct objfile *objfile;
     struct objfile *objfile;
{
{
  register struct context_stack *new;
  register struct context_stack *new;
  CORE_ADDR lowpc, highpc;
  CORE_ADDR lowpc, highpc;
  struct die_info *child_die;
  struct die_info *child_die;
 
 
  /* Ignore blocks with missing or invalid low and high pc attributes.  */
  /* Ignore blocks with missing or invalid low and high pc attributes.  */
  if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile))
  if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile))
    return;
    return;
  lowpc += baseaddr;
  lowpc += baseaddr;
  highpc += baseaddr;
  highpc += baseaddr;
 
 
  push_context (0, lowpc);
  push_context (0, lowpc);
  if (die->has_children)
  if (die->has_children)
    {
    {
      child_die = die->next;
      child_die = die->next;
      while (child_die && child_die->tag)
      while (child_die && child_die->tag)
        {
        {
          process_die (child_die, objfile);
          process_die (child_die, objfile);
          child_die = sibling_die (child_die);
          child_die = sibling_die (child_die);
        }
        }
    }
    }
  new = pop_context ();
  new = pop_context ();
 
 
  if (local_symbols != NULL)
  if (local_symbols != NULL)
    {
    {
      finish_block (0, &local_symbols, new->old_blocks, new->start_addr,
      finish_block (0, &local_symbols, new->old_blocks, new->start_addr,
                    highpc, objfile);
                    highpc, objfile);
    }
    }
  local_symbols = new->locals;
  local_symbols = new->locals;
}
}
 
 
/* Get low and high pc attributes from a die.
/* Get low and high pc attributes from a die.
   Return 1 if the attributes are present and valid, otherwise, return 0.  */
   Return 1 if the attributes are present and valid, otherwise, return 0.  */
 
 
static int
static int
dwarf2_get_pc_bounds (die, lowpc, highpc, objfile)
dwarf2_get_pc_bounds (die, lowpc, highpc, objfile)
     struct die_info *die;
     struct die_info *die;
     CORE_ADDR *lowpc;
     CORE_ADDR *lowpc;
     CORE_ADDR *highpc;
     CORE_ADDR *highpc;
     struct objfile *objfile;
     struct objfile *objfile;
{
{
  struct attribute *attr;
  struct attribute *attr;
  CORE_ADDR low;
  CORE_ADDR low;
  CORE_ADDR high;
  CORE_ADDR high;
 
 
  attr = dwarf_attr (die, DW_AT_low_pc);
  attr = dwarf_attr (die, DW_AT_low_pc);
  if (attr)
  if (attr)
    low = DW_ADDR (attr);
    low = DW_ADDR (attr);
  else
  else
    return 0;
    return 0;
  attr = dwarf_attr (die, DW_AT_high_pc);
  attr = dwarf_attr (die, DW_AT_high_pc);
  if (attr)
  if (attr)
    high = DW_ADDR (attr);
    high = DW_ADDR (attr);
  else
  else
    return 0;
    return 0;
 
 
  if (high < low)
  if (high < low)
    return 0;
    return 0;
 
 
  /* When using the GNU linker, .gnu.linkonce. sections are used to
  /* When using the GNU linker, .gnu.linkonce. sections are used to
     eliminate duplicate copies of functions and vtables and such.
     eliminate duplicate copies of functions and vtables and such.
     The linker will arbitrarily choose one and discard the others.
     The linker will arbitrarily choose one and discard the others.
     The AT_*_pc values for such functions refer to local labels in
     The AT_*_pc values for such functions refer to local labels in
     these sections.  If the section from that file was discarded, the
     these sections.  If the section from that file was discarded, the
     labels are not in the output, so the relocs get a value of 0.
     labels are not in the output, so the relocs get a value of 0.
     If this is a discarded function, mark the pc bounds as invalid,
     If this is a discarded function, mark the pc bounds as invalid,
     so that GDB will ignore it.  */
     so that GDB will ignore it.  */
  if (low == 0 && (bfd_get_file_flags (objfile->obfd) & HAS_RELOC) == 0)
  if (low == 0 && (bfd_get_file_flags (objfile->obfd) & HAS_RELOC) == 0)
    return 0;
    return 0;
 
 
  *lowpc = low;
  *lowpc = low;
  *highpc = high;
  *highpc = high;
  return 1;
  return 1;
}
}
 
 
/* Add an aggregate field to the field list.  */
/* Add an aggregate field to the field list.  */
 
 
static void
static void
dwarf2_add_field (fip, die, objfile)
dwarf2_add_field (fip, die, objfile)
     struct field_info *fip;
     struct field_info *fip;
     struct die_info *die;
     struct die_info *die;
     struct objfile *objfile;
     struct objfile *objfile;
{
{
  struct nextfield *new_field;
  struct nextfield *new_field;
  struct attribute *attr;
  struct attribute *attr;
  struct field *fp;
  struct field *fp;
  char *fieldname = "";
  char *fieldname = "";
 
 
  /* Allocate a new field list entry and link it in.  */
  /* Allocate a new field list entry and link it in.  */
  new_field = (struct nextfield *) xmalloc (sizeof (struct nextfield));
  new_field = (struct nextfield *) xmalloc (sizeof (struct nextfield));
  make_cleanup (free, new_field);
  make_cleanup (free, new_field);
  memset (new_field, 0, sizeof (struct nextfield));
  memset (new_field, 0, sizeof (struct nextfield));
  new_field->next = fip->fields;
  new_field->next = fip->fields;
  fip->fields = new_field;
  fip->fields = new_field;
  fip->nfields++;
  fip->nfields++;
 
 
  /* Handle accessibility and virtuality of field.
  /* Handle accessibility and virtuality of field.
     The default accessibility for members is public, the default
     The default accessibility for members is public, the default
     accessibility for inheritance is private.  */
     accessibility for inheritance is private.  */
  if (die->tag != DW_TAG_inheritance)
  if (die->tag != DW_TAG_inheritance)
    new_field->accessibility = DW_ACCESS_public;
    new_field->accessibility = DW_ACCESS_public;
  else
  else
    new_field->accessibility = DW_ACCESS_private;
    new_field->accessibility = DW_ACCESS_private;
  new_field->virtuality = DW_VIRTUALITY_none;
  new_field->virtuality = DW_VIRTUALITY_none;
 
 
  attr = dwarf_attr (die, DW_AT_accessibility);
  attr = dwarf_attr (die, DW_AT_accessibility);
  if (attr)
  if (attr)
    new_field->accessibility = DW_UNSND (attr);
    new_field->accessibility = DW_UNSND (attr);
  if (new_field->accessibility != DW_ACCESS_public)
  if (new_field->accessibility != DW_ACCESS_public)
    fip->non_public_fields = 1;
    fip->non_public_fields = 1;
  attr = dwarf_attr (die, DW_AT_virtuality);
  attr = dwarf_attr (die, DW_AT_virtuality);
  if (attr)
  if (attr)
    new_field->virtuality = DW_UNSND (attr);
    new_field->virtuality = DW_UNSND (attr);
 
 
  fp = &new_field->field;
  fp = &new_field->field;
  if (die->tag == DW_TAG_member)
  if (die->tag == DW_TAG_member)
    {
    {
      /* Get type of field.  */
      /* Get type of field.  */
      fp->type = die_type (die, objfile);
      fp->type = die_type (die, objfile);
 
 
      /* Get bit size of field (zero if none).  */
      /* Get bit size of field (zero if none).  */
      attr = dwarf_attr (die, DW_AT_bit_size);
      attr = dwarf_attr (die, DW_AT_bit_size);
      if (attr)
      if (attr)
        {
        {
          FIELD_BITSIZE (*fp) = DW_UNSND (attr);
          FIELD_BITSIZE (*fp) = DW_UNSND (attr);
        }
        }
      else
      else
        {
        {
          FIELD_BITSIZE (*fp) = 0;
          FIELD_BITSIZE (*fp) = 0;
        }
        }
 
 
      /* Get bit offset of field.  */
      /* Get bit offset of field.  */
      attr = dwarf_attr (die, DW_AT_data_member_location);
      attr = dwarf_attr (die, DW_AT_data_member_location);
      if (attr)
      if (attr)
        {
        {
          FIELD_BITPOS (*fp) =
          FIELD_BITPOS (*fp) =
            decode_locdesc (DW_BLOCK (attr), objfile) * bits_per_byte;
            decode_locdesc (DW_BLOCK (attr), objfile) * bits_per_byte;
        }
        }
      else
      else
        FIELD_BITPOS (*fp) = 0;
        FIELD_BITPOS (*fp) = 0;
      attr = dwarf_attr (die, DW_AT_bit_offset);
      attr = dwarf_attr (die, DW_AT_bit_offset);
      if (attr)
      if (attr)
        {
        {
          if (BITS_BIG_ENDIAN)
          if (BITS_BIG_ENDIAN)
            {
            {
              /* For big endian bits, the DW_AT_bit_offset gives the
              /* For big endian bits, the DW_AT_bit_offset gives the
                 additional bit offset from the MSB of the containing
                 additional bit offset from the MSB of the containing
                 anonymous object to the MSB of the field.  We don't
                 anonymous object to the MSB of the field.  We don't
                 have to do anything special since we don't need to
                 have to do anything special since we don't need to
                 know the size of the anonymous object.  */
                 know the size of the anonymous object.  */
              FIELD_BITPOS (*fp) += DW_UNSND (attr);
              FIELD_BITPOS (*fp) += DW_UNSND (attr);
            }
            }
          else
          else
            {
            {
              /* For little endian bits, compute the bit offset to the
              /* For little endian bits, compute the bit offset to the
                 MSB of the anonymous object, subtract off the number of
                 MSB of the anonymous object, subtract off the number of
                 bits from the MSB of the field to the MSB of the
                 bits from the MSB of the field to the MSB of the
                 object, and then subtract off the number of bits of
                 object, and then subtract off the number of bits of
                 the field itself.  The result is the bit offset of
                 the field itself.  The result is the bit offset of
                 the LSB of the field.  */
                 the LSB of the field.  */
              int anonymous_size;
              int anonymous_size;
              int bit_offset = DW_UNSND (attr);
              int bit_offset = DW_UNSND (attr);
 
 
              attr = dwarf_attr (die, DW_AT_byte_size);
              attr = dwarf_attr (die, DW_AT_byte_size);
              if (attr)
              if (attr)
                {
                {
                  /* The size of the anonymous object containing
                  /* The size of the anonymous object containing
                     the bit field is explicit, so use the
                     the bit field is explicit, so use the
                     indicated size (in bytes).  */
                     indicated size (in bytes).  */
                  anonymous_size = DW_UNSND (attr);
                  anonymous_size = DW_UNSND (attr);
                }
                }
              else
              else
                {
                {
                  /* The size of the anonymous object containing
                  /* The size of the anonymous object containing
                     the bit field must be inferred from the type
                     the bit field must be inferred from the type
                     attribute of the data member containing the
                     attribute of the data member containing the
                     bit field.  */
                     bit field.  */
                  anonymous_size = TYPE_LENGTH (fp->type);
                  anonymous_size = TYPE_LENGTH (fp->type);
                }
                }
              FIELD_BITPOS (*fp) += anonymous_size * bits_per_byte
              FIELD_BITPOS (*fp) += anonymous_size * bits_per_byte
                - bit_offset - FIELD_BITSIZE (*fp);
                - bit_offset - FIELD_BITSIZE (*fp);
            }
            }
        }
        }
 
 
      /* Get name of field.  */
      /* Get name of field.  */
      attr = dwarf_attr (die, DW_AT_name);
      attr = dwarf_attr (die, DW_AT_name);
      if (attr && DW_STRING (attr))
      if (attr && DW_STRING (attr))
        fieldname = DW_STRING (attr);
        fieldname = DW_STRING (attr);
      fp->name = obsavestring (fieldname, strlen (fieldname),
      fp->name = obsavestring (fieldname, strlen (fieldname),
                               &objfile->type_obstack);
                               &objfile->type_obstack);
 
 
      /* Change accessibility for artificial fields (e.g. virtual table
      /* Change accessibility for artificial fields (e.g. virtual table
         pointer or virtual base class pointer) to private.  */
         pointer or virtual base class pointer) to private.  */
      if (dwarf_attr (die, DW_AT_artificial))
      if (dwarf_attr (die, DW_AT_artificial))
        {
        {
          new_field->accessibility = DW_ACCESS_private;
          new_field->accessibility = DW_ACCESS_private;
          fip->non_public_fields = 1;
          fip->non_public_fields = 1;
        }
        }
    }
    }
  else if (die->tag == DW_TAG_variable)
  else if (die->tag == DW_TAG_variable)
    {
    {
      char *physname;
      char *physname;
 
 
      /* C++ static member.
      /* C++ static member.
         Get name of field.  */
         Get name of field.  */
      attr = dwarf_attr (die, DW_AT_name);
      attr = dwarf_attr (die, DW_AT_name);
      if (attr && DW_STRING (attr))
      if (attr && DW_STRING (attr))
        fieldname = DW_STRING (attr);
        fieldname = DW_STRING (attr);
      else
      else
        return;
        return;
 
 
      /* Get physical name.  */
      /* Get physical name.  */
      physname = dwarf2_linkage_name (die);
      physname = dwarf2_linkage_name (die);
 
 
      SET_FIELD_PHYSNAME (*fp, obsavestring (physname, strlen (physname),
      SET_FIELD_PHYSNAME (*fp, obsavestring (physname, strlen (physname),
                                             &objfile->type_obstack));
                                             &objfile->type_obstack));
      FIELD_TYPE (*fp) = die_type (die, objfile);
      FIELD_TYPE (*fp) = die_type (die, objfile);
      FIELD_NAME (*fp) = obsavestring (fieldname, strlen (fieldname),
      FIELD_NAME (*fp) = obsavestring (fieldname, strlen (fieldname),
                                       &objfile->type_obstack);
                                       &objfile->type_obstack);
    }
    }
  else if (die->tag == DW_TAG_inheritance)
  else if (die->tag == DW_TAG_inheritance)
    {
    {
      /* C++ base class field.  */
      /* C++ base class field.  */
      attr = dwarf_attr (die, DW_AT_data_member_location);
      attr = dwarf_attr (die, DW_AT_data_member_location);
      if (attr)
      if (attr)
        FIELD_BITPOS (*fp) = decode_locdesc (DW_BLOCK (attr), objfile) * bits_per_byte;
        FIELD_BITPOS (*fp) = decode_locdesc (DW_BLOCK (attr), objfile) * bits_per_byte;
      FIELD_BITSIZE (*fp) = 0;
      FIELD_BITSIZE (*fp) = 0;
      FIELD_TYPE (*fp) = die_type (die, objfile);
      FIELD_TYPE (*fp) = die_type (die, objfile);
      FIELD_NAME (*fp) = type_name_no_tag (fp->type);
      FIELD_NAME (*fp) = type_name_no_tag (fp->type);
      fip->nbaseclasses++;
      fip->nbaseclasses++;
    }
    }
}
}
 
 
/* Create the vector of fields, and attach it to the type.  */
/* Create the vector of fields, and attach it to the type.  */
 
 
static void
static void
dwarf2_attach_fields_to_type (fip, type, objfile)
dwarf2_attach_fields_to_type (fip, type, objfile)
     struct field_info *fip;
     struct field_info *fip;
     struct type *type;
     struct type *type;
     struct objfile *objfile;
     struct objfile *objfile;
{
{
  int nfields = fip->nfields;
  int nfields = fip->nfields;
 
 
  /* Record the field count, allocate space for the array of fields,
  /* Record the field count, allocate space for the array of fields,
     and create blank accessibility bitfields if necessary.  */
     and create blank accessibility bitfields if necessary.  */
  TYPE_NFIELDS (type) = nfields;
  TYPE_NFIELDS (type) = nfields;
  TYPE_FIELDS (type) = (struct field *)
  TYPE_FIELDS (type) = (struct field *)
    TYPE_ALLOC (type, sizeof (struct field) * nfields);
    TYPE_ALLOC (type, sizeof (struct field) * nfields);
  memset (TYPE_FIELDS (type), 0, sizeof (struct field) * nfields);
  memset (TYPE_FIELDS (type), 0, sizeof (struct field) * nfields);
 
 
  if (fip->non_public_fields)
  if (fip->non_public_fields)
    {
    {
      ALLOCATE_CPLUS_STRUCT_TYPE (type);
      ALLOCATE_CPLUS_STRUCT_TYPE (type);
 
 
      TYPE_FIELD_PRIVATE_BITS (type) =
      TYPE_FIELD_PRIVATE_BITS (type) =
        (B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields));
        (B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields));
      B_CLRALL (TYPE_FIELD_PRIVATE_BITS (type), nfields);
      B_CLRALL (TYPE_FIELD_PRIVATE_BITS (type), nfields);
 
 
      TYPE_FIELD_PROTECTED_BITS (type) =
      TYPE_FIELD_PROTECTED_BITS (type) =
        (B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields));
        (B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields));
      B_CLRALL (TYPE_FIELD_PROTECTED_BITS (type), nfields);
      B_CLRALL (TYPE_FIELD_PROTECTED_BITS (type), nfields);
 
 
      TYPE_FIELD_IGNORE_BITS (type) =
      TYPE_FIELD_IGNORE_BITS (type) =
        (B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields));
        (B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields));
      B_CLRALL (TYPE_FIELD_IGNORE_BITS (type), nfields);
      B_CLRALL (TYPE_FIELD_IGNORE_BITS (type), nfields);
    }
    }
 
 
  /* If the type has baseclasses, allocate and clear a bit vector for
  /* If the type has baseclasses, allocate and clear a bit vector for
     TYPE_FIELD_VIRTUAL_BITS.  */
     TYPE_FIELD_VIRTUAL_BITS.  */
  if (fip->nbaseclasses)
  if (fip->nbaseclasses)
    {
    {
      int num_bytes = B_BYTES (fip->nbaseclasses);
      int num_bytes = B_BYTES (fip->nbaseclasses);
      char *pointer;
      char *pointer;
 
 
      ALLOCATE_CPLUS_STRUCT_TYPE (type);
      ALLOCATE_CPLUS_STRUCT_TYPE (type);
      pointer = (char *) TYPE_ALLOC (type, num_bytes);
      pointer = (char *) TYPE_ALLOC (type, num_bytes);
      TYPE_FIELD_VIRTUAL_BITS (type) = (B_TYPE *) pointer;
      TYPE_FIELD_VIRTUAL_BITS (type) = (B_TYPE *) pointer;
      B_CLRALL (TYPE_FIELD_VIRTUAL_BITS (type), fip->nbaseclasses);
      B_CLRALL (TYPE_FIELD_VIRTUAL_BITS (type), fip->nbaseclasses);
      TYPE_N_BASECLASSES (type) = fip->nbaseclasses;
      TYPE_N_BASECLASSES (type) = fip->nbaseclasses;
    }
    }
 
 
  /* Copy the saved-up fields into the field vector.  Start from the head
  /* Copy the saved-up fields into the field vector.  Start from the head
     of the list, adding to the tail of the field array, so that they end
     of the list, adding to the tail of the field array, so that they end
     up in the same order in the array in which they were added to the list.  */
     up in the same order in the array in which they were added to the list.  */
  while (nfields-- > 0)
  while (nfields-- > 0)
    {
    {
      TYPE_FIELD (type, nfields) = fip->fields->field;
      TYPE_FIELD (type, nfields) = fip->fields->field;
      switch (fip->fields->accessibility)
      switch (fip->fields->accessibility)
        {
        {
        case DW_ACCESS_private:
        case DW_ACCESS_private:
          SET_TYPE_FIELD_PRIVATE (type, nfields);
          SET_TYPE_FIELD_PRIVATE (type, nfields);
          break;
          break;
 
 
        case DW_ACCESS_protected:
        case DW_ACCESS_protected:
          SET_TYPE_FIELD_PROTECTED (type, nfields);
          SET_TYPE_FIELD_PROTECTED (type, nfields);
          break;
          break;
 
 
        case DW_ACCESS_public:
        case DW_ACCESS_public:
          break;
          break;
 
 
        default:
        default:
          /* Unknown accessibility.  Complain and treat it as public.  */
          /* Unknown accessibility.  Complain and treat it as public.  */
          {
          {
            complain (&dwarf2_unsupported_accessibility,
            complain (&dwarf2_unsupported_accessibility,
                      fip->fields->accessibility);
                      fip->fields->accessibility);
          }
          }
          break;
          break;
        }
        }
      if (nfields < fip->nbaseclasses)
      if (nfields < fip->nbaseclasses)
        {
        {
          switch (fip->fields->virtuality)
          switch (fip->fields->virtuality)
            {
            {
            case DW_VIRTUALITY_virtual:
            case DW_VIRTUALITY_virtual:
            case DW_VIRTUALITY_pure_virtual:
            case DW_VIRTUALITY_pure_virtual:
              SET_TYPE_FIELD_VIRTUAL (type, nfields);
              SET_TYPE_FIELD_VIRTUAL (type, nfields);
              break;
              break;
            }
            }
        }
        }
      fip->fields = fip->fields->next;
      fip->fields = fip->fields->next;
    }
    }
}
}
 
 
/* Add a member function to the proper fieldlist.  */
/* Add a member function to the proper fieldlist.  */
 
 
static void
static void
dwarf2_add_member_fn (fip, die, type, objfile)
dwarf2_add_member_fn (fip, die, type, objfile)
     struct field_info *fip;
     struct field_info *fip;
     struct die_info *die;
     struct die_info *die;
     struct type *type;
     struct type *type;
     struct objfile *objfile;
     struct objfile *objfile;
{
{
  struct attribute *attr;
  struct attribute *attr;
  struct fnfieldlist *flp;
  struct fnfieldlist *flp;
  int i;
  int i;
  struct fn_field *fnp;
  struct fn_field *fnp;
  char *fieldname;
  char *fieldname;
  char *physname;
  char *physname;
  struct nextfnfield *new_fnfield;
  struct nextfnfield *new_fnfield;
 
 
  /* Get name of member function.  */
  /* Get name of member function.  */
  attr = dwarf_attr (die, DW_AT_name);
  attr = dwarf_attr (die, DW_AT_name);
  if (attr && DW_STRING (attr))
  if (attr && DW_STRING (attr))
    fieldname = DW_STRING (attr);
    fieldname = DW_STRING (attr);
  else
  else
    return;
    return;
 
 
  /* Get the mangled name.  */
  /* Get the mangled name.  */
  physname = dwarf2_linkage_name (die);
  physname = dwarf2_linkage_name (die);
 
 
  /* Look up member function name in fieldlist.  */
  /* Look up member function name in fieldlist.  */
  for (i = 0; i < fip->nfnfields; i++)
  for (i = 0; i < fip->nfnfields; i++)
    {
    {
      if (STREQ (fip->fnfieldlists[i].name, fieldname))
      if (STREQ (fip->fnfieldlists[i].name, fieldname))
        break;
        break;
    }
    }
 
 
  /* Create new list element if necessary.  */
  /* Create new list element if necessary.  */
  if (i < fip->nfnfields)
  if (i < fip->nfnfields)
    flp = &fip->fnfieldlists[i];
    flp = &fip->fnfieldlists[i];
  else
  else
    {
    {
      if ((fip->nfnfields % DW_FIELD_ALLOC_CHUNK) == 0)
      if ((fip->nfnfields % DW_FIELD_ALLOC_CHUNK) == 0)
        {
        {
          fip->fnfieldlists = (struct fnfieldlist *)
          fip->fnfieldlists = (struct fnfieldlist *)
            xrealloc (fip->fnfieldlists,
            xrealloc (fip->fnfieldlists,
                      (fip->nfnfields + DW_FIELD_ALLOC_CHUNK)
                      (fip->nfnfields + DW_FIELD_ALLOC_CHUNK)
                      * sizeof (struct fnfieldlist));
                      * sizeof (struct fnfieldlist));
          if (fip->nfnfields == 0)
          if (fip->nfnfields == 0)
            make_cleanup ((make_cleanup_func) free_current_contents,
            make_cleanup ((make_cleanup_func) free_current_contents,
                          &fip->fnfieldlists);
                          &fip->fnfieldlists);
        }
        }
      flp = &fip->fnfieldlists[fip->nfnfields];
      flp = &fip->fnfieldlists[fip->nfnfields];
      flp->name = fieldname;
      flp->name = fieldname;
      flp->length = 0;
      flp->length = 0;
      flp->head = NULL;
      flp->head = NULL;
      fip->nfnfields++;
      fip->nfnfields++;
    }
    }
 
 
  /* Create a new member function field and chain it to the field list
  /* Create a new member function field and chain it to the field list
     entry. */
     entry. */
  new_fnfield = (struct nextfnfield *) xmalloc (sizeof (struct nextfnfield));
  new_fnfield = (struct nextfnfield *) xmalloc (sizeof (struct nextfnfield));
  make_cleanup (free, new_fnfield);
  make_cleanup (free, new_fnfield);
  memset (new_fnfield, 0, sizeof (struct nextfnfield));
  memset (new_fnfield, 0, sizeof (struct nextfnfield));
  new_fnfield->next = flp->head;
  new_fnfield->next = flp->head;
  flp->head = new_fnfield;
  flp->head = new_fnfield;
  flp->length++;
  flp->length++;
 
 
  /* Fill in the member function field info.  */
  /* Fill in the member function field info.  */
  fnp = &new_fnfield->fnfield;
  fnp = &new_fnfield->fnfield;
  fnp->physname = obsavestring (physname, strlen (physname),
  fnp->physname = obsavestring (physname, strlen (physname),
                                &objfile->type_obstack);
                                &objfile->type_obstack);
  fnp->type = alloc_type (objfile);
  fnp->type = alloc_type (objfile);
  if (die->type && TYPE_CODE (die->type) == TYPE_CODE_FUNC)
  if (die->type && TYPE_CODE (die->type) == TYPE_CODE_FUNC)
    {
    {
      struct type *return_type = TYPE_TARGET_TYPE (die->type);
      struct type *return_type = TYPE_TARGET_TYPE (die->type);
      struct type **arg_types;
      struct type **arg_types;
      int nparams = TYPE_NFIELDS (die->type);
      int nparams = TYPE_NFIELDS (die->type);
      int iparams;
      int iparams;
 
 
      /* Copy argument types from the subroutine type.  */
      /* Copy argument types from the subroutine type.  */
      arg_types = (struct type **)
      arg_types = (struct type **)
        TYPE_ALLOC (fnp->type, (nparams + 1) * sizeof (struct type *));
        TYPE_ALLOC (fnp->type, (nparams + 1) * sizeof (struct type *));
      for (iparams = 0; iparams < nparams; iparams++)
      for (iparams = 0; iparams < nparams; iparams++)
        arg_types[iparams] = TYPE_FIELD_TYPE (die->type, iparams);
        arg_types[iparams] = TYPE_FIELD_TYPE (die->type, iparams);
 
 
      /* Set last entry in argument type vector.  */
      /* Set last entry in argument type vector.  */
      if (TYPE_FLAGS (die->type) & TYPE_FLAG_VARARGS)
      if (TYPE_FLAGS (die->type) & TYPE_FLAG_VARARGS)
        arg_types[nparams] = NULL;
        arg_types[nparams] = NULL;
      else
      else
        arg_types[nparams] = dwarf2_fundamental_type (objfile, FT_VOID);
        arg_types[nparams] = dwarf2_fundamental_type (objfile, FT_VOID);
 
 
      smash_to_method_type (fnp->type, type, return_type, arg_types);
      smash_to_method_type (fnp->type, type, return_type, arg_types);
 
 
      /* Handle static member functions.
      /* Handle static member functions.
         Dwarf2 has no clean way to discern C++ static and non-static
         Dwarf2 has no clean way to discern C++ static and non-static
         member functions. G++ helps GDB by marking the first
         member functions. G++ helps GDB by marking the first
         parameter for non-static member functions (which is the
         parameter for non-static member functions (which is the
         this pointer) as artificial. We obtain this information
         this pointer) as artificial. We obtain this information
         from read_subroutine_type via TYPE_FIELD_ARTIFICIAL.  */
         from read_subroutine_type via TYPE_FIELD_ARTIFICIAL.  */
      if (nparams == 0 || TYPE_FIELD_ARTIFICIAL (die->type, 0) == 0)
      if (nparams == 0 || TYPE_FIELD_ARTIFICIAL (die->type, 0) == 0)
        fnp->voffset = VOFFSET_STATIC;
        fnp->voffset = VOFFSET_STATIC;
    }
    }
  else
  else
    complain (&dwarf2_missing_member_fn_type_complaint, physname);
    complain (&dwarf2_missing_member_fn_type_complaint, physname);
 
 
  /* Get fcontext from DW_AT_containing_type if present.  */
  /* Get fcontext from DW_AT_containing_type if present.  */
  if (dwarf_attr (die, DW_AT_containing_type) != NULL)
  if (dwarf_attr (die, DW_AT_containing_type) != NULL)
    fnp->fcontext = die_containing_type (die, objfile);
    fnp->fcontext = die_containing_type (die, objfile);
 
 
  /* dwarf2 doesn't have stubbed physical names, so the setting of is_const
  /* dwarf2 doesn't have stubbed physical names, so the setting of is_const
     and is_volatile is irrelevant, as it is needed by gdb_mangle_name only.  */
     and is_volatile is irrelevant, as it is needed by gdb_mangle_name only.  */
 
 
  /* Get accessibility.  */
  /* Get accessibility.  */
  attr = dwarf_attr (die, DW_AT_accessibility);
  attr = dwarf_attr (die, DW_AT_accessibility);
  if (attr)
  if (attr)
    {
    {
      switch (DW_UNSND (attr))
      switch (DW_UNSND (attr))
        {
        {
        case DW_ACCESS_private:
        case DW_ACCESS_private:
          fnp->is_private = 1;
          fnp->is_private = 1;
          break;
          break;
        case DW_ACCESS_protected:
        case DW_ACCESS_protected:
          fnp->is_protected = 1;
          fnp->is_protected = 1;
          break;
          break;
        }
        }
    }
    }
 
 
  /* Get index in virtual function table if it is a virtual member function.  */
  /* Get index in virtual function table if it is a virtual member function.  */
  attr = dwarf_attr (die, DW_AT_vtable_elem_location);
  attr = dwarf_attr (die, DW_AT_vtable_elem_location);
  if (attr)
  if (attr)
    fnp->voffset = decode_locdesc (DW_BLOCK (attr), objfile) + 2;
    fnp->voffset = decode_locdesc (DW_BLOCK (attr), objfile) + 2;
}
}
 
 
/* Create the vector of member function fields, and attach it to the type.  */
/* Create the vector of member function fields, and attach it to the type.  */
 
 
static void
static void
dwarf2_attach_fn_fields_to_type (fip, type, objfile)
dwarf2_attach_fn_fields_to_type (fip, type, objfile)
     struct field_info *fip;
     struct field_info *fip;
     struct type *type;
     struct type *type;
     struct objfile *objfile;
     struct objfile *objfile;
{
{
  struct fnfieldlist *flp;
  struct fnfieldlist *flp;
  int total_length = 0;
  int total_length = 0;
  int i;
  int i;
 
 
  ALLOCATE_CPLUS_STRUCT_TYPE (type);
  ALLOCATE_CPLUS_STRUCT_TYPE (type);
  TYPE_FN_FIELDLISTS (type) = (struct fn_fieldlist *)
  TYPE_FN_FIELDLISTS (type) = (struct fn_fieldlist *)
    TYPE_ALLOC (type, sizeof (struct fn_fieldlist) * fip->nfnfields);
    TYPE_ALLOC (type, sizeof (struct fn_fieldlist) * fip->nfnfields);
 
 
  for (i = 0, flp = fip->fnfieldlists; i < fip->nfnfields; i++, flp++)
  for (i = 0, flp = fip->fnfieldlists; i < fip->nfnfields; i++, flp++)
    {
    {
      struct nextfnfield *nfp = flp->head;
      struct nextfnfield *nfp = flp->head;
      struct fn_fieldlist *fn_flp = &TYPE_FN_FIELDLIST (type, i);
      struct fn_fieldlist *fn_flp = &TYPE_FN_FIELDLIST (type, i);
      int k;
      int k;
 
 
      TYPE_FN_FIELDLIST_NAME (type, i) = flp->name;
      TYPE_FN_FIELDLIST_NAME (type, i) = flp->name;
      TYPE_FN_FIELDLIST_LENGTH (type, i) = flp->length;
      TYPE_FN_FIELDLIST_LENGTH (type, i) = flp->length;
      fn_flp->fn_fields = (struct fn_field *)
      fn_flp->fn_fields = (struct fn_field *)
        TYPE_ALLOC (type, sizeof (struct fn_field) * flp->length);
        TYPE_ALLOC (type, sizeof (struct fn_field) * flp->length);
      for (k = flp->length; (k--, nfp); nfp = nfp->next)
      for (k = flp->length; (k--, nfp); nfp = nfp->next)
        fn_flp->fn_fields[k] = nfp->fnfield;
        fn_flp->fn_fields[k] = nfp->fnfield;
 
 
      total_length += flp->length;
      total_length += flp->length;
    }
    }
 
 
  TYPE_NFN_FIELDS (type) = fip->nfnfields;
  TYPE_NFN_FIELDS (type) = fip->nfnfields;
  TYPE_NFN_FIELDS_TOTAL (type) = total_length;
  TYPE_NFN_FIELDS_TOTAL (type) = total_length;
}
}
 
 
/* Called when we find the DIE that starts a structure or union scope
/* Called when we find the DIE that starts a structure or union scope
   (definition) to process all dies that define the members of the
   (definition) to process all dies that define the members of the
   structure or union.
   structure or union.
 
 
   NOTE: we need to call struct_type regardless of whether or not the
   NOTE: we need to call struct_type regardless of whether or not the
   DIE has an at_name attribute, since it might be an anonymous
   DIE has an at_name attribute, since it might be an anonymous
   structure or union.  This gets the type entered into our set of
   structure or union.  This gets the type entered into our set of
   user defined types.
   user defined types.
 
 
   However, if the structure is incomplete (an opaque struct/union)
   However, if the structure is incomplete (an opaque struct/union)
   then suppress creating a symbol table entry for it since gdb only
   then suppress creating a symbol table entry for it since gdb only
   wants to find the one with the complete definition.  Note that if
   wants to find the one with the complete definition.  Note that if
   it is complete, we just call new_symbol, which does it's own
   it is complete, we just call new_symbol, which does it's own
   checking about whether the struct/union is anonymous or not (and
   checking about whether the struct/union is anonymous or not (and
   suppresses creating a symbol table entry itself).  */
   suppresses creating a symbol table entry itself).  */
 
 
static void
static void
read_structure_scope (die, objfile)
read_structure_scope (die, objfile)
     struct die_info *die;
     struct die_info *die;
     struct objfile *objfile;
     struct objfile *objfile;
{
{
  struct type *type;
  struct type *type;
  struct attribute *attr;
  struct attribute *attr;
 
 
  type = alloc_type (objfile);
  type = alloc_type (objfile);
 
 
  INIT_CPLUS_SPECIFIC (type);
  INIT_CPLUS_SPECIFIC (type);
  attr = dwarf_attr (die, DW_AT_name);
  attr = dwarf_attr (die, DW_AT_name);
  if (attr && DW_STRING (attr))
  if (attr && DW_STRING (attr))
    {
    {
      TYPE_TAG_NAME (type) = obsavestring (DW_STRING (attr),
      TYPE_TAG_NAME (type) = obsavestring (DW_STRING (attr),
                                           strlen (DW_STRING (attr)),
                                           strlen (DW_STRING (attr)),
                                           &objfile->type_obstack);
                                           &objfile->type_obstack);
    }
    }
 
 
  if (die->tag == DW_TAG_structure_type)
  if (die->tag == DW_TAG_structure_type)
    {
    {
      TYPE_CODE (type) = TYPE_CODE_STRUCT;
      TYPE_CODE (type) = TYPE_CODE_STRUCT;
    }
    }
  else if (die->tag == DW_TAG_union_type)
  else if (die->tag == DW_TAG_union_type)
    {
    {
      TYPE_CODE (type) = TYPE_CODE_UNION;
      TYPE_CODE (type) = TYPE_CODE_UNION;
    }
    }
  else
  else
    {
    {
      /* FIXME: TYPE_CODE_CLASS is currently defined to TYPE_CODE_STRUCT
      /* FIXME: TYPE_CODE_CLASS is currently defined to TYPE_CODE_STRUCT
         in gdbtypes.h.  */
         in gdbtypes.h.  */
      TYPE_CODE (type) = TYPE_CODE_CLASS;
      TYPE_CODE (type) = TYPE_CODE_CLASS;
    }
    }
 
 
  attr = dwarf_attr (die, DW_AT_byte_size);
  attr = dwarf_attr (die, DW_AT_byte_size);
  if (attr)
  if (attr)
    {
    {
      TYPE_LENGTH (type) = DW_UNSND (attr);
      TYPE_LENGTH (type) = DW_UNSND (attr);
    }
    }
  else
  else
    {
    {
      TYPE_LENGTH (type) = 0;
      TYPE_LENGTH (type) = 0;
    }
    }
 
 
  /* We need to add the type field to the die immediately so we don't
  /* We need to add the type field to the die immediately so we don't
     infinitely recurse when dealing with pointers to the structure
     infinitely recurse when dealing with pointers to the structure
     type within the structure itself. */
     type within the structure itself. */
  die->type = type;
  die->type = type;
 
 
  if (die->has_children && ! die_is_declaration (die))
  if (die->has_children && ! die_is_declaration (die))
    {
    {
      struct field_info fi;
      struct field_info fi;
      struct die_info *child_die;
      struct die_info *child_die;
      struct cleanup *back_to = make_cleanup (null_cleanup, NULL);
      struct cleanup *back_to = make_cleanup (null_cleanup, NULL);
 
 
      memset (&fi, 0, sizeof (struct field_info));
      memset (&fi, 0, sizeof (struct field_info));
 
 
      child_die = die->next;
      child_die = die->next;
 
 
      while (child_die && child_die->tag)
      while (child_die && child_die->tag)
        {
        {
          if (child_die->tag == DW_TAG_member)
          if (child_die->tag == DW_TAG_member)
            {
            {
              dwarf2_add_field (&fi, child_die, objfile);
              dwarf2_add_field (&fi, child_die, objfile);
            }
            }
          else if (child_die->tag == DW_TAG_variable)
          else if (child_die->tag == DW_TAG_variable)
            {
            {
              /* C++ static member.  */
              /* C++ static member.  */
              dwarf2_add_field (&fi, child_die, objfile);
              dwarf2_add_field (&fi, child_die, objfile);
            }
            }
          else if (child_die->tag == DW_TAG_subprogram)
          else if (child_die->tag == DW_TAG_subprogram)
            {
            {
              /* C++ member function. */
              /* C++ member function. */
              process_die (child_die, objfile);
              process_die (child_die, objfile);
              dwarf2_add_member_fn (&fi, child_die, type, objfile);
              dwarf2_add_member_fn (&fi, child_die, type, objfile);
            }
            }
          else if (child_die->tag == DW_TAG_inheritance)
          else if (child_die->tag == DW_TAG_inheritance)
            {
            {
              /* C++ base class field.  */
              /* C++ base class field.  */
              dwarf2_add_field (&fi, child_die, objfile);
              dwarf2_add_field (&fi, child_die, objfile);
            }
            }
          else
          else
            {
            {
              process_die (child_die, objfile);
              process_die (child_die, objfile);
            }
            }
          child_die = sibling_die (child_die);
          child_die = sibling_die (child_die);
        }
        }
 
 
      /* Attach fields and member functions to the type.  */
      /* Attach fields and member functions to the type.  */
      if (fi.nfields)
      if (fi.nfields)
        dwarf2_attach_fields_to_type (&fi, type, objfile);
        dwarf2_attach_fields_to_type (&fi, type, objfile);
      if (fi.nfnfields)
      if (fi.nfnfields)
        {
        {
          dwarf2_attach_fn_fields_to_type (&fi, type, objfile);
          dwarf2_attach_fn_fields_to_type (&fi, type, objfile);
 
 
          /* Get the type which refers to the base class (possibly this
          /* Get the type which refers to the base class (possibly this
             class itself) which contains the vtable pointer for the current
             class itself) which contains the vtable pointer for the current
             class from the DW_AT_containing_type attribute.  */
             class from the DW_AT_containing_type attribute.  */
 
 
          if (dwarf_attr (die, DW_AT_containing_type) != NULL)
          if (dwarf_attr (die, DW_AT_containing_type) != NULL)
            {
            {
              struct type *t = die_containing_type (die, objfile);
              struct type *t = die_containing_type (die, objfile);
 
 
              TYPE_VPTR_BASETYPE (type) = t;
              TYPE_VPTR_BASETYPE (type) = t;
              if (type == t)
              if (type == t)
                {
                {
                  static const char vptr_name[] =
                  static const char vptr_name[] =
                  {'_', 'v', 'p', 't', 'r', '\0'};
                  {'_', 'v', 'p', 't', 'r', '\0'};
                  int i;
                  int i;
 
 
                  /* Our own class provides vtbl ptr.  */
                  /* Our own class provides vtbl ptr.  */
                  for (i = TYPE_NFIELDS (t) - 1;
                  for (i = TYPE_NFIELDS (t) - 1;
                       i >= TYPE_N_BASECLASSES (t);
                       i >= TYPE_N_BASECLASSES (t);
                       --i)
                       --i)
                    {
                    {
                      char *fieldname = TYPE_FIELD_NAME (t, i);
                      char *fieldname = TYPE_FIELD_NAME (t, i);
 
 
                      if (STREQN (fieldname, vptr_name, strlen (vptr_name) - 1)
                      if (STREQN (fieldname, vptr_name, strlen (vptr_name) - 1)
                          && is_cplus_marker (fieldname[strlen (vptr_name)]))
                          && is_cplus_marker (fieldname[strlen (vptr_name)]))
                        {
                        {
                          TYPE_VPTR_FIELDNO (type) = i;
                          TYPE_VPTR_FIELDNO (type) = i;
                          break;
                          break;
                        }
                        }
                    }
                    }
 
 
                  /* Complain if virtual function table field not found.  */
                  /* Complain if virtual function table field not found.  */
                  if (i < TYPE_N_BASECLASSES (t))
                  if (i < TYPE_N_BASECLASSES (t))
                    complain (&dwarf2_vtbl_not_found_complaint,
                    complain (&dwarf2_vtbl_not_found_complaint,
                          TYPE_TAG_NAME (type) ? TYPE_TAG_NAME (type) : "");
                          TYPE_TAG_NAME (type) ? TYPE_TAG_NAME (type) : "");
                }
                }
              else
              else
                {
                {
                  TYPE_VPTR_FIELDNO (type) = TYPE_VPTR_FIELDNO (t);
                  TYPE_VPTR_FIELDNO (type) = TYPE_VPTR_FIELDNO (t);
                }
                }
            }
            }
        }
        }
 
 
      new_symbol (die, type, objfile);
      new_symbol (die, type, objfile);
 
 
      do_cleanups (back_to);
      do_cleanups (back_to);
    }
    }
  else
  else
    {
    {
      /* No children, must be stub. */
      /* No children, must be stub. */
      TYPE_FLAGS (type) |= TYPE_FLAG_STUB;
      TYPE_FLAGS (type) |= TYPE_FLAG_STUB;
    }
    }
 
 
  die->type = type;
  die->type = type;
}
}
 
 
/* Given a pointer to a die which begins an enumeration, process all
/* Given a pointer to a die which begins an enumeration, process all
   the dies that define the members of the enumeration.
   the dies that define the members of the enumeration.
 
 
   This will be much nicer in draft 6 of the DWARF spec when our
   This will be much nicer in draft 6 of the DWARF spec when our
   members will be dies instead squished into the DW_AT_element_list
   members will be dies instead squished into the DW_AT_element_list
   attribute.
   attribute.
 
 
   NOTE: We reverse the order of the element list.  */
   NOTE: We reverse the order of the element list.  */
 
 
static void
static void
read_enumeration (die, objfile)
read_enumeration (die, objfile)
     struct die_info *die;
     struct die_info *die;
     struct objfile *objfile;
     struct objfile *objfile;
{
{
  struct die_info *child_die;
  struct die_info *child_die;
  struct type *type;
  struct type *type;
  struct field *fields;
  struct field *fields;
  struct attribute *attr;
  struct attribute *attr;
  struct symbol *sym;
  struct symbol *sym;
  int num_fields;
  int num_fields;
  int unsigned_enum = 1;
  int unsigned_enum = 1;
 
 
  type = alloc_type (objfile);
  type = alloc_type (objfile);
 
 
  TYPE_CODE (type) = TYPE_CODE_ENUM;
  TYPE_CODE (type) = TYPE_CODE_ENUM;
  attr = dwarf_attr (die, DW_AT_name);
  attr = dwarf_attr (die, DW_AT_name);
  if (attr && DW_STRING (attr))
  if (attr && DW_STRING (attr))
    {
    {
      TYPE_TAG_NAME (type) = obsavestring (DW_STRING (attr),
      TYPE_TAG_NAME (type) = obsavestring (DW_STRING (attr),
                                           strlen (DW_STRING (attr)),
                                           strlen (DW_STRING (attr)),
                                           &objfile->type_obstack);
                                           &objfile->type_obstack);
    }
    }
 
 
  attr = dwarf_attr (die, DW_AT_byte_size);
  attr = dwarf_attr (die, DW_AT_byte_size);
  if (attr)
  if (attr)
    {
    {
      TYPE_LENGTH (type) = DW_UNSND (attr);
      TYPE_LENGTH (type) = DW_UNSND (attr);
    }
    }
  else
  else
    {
    {
      TYPE_LENGTH (type) = 0;
      TYPE_LENGTH (type) = 0;
    }
    }
 
 
  num_fields = 0;
  num_fields = 0;
  fields = NULL;
  fields = NULL;
  if (die->has_children)
  if (die->has_children)
    {
    {
      child_die = die->next;
      child_die = die->next;
      while (child_die && child_die->tag)
      while (child_die && child_die->tag)
        {
        {
          if (child_die->tag != DW_TAG_enumerator)
          if (child_die->tag != DW_TAG_enumerator)
            {
            {
              process_die (child_die, objfile);
              process_die (child_die, objfile);
            }
            }
          else
          else
            {
            {
              attr = dwarf_attr (child_die, DW_AT_name);
              attr = dwarf_attr (child_die, DW_AT_name);
              if (attr)
              if (attr)
                {
                {
                  sym = new_symbol (child_die, type, objfile);
                  sym = new_symbol (child_die, type, objfile);
                  if (SYMBOL_VALUE (sym) < 0)
                  if (SYMBOL_VALUE (sym) < 0)
                    unsigned_enum = 0;
                    unsigned_enum = 0;
 
 
                  if ((num_fields % DW_FIELD_ALLOC_CHUNK) == 0)
                  if ((num_fields % DW_FIELD_ALLOC_CHUNK) == 0)
                    {
                    {
                      fields = (struct field *)
                      fields = (struct field *)
                        xrealloc (fields,
                        xrealloc (fields,
                                  (num_fields + DW_FIELD_ALLOC_CHUNK)
                                  (num_fields + DW_FIELD_ALLOC_CHUNK)
                                  * sizeof (struct field));
                                  * sizeof (struct field));
                    }
                    }
 
 
                  FIELD_NAME (fields[num_fields]) = SYMBOL_NAME (sym);
                  FIELD_NAME (fields[num_fields]) = SYMBOL_NAME (sym);
                  FIELD_TYPE (fields[num_fields]) = NULL;
                  FIELD_TYPE (fields[num_fields]) = NULL;
                  FIELD_BITPOS (fields[num_fields]) = SYMBOL_VALUE (sym);
                  FIELD_BITPOS (fields[num_fields]) = SYMBOL_VALUE (sym);
                  FIELD_BITSIZE (fields[num_fields]) = 0;
                  FIELD_BITSIZE (fields[num_fields]) = 0;
 
 
                  num_fields++;
                  num_fields++;
                }
                }
            }
            }
 
 
          child_die = sibling_die (child_die);
          child_die = sibling_die (child_die);
        }
        }
 
 
      if (num_fields)
      if (num_fields)
        {
        {
          TYPE_NFIELDS (type) = num_fields;
          TYPE_NFIELDS (type) = num_fields;
          TYPE_FIELDS (type) = (struct field *)
          TYPE_FIELDS (type) = (struct field *)
            TYPE_ALLOC (type, sizeof (struct field) * num_fields);
            TYPE_ALLOC (type, sizeof (struct field) * num_fields);
          memcpy (TYPE_FIELDS (type), fields,
          memcpy (TYPE_FIELDS (type), fields,
                  sizeof (struct field) * num_fields);
                  sizeof (struct field) * num_fields);
          free (fields);
          free (fields);
        }
        }
      if (unsigned_enum)
      if (unsigned_enum)
        TYPE_FLAGS (type) |= TYPE_FLAG_UNSIGNED;
        TYPE_FLAGS (type) |= TYPE_FLAG_UNSIGNED;
    }
    }
  die->type = type;
  die->type = type;
  new_symbol (die, type, objfile);
  new_symbol (die, type, objfile);
}
}
 
 
/* Extract all information from a DW_TAG_array_type DIE and put it in
/* Extract all information from a DW_TAG_array_type DIE and put it in
   the DIE's type field.  For now, this only handles one dimensional
   the DIE's type field.  For now, this only handles one dimensional
   arrays.  */
   arrays.  */
 
 
static void
static void
read_array_type (die, objfile)
read_array_type (die, objfile)
     struct die_info *die;
     struct die_info *die;
     struct objfile *objfile;
     struct objfile *objfile;
{
{
  struct die_info *child_die;
  struct die_info *child_die;
  struct type *type = NULL;
  struct type *type = NULL;
  struct type *element_type, *range_type, *index_type;
  struct type *element_type, *range_type, *index_type;
  struct type **range_types = NULL;
  struct type **range_types = NULL;
  struct attribute *attr;
  struct attribute *attr;
  int ndim = 0;
  int ndim = 0;
  struct cleanup *back_to;
  struct cleanup *back_to;
 
 
  /* Return if we've already decoded this type. */
  /* Return if we've already decoded this type. */
  if (die->type)
  if (die->type)
    {
    {
      return;
      return;
    }
    }
 
 
  element_type = die_type (die, objfile);
  element_type = die_type (die, objfile);
 
 
  /* Irix 6.2 native cc creates array types without children for
  /* Irix 6.2 native cc creates array types without children for
     arrays with unspecified length.  */
     arrays with unspecified length.  */
  if (die->has_children == 0)
  if (die->has_children == 0)
    {
    {
      index_type = dwarf2_fundamental_type (objfile, FT_INTEGER);
      index_type = dwarf2_fundamental_type (objfile, FT_INTEGER);
      range_type = create_range_type (NULL, index_type, 0, -1);
      range_type = create_range_type (NULL, index_type, 0, -1);
      die->type = create_array_type (NULL, element_type, range_type);
      die->type = create_array_type (NULL, element_type, range_type);
      return;
      return;
    }
    }
 
 
  back_to = make_cleanup (null_cleanup, NULL);
  back_to = make_cleanup (null_cleanup, NULL);
  child_die = die->next;
  child_die = die->next;
  while (child_die && child_die->tag)
  while (child_die && child_die->tag)
    {
    {
      if (child_die->tag == DW_TAG_subrange_type)
      if (child_die->tag == DW_TAG_subrange_type)
        {
        {
          unsigned int low, high;
          unsigned int low, high;
 
 
          /* Default bounds to an array with unspecified length.  */
          /* Default bounds to an array with unspecified length.  */
          low = 0;
          low = 0;
          high = -1;
          high = -1;
          if (cu_language == language_fortran)
          if (cu_language == language_fortran)
            {
            {
              /* FORTRAN implies a lower bound of 1, if not given.  */
              /* FORTRAN implies a lower bound of 1, if not given.  */
              low = 1;
              low = 1;
            }
            }
 
 
          index_type = die_type (child_die, objfile);
          index_type = die_type (child_die, objfile);
          attr = dwarf_attr (child_die, DW_AT_lower_bound);
          attr = dwarf_attr (child_die, DW_AT_lower_bound);
          if (attr)
          if (attr)
            {
            {
              if (attr->form == DW_FORM_sdata)
              if (attr->form == DW_FORM_sdata)
                {
                {
                  low = DW_SND (attr);
                  low = DW_SND (attr);
                }
                }
              else if (attr->form == DW_FORM_udata
              else if (attr->form == DW_FORM_udata
                       || attr->form == DW_FORM_data1
                       || attr->form == DW_FORM_data1
                       || attr->form == DW_FORM_data2
                       || attr->form == DW_FORM_data2
                       || attr->form == DW_FORM_data4)
                       || attr->form == DW_FORM_data4)
                {
                {
                  low = DW_UNSND (attr);
                  low = DW_UNSND (attr);
                }
                }
              else
              else
                {
                {
                  complain (&dwarf2_non_const_array_bound_ignored,
                  complain (&dwarf2_non_const_array_bound_ignored,
                            dwarf_form_name (attr->form));
                            dwarf_form_name (attr->form));
#ifdef FORTRAN_HACK
#ifdef FORTRAN_HACK
                  die->type = lookup_pointer_type (element_type);
                  die->type = lookup_pointer_type (element_type);
                  return;
                  return;
#else
#else
                  low = 0;
                  low = 0;
#endif
#endif
                }
                }
            }
            }
          attr = dwarf_attr (child_die, DW_AT_upper_bound);
          attr = dwarf_attr (child_die, DW_AT_upper_bound);
          if (attr)
          if (attr)
            {
            {
              if (attr->form == DW_FORM_sdata)
              if (attr->form == DW_FORM_sdata)
                {
                {
                  high = DW_SND (attr);
                  high = DW_SND (attr);
                }
                }
              else if (attr->form == DW_FORM_udata
              else if (attr->form == DW_FORM_udata
                       || attr->form == DW_FORM_data1
                       || attr->form == DW_FORM_data1
                       || attr->form == DW_FORM_data2
                       || attr->form == DW_FORM_data2
                       || attr->form == DW_FORM_data4)
                       || attr->form == DW_FORM_data4)
                {
                {
                  high = DW_UNSND (attr);
                  high = DW_UNSND (attr);
                }
                }
              else if (attr->form == DW_FORM_block1)
              else if (attr->form == DW_FORM_block1)
                {
                {
                  /* GCC encodes arrays with unspecified or dynamic length
                  /* GCC encodes arrays with unspecified or dynamic length
                     with a DW_FORM_block1 attribute.
                     with a DW_FORM_block1 attribute.
                     FIXME: GDB does not yet know how to handle dynamic
                     FIXME: GDB does not yet know how to handle dynamic
                     arrays properly, treat them as arrays with unspecified
                     arrays properly, treat them as arrays with unspecified
                     length for now.  */
                     length for now.  */
                  high = -1;
                  high = -1;
                }
                }
              else
              else
                {
                {
                  complain (&dwarf2_non_const_array_bound_ignored,
                  complain (&dwarf2_non_const_array_bound_ignored,
                            dwarf_form_name (attr->form));
                            dwarf_form_name (attr->form));
#ifdef FORTRAN_HACK
#ifdef FORTRAN_HACK
                  die->type = lookup_pointer_type (element_type);
                  die->type = lookup_pointer_type (element_type);
                  return;
                  return;
#else
#else
                  high = 1;
                  high = 1;
#endif
#endif
                }
                }
            }
            }
 
 
          /* Create a range type and save it for array type creation.  */
          /* Create a range type and save it for array type creation.  */
          if ((ndim % DW_FIELD_ALLOC_CHUNK) == 0)
          if ((ndim % DW_FIELD_ALLOC_CHUNK) == 0)
            {
            {
              range_types = (struct type **)
              range_types = (struct type **)
                xrealloc (range_types, (ndim + DW_FIELD_ALLOC_CHUNK)
                xrealloc (range_types, (ndim + DW_FIELD_ALLOC_CHUNK)
                          * sizeof (struct type *));
                          * sizeof (struct type *));
              if (ndim == 0)
              if (ndim == 0)
                make_cleanup ((make_cleanup_func) free_current_contents,
                make_cleanup ((make_cleanup_func) free_current_contents,
                              &range_types);
                              &range_types);
            }
            }
          range_types[ndim++] = create_range_type (NULL, index_type, low, high);
          range_types[ndim++] = create_range_type (NULL, index_type, low, high);
        }
        }
      child_die = sibling_die (child_die);
      child_die = sibling_die (child_die);
    }
    }
 
 
  /* Dwarf2 dimensions are output from left to right, create the
  /* Dwarf2 dimensions are output from left to right, create the
     necessary array types in backwards order.  */
     necessary array types in backwards order.  */
  type = element_type;
  type = element_type;
  while (ndim-- > 0)
  while (ndim-- > 0)
    type = create_array_type (NULL, type, range_types[ndim]);
    type = create_array_type (NULL, type, range_types[ndim]);
 
 
  do_cleanups (back_to);
  do_cleanups (back_to);
 
 
  /* Install the type in the die. */
  /* Install the type in the die. */
  die->type = type;
  die->type = type;
}
}
 
 
/* First cut: install each common block member as a global variable.  */
/* First cut: install each common block member as a global variable.  */
 
 
static void
static void
read_common_block (die, objfile)
read_common_block (die, objfile)
     struct die_info *die;
     struct die_info *die;
     struct objfile *objfile;
     struct objfile *objfile;
{
{
  struct die_info *child_die;
  struct die_info *child_die;
  struct attribute *attr;
  struct attribute *attr;
  struct symbol *sym;
  struct symbol *sym;
  CORE_ADDR base = (CORE_ADDR) 0;
  CORE_ADDR base = (CORE_ADDR) 0;
 
 
  attr = dwarf_attr (die, DW_AT_location);
  attr = dwarf_attr (die, DW_AT_location);
  if (attr)
  if (attr)
    {
    {
      base = decode_locdesc (DW_BLOCK (attr), objfile);
      base = decode_locdesc (DW_BLOCK (attr), objfile);
    }
    }
  if (die->has_children)
  if (die->has_children)
    {
    {
      child_die = die->next;
      child_die = die->next;
      while (child_die && child_die->tag)
      while (child_die && child_die->tag)
        {
        {
          sym = new_symbol (child_die, NULL, objfile);
          sym = new_symbol (child_die, NULL, objfile);
          attr = dwarf_attr (child_die, DW_AT_data_member_location);
          attr = dwarf_attr (child_die, DW_AT_data_member_location);
          if (attr)
          if (attr)
            {
            {
              SYMBOL_VALUE_ADDRESS (sym) =
              SYMBOL_VALUE_ADDRESS (sym) =
                base + decode_locdesc (DW_BLOCK (attr), objfile);
                base + decode_locdesc (DW_BLOCK (attr), objfile);
              add_symbol_to_list (sym, &global_symbols);
              add_symbol_to_list (sym, &global_symbols);
            }
            }
          child_die = sibling_die (child_die);
          child_die = sibling_die (child_die);
        }
        }
    }
    }
}
}
 
 
/* Extract all information from a DW_TAG_pointer_type DIE and add to
/* Extract all information from a DW_TAG_pointer_type DIE and add to
   the user defined type vector.  */
   the user defined type vector.  */
 
 
static void
static void
read_tag_pointer_type (die, objfile)
read_tag_pointer_type (die, objfile)
     struct die_info *die;
     struct die_info *die;
     struct objfile *objfile;
     struct objfile *objfile;
{
{
  struct type *type;
  struct type *type;
  struct attribute *attr;
  struct attribute *attr;
 
 
  if (die->type)
  if (die->type)
    {
    {
      return;
      return;
    }
    }
 
 
  type = lookup_pointer_type (die_type (die, objfile));
  type = lookup_pointer_type (die_type (die, objfile));
  attr = dwarf_attr (die, DW_AT_byte_size);
  attr = dwarf_attr (die, DW_AT_byte_size);
  if (attr)
  if (attr)
    {
    {
      TYPE_LENGTH (type) = DW_UNSND (attr);
      TYPE_LENGTH (type) = DW_UNSND (attr);
    }
    }
  else
  else
    {
    {
      TYPE_LENGTH (type) = address_size;
      TYPE_LENGTH (type) = address_size;
    }
    }
  die->type = type;
  die->type = type;
}
}
 
 
/* Extract all information from a DW_TAG_ptr_to_member_type DIE and add to
/* Extract all information from a DW_TAG_ptr_to_member_type DIE and add to
   the user defined type vector.  */
   the user defined type vector.  */
 
 
static void
static void
read_tag_ptr_to_member_type (die, objfile)
read_tag_ptr_to_member_type (die, objfile)
     struct die_info *die;
     struct die_info *die;
     struct objfile *objfile;
     struct objfile *objfile;
{
{
  struct type *type;
  struct type *type;
  struct type *to_type;
  struct type *to_type;
  struct type *domain;
  struct type *domain;
 
 
  if (die->type)
  if (die->type)
    {
    {
      return;
      return;
    }
    }
 
 
  type = alloc_type (objfile);
  type = alloc_type (objfile);
  to_type = die_type (die, objfile);
  to_type = die_type (die, objfile);
  domain = die_containing_type (die, objfile);
  domain = die_containing_type (die, objfile);
  smash_to_member_type (type, domain, to_type);
  smash_to_member_type (type, domain, to_type);
 
 
  die->type = type;
  die->type = type;
}
}
 
 
/* Extract all information from a DW_TAG_reference_type DIE and add to
/* Extract all information from a DW_TAG_reference_type DIE and add to
   the user defined type vector.  */
   the user defined type vector.  */
 
 
static void
static void
read_tag_reference_type (die, objfile)
read_tag_reference_type (die, objfile)
     struct die_info *die;
     struct die_info *die;
     struct objfile *objfile;
     struct objfile *objfile;
{
{
  struct type *type;
  struct type *type;
  struct attribute *attr;
  struct attribute *attr;
 
 
  if (die->type)
  if (die->type)
    {
    {
      return;
      return;
    }
    }
 
 
  type = lookup_reference_type (die_type (die, objfile));
  type = lookup_reference_type (die_type (die, objfile));
  attr = dwarf_attr (die, DW_AT_byte_size);
  attr = dwarf_attr (die, DW_AT_byte_size);
  if (attr)
  if (attr)
    {
    {
      TYPE_LENGTH (type) = DW_UNSND (attr);
      TYPE_LENGTH (type) = DW_UNSND (attr);
    }
    }
  else
  else
    {
    {
      TYPE_LENGTH (type) = address_size;
      TYPE_LENGTH (type) = address_size;
    }
    }
  die->type = type;
  die->type = type;
}
}
 
 
static void
static void
read_tag_const_type (die, objfile)
read_tag_const_type (die, objfile)
     struct die_info *die;
     struct die_info *die;
     struct objfile *objfile;
     struct objfile *objfile;
{
{
  if (die->type)
  if (die->type)
    {
    {
      return;
      return;
    }
    }
 
 
  complain (&dwarf2_const_ignored);
  complain (&dwarf2_const_ignored);
  die->type = die_type (die, objfile);
  die->type = die_type (die, objfile);
}
}
 
 
static void
static void
read_tag_volatile_type (die, objfile)
read_tag_volatile_type (die, objfile)
     struct die_info *die;
     struct die_info *die;
     struct objfile *objfile;
     struct objfile *objfile;
{
{
  if (die->type)
  if (die->type)
    {
    {
      return;
      return;
    }
    }
 
 
  complain (&dwarf2_volatile_ignored);
  complain (&dwarf2_volatile_ignored);
  die->type = die_type (die, objfile);
  die->type = die_type (die, objfile);
}
}
 
 
/* Extract all information from a DW_TAG_string_type DIE and add to
/* Extract all information from a DW_TAG_string_type DIE and add to
   the user defined type vector.  It isn't really a user defined type,
   the user defined type vector.  It isn't really a user defined type,
   but it behaves like one, with other DIE's using an AT_user_def_type
   but it behaves like one, with other DIE's using an AT_user_def_type
   attribute to reference it.  */
   attribute to reference it.  */
 
 
static void
static void
read_tag_string_type (die, objfile)
read_tag_string_type (die, objfile)
     struct die_info *die;
     struct die_info *die;
     struct objfile *objfile;
     struct objfile *objfile;
{
{
  struct type *type, *range_type, *index_type, *char_type;
  struct type *type, *range_type, *index_type, *char_type;
  struct attribute *attr;
  struct attribute *attr;
  unsigned int length;
  unsigned int length;
 
 
  if (die->type)
  if (die->type)
    {
    {
      return;
      return;
    }
    }
 
 
  attr = dwarf_attr (die, DW_AT_string_length);
  attr = dwarf_attr (die, DW_AT_string_length);
  if (attr)
  if (attr)
    {
    {
      length = DW_UNSND (attr);
      length = DW_UNSND (attr);
    }
    }
  else
  else
    {
    {
      length = 1;
      length = 1;
    }
    }
  index_type = dwarf2_fundamental_type (objfile, FT_INTEGER);
  index_type = dwarf2_fundamental_type (objfile, FT_INTEGER);
  range_type = create_range_type (NULL, index_type, 1, length);
  range_type = create_range_type (NULL, index_type, 1, length);
  char_type = dwarf2_fundamental_type (objfile, FT_CHAR);
  char_type = dwarf2_fundamental_type (objfile, FT_CHAR);
  type = create_string_type (char_type, range_type);
  type = create_string_type (char_type, range_type);
  die->type = type;
  die->type = type;
}
}
 
 
/* Handle DIES due to C code like:
/* Handle DIES due to C code like:
 
 
   struct foo
   struct foo
   {
   {
   int (*funcp)(int a, long l);
   int (*funcp)(int a, long l);
   int b;
   int b;
   };
   };
 
 
   ('funcp' generates a DW_TAG_subroutine_type DIE)
   ('funcp' generates a DW_TAG_subroutine_type DIE)
 */
 */
 
 
static void
static void
read_subroutine_type (die, objfile)
read_subroutine_type (die, objfile)
     struct die_info *die;
     struct die_info *die;
     struct objfile *objfile;
     struct objfile *objfile;
{
{
  struct type *type;            /* Type that this function returns */
  struct type *type;            /* Type that this function returns */
  struct type *ftype;           /* Function that returns above type */
  struct type *ftype;           /* Function that returns above type */
  struct attribute *attr;
  struct attribute *attr;
 
 
  /* Decode the type that this subroutine returns */
  /* Decode the type that this subroutine returns */
  if (die->type)
  if (die->type)
    {
    {
      return;
      return;
    }
    }
  type = die_type (die, objfile);
  type = die_type (die, objfile);
  ftype = lookup_function_type (type);
  ftype = lookup_function_type (type);
 
 
  /* All functions in C++ have prototypes.  */
  /* All functions in C++ have prototypes.  */
  attr = dwarf_attr (die, DW_AT_prototyped);
  attr = dwarf_attr (die, DW_AT_prototyped);
  if ((attr && (DW_UNSND (attr) != 0))
  if ((attr && (DW_UNSND (attr) != 0))
      || cu_language == language_cplus)
      || cu_language == language_cplus)
    TYPE_FLAGS (ftype) |= TYPE_FLAG_PROTOTYPED;
    TYPE_FLAGS (ftype) |= TYPE_FLAG_PROTOTYPED;
 
 
  if (die->has_children)
  if (die->has_children)
    {
    {
      struct die_info *child_die;
      struct die_info *child_die;
      int nparams = 0;
      int nparams = 0;
      int iparams = 0;
      int iparams = 0;
 
 
      /* Count the number of parameters.
      /* Count the number of parameters.
         FIXME: GDB currently ignores vararg functions, but knows about
         FIXME: GDB currently ignores vararg functions, but knows about
         vararg member functions.  */
         vararg member functions.  */
      child_die = die->next;
      child_die = die->next;
      while (child_die && child_die->tag)
      while (child_die && child_die->tag)
        {
        {
          if (child_die->tag == DW_TAG_formal_parameter)
          if (child_die->tag == DW_TAG_formal_parameter)
            nparams++;
            nparams++;
          else if (child_die->tag == DW_TAG_unspecified_parameters)
          else if (child_die->tag == DW_TAG_unspecified_parameters)
            TYPE_FLAGS (ftype) |= TYPE_FLAG_VARARGS;
            TYPE_FLAGS (ftype) |= TYPE_FLAG_VARARGS;
          child_die = sibling_die (child_die);
          child_die = sibling_die (child_die);
        }
        }
 
 
      /* Allocate storage for parameters and fill them in.  */
      /* Allocate storage for parameters and fill them in.  */
      TYPE_NFIELDS (ftype) = nparams;
      TYPE_NFIELDS (ftype) = nparams;
      TYPE_FIELDS (ftype) = (struct field *)
      TYPE_FIELDS (ftype) = (struct field *)
        TYPE_ALLOC (ftype, nparams * sizeof (struct field));
        TYPE_ALLOC (ftype, nparams * sizeof (struct field));
 
 
      child_die = die->next;
      child_die = die->next;
      while (child_die && child_die->tag)
      while (child_die && child_die->tag)
        {
        {
          if (child_die->tag == DW_TAG_formal_parameter)
          if (child_die->tag == DW_TAG_formal_parameter)
            {
            {
              /* Dwarf2 has no clean way to discern C++ static and non-static
              /* Dwarf2 has no clean way to discern C++ static and non-static
                 member functions. G++ helps GDB by marking the first
                 member functions. G++ helps GDB by marking the first
                 parameter for non-static member functions (which is the
                 parameter for non-static member functions (which is the
                 this pointer) as artificial. We pass this information
                 this pointer) as artificial. We pass this information
                 to dwarf2_add_member_fn via TYPE_FIELD_ARTIFICIAL.  */
                 to dwarf2_add_member_fn via TYPE_FIELD_ARTIFICIAL.  */
              attr = dwarf_attr (child_die, DW_AT_artificial);
              attr = dwarf_attr (child_die, DW_AT_artificial);
              if (attr)
              if (attr)
                TYPE_FIELD_ARTIFICIAL (ftype, iparams) = DW_UNSND (attr);
                TYPE_FIELD_ARTIFICIAL (ftype, iparams) = DW_UNSND (attr);
              else
              else
                TYPE_FIELD_ARTIFICIAL (ftype, iparams) = 0;
                TYPE_FIELD_ARTIFICIAL (ftype, iparams) = 0;
              TYPE_FIELD_TYPE (ftype, iparams) = die_type (child_die, objfile);
              TYPE_FIELD_TYPE (ftype, iparams) = die_type (child_die, objfile);
              iparams++;
              iparams++;
            }
            }
          child_die = sibling_die (child_die);
          child_die = sibling_die (child_die);
        }
        }
    }
    }
 
 
  die->type = ftype;
  die->type = ftype;
}
}
 
 
static void
static void
read_typedef (die, objfile)
read_typedef (die, objfile)
     struct die_info *die;
     struct die_info *die;
     struct objfile *objfile;
     struct objfile *objfile;
{
{
  struct type *type;
  struct type *type;
 
 
  if (!die->type)
  if (!die->type)
    {
    {
      struct attribute *attr;
      struct attribute *attr;
      struct type *xtype;
      struct type *xtype;
 
 
      xtype = die_type (die, objfile);
      xtype = die_type (die, objfile);
 
 
      type = alloc_type (objfile);
      type = alloc_type (objfile);
      TYPE_CODE (type) = TYPE_CODE_TYPEDEF;
      TYPE_CODE (type) = TYPE_CODE_TYPEDEF;
      TYPE_FLAGS (type) |= TYPE_FLAG_TARGET_STUB;
      TYPE_FLAGS (type) |= TYPE_FLAG_TARGET_STUB;
      TYPE_TARGET_TYPE (type) = xtype;
      TYPE_TARGET_TYPE (type) = xtype;
      attr = dwarf_attr (die, DW_AT_name);
      attr = dwarf_attr (die, DW_AT_name);
      if (attr && DW_STRING (attr))
      if (attr && DW_STRING (attr))
        TYPE_NAME (type) = obsavestring (DW_STRING (attr),
        TYPE_NAME (type) = obsavestring (DW_STRING (attr),
                                         strlen (DW_STRING (attr)),
                                         strlen (DW_STRING (attr)),
                                         &objfile->type_obstack);
                                         &objfile->type_obstack);
 
 
      die->type = type;
      die->type = type;
    }
    }
}
}
 
 
/* Find a representation of a given base type and install
/* Find a representation of a given base type and install
   it in the TYPE field of the die.  */
   it in the TYPE field of the die.  */
 
 
static void
static void
read_base_type (die, objfile)
read_base_type (die, objfile)
     struct die_info *die;
     struct die_info *die;
     struct objfile *objfile;
     struct objfile *objfile;
{
{
  struct type *type;
  struct type *type;
  struct attribute *attr;
  struct attribute *attr;
  int encoding = 0, size = 0;
  int encoding = 0, size = 0;
 
 
  /* If we've already decoded this die, this is a no-op. */
  /* If we've already decoded this die, this is a no-op. */
  if (die->type)
  if (die->type)
    {
    {
      return;
      return;
    }
    }
 
 
  attr = dwarf_attr (die, DW_AT_encoding);
  attr = dwarf_attr (die, DW_AT_encoding);
  if (attr)
  if (attr)
    {
    {
      encoding = DW_UNSND (attr);
      encoding = DW_UNSND (attr);
    }
    }
  attr = dwarf_attr (die, DW_AT_byte_size);
  attr = dwarf_attr (die, DW_AT_byte_size);
  if (attr)
  if (attr)
    {
    {
      size = DW_UNSND (attr);
      size = DW_UNSND (attr);
    }
    }
  attr = dwarf_attr (die, DW_AT_name);
  attr = dwarf_attr (die, DW_AT_name);
  if (attr && DW_STRING (attr))
  if (attr && DW_STRING (attr))
    {
    {
      enum type_code code = TYPE_CODE_INT;
      enum type_code code = TYPE_CODE_INT;
      int is_unsigned = 0;
      int is_unsigned = 0;
 
 
      switch (encoding)
      switch (encoding)
        {
        {
        case DW_ATE_address:
        case DW_ATE_address:
          /* Turn DW_ATE_address into a void * pointer.  */
          /* Turn DW_ATE_address into a void * pointer.  */
          code = TYPE_CODE_PTR;
          code = TYPE_CODE_PTR;
          is_unsigned = 1;
          is_unsigned = 1;
          break;
          break;
        case DW_ATE_boolean:
        case DW_ATE_boolean:
          code = TYPE_CODE_BOOL;
          code = TYPE_CODE_BOOL;
          is_unsigned = 1;
          is_unsigned = 1;
          break;
          break;
        case DW_ATE_complex_float:
        case DW_ATE_complex_float:
          code = TYPE_CODE_COMPLEX;
          code = TYPE_CODE_COMPLEX;
          break;
          break;
        case DW_ATE_float:
        case DW_ATE_float:
          code = TYPE_CODE_FLT;
          code = TYPE_CODE_FLT;
          break;
          break;
        case DW_ATE_signed:
        case DW_ATE_signed:
        case DW_ATE_signed_char:
        case DW_ATE_signed_char:
          break;
          break;
        case DW_ATE_unsigned:
        case DW_ATE_unsigned:
        case DW_ATE_unsigned_char:
        case DW_ATE_unsigned_char:
          is_unsigned = 1;
          is_unsigned = 1;
          break;
          break;
        default:
        default:
          complain (&dwarf2_unsupported_at_encoding,
          complain (&dwarf2_unsupported_at_encoding,
                    dwarf_type_encoding_name (encoding));
                    dwarf_type_encoding_name (encoding));
          break;
          break;
        }
        }
      type = init_type (code, size, is_unsigned, DW_STRING (attr), objfile);
      type = init_type (code, size, is_unsigned, DW_STRING (attr), objfile);
      if (encoding == DW_ATE_address)
      if (encoding == DW_ATE_address)
        TYPE_TARGET_TYPE (type) = dwarf2_fundamental_type (objfile, FT_VOID);
        TYPE_TARGET_TYPE (type) = dwarf2_fundamental_type (objfile, FT_VOID);
    }
    }
  else
  else
    {
    {
      type = dwarf_base_type (encoding, size, objfile);
      type = dwarf_base_type (encoding, size, objfile);
    }
    }
  die->type = type;
  die->type = type;
}
}
 
 
/* Read a whole compilation unit into a linked list of dies.  */
/* Read a whole compilation unit into a linked list of dies.  */
 
 
struct die_info *
struct die_info *
read_comp_unit (info_ptr, abfd)
read_comp_unit (info_ptr, abfd)
     char *info_ptr;
     char *info_ptr;
     bfd *abfd;
     bfd *abfd;
{
{
  struct die_info *first_die, *last_die, *die;
  struct die_info *first_die, *last_die, *die;
  char *cur_ptr;
  char *cur_ptr;
  int nesting_level;
  int nesting_level;
 
 
  /* Reset die reference table, we are building a new one now. */
  /* Reset die reference table, we are building a new one now. */
  dwarf2_empty_die_ref_table ();
  dwarf2_empty_die_ref_table ();
 
 
  cur_ptr = info_ptr;
  cur_ptr = info_ptr;
  nesting_level = 0;
  nesting_level = 0;
  first_die = last_die = NULL;
  first_die = last_die = NULL;
  do
  do
    {
    {
      cur_ptr = read_full_die (&die, abfd, cur_ptr);
      cur_ptr = read_full_die (&die, abfd, cur_ptr);
      if (die->has_children)
      if (die->has_children)
        {
        {
          nesting_level++;
          nesting_level++;
        }
        }
      if (die->tag == 0)
      if (die->tag == 0)
        {
        {
          nesting_level--;
          nesting_level--;
        }
        }
 
 
      die->next = NULL;
      die->next = NULL;
 
 
      /* Enter die in reference hash table */
      /* Enter die in reference hash table */
      store_in_ref_table (die->offset, die);
      store_in_ref_table (die->offset, die);
 
 
      if (!first_die)
      if (!first_die)
        {
        {
          first_die = last_die = die;
          first_die = last_die = die;
        }
        }
      else
      else
        {
        {
          last_die->next = die;
          last_die->next = die;
          last_die = die;
          last_die = die;
        }
        }
    }
    }
  while (nesting_level > 0);
  while (nesting_level > 0);
  return first_die;
  return first_die;
}
}
 
 
/* Free a linked list of dies.  */
/* Free a linked list of dies.  */
 
 
static void
static void
free_die_list (dies)
free_die_list (dies)
     struct die_info *dies;
     struct die_info *dies;
{
{
  struct die_info *die, *next;
  struct die_info *die, *next;
 
 
  die = dies;
  die = dies;
  while (die)
  while (die)
    {
    {
      next = die->next;
      next = die->next;
      free (die->attrs);
      free (die->attrs);
      free (die);
      free (die);
      die = next;
      die = next;
    }
    }
}
}
 
 
/* Read the contents of the section at OFFSET and of size SIZE from the
/* Read the contents of the section at OFFSET and of size SIZE from the
   object file specified by OBJFILE into the psymbol_obstack and return it.  */
   object file specified by OBJFILE into the psymbol_obstack and return it.  */
 
 
static char *
static char *
dwarf2_read_section (objfile, offset, size)
dwarf2_read_section (objfile, offset, size)
     struct objfile *objfile;
     struct objfile *objfile;
     file_ptr offset;
     file_ptr offset;
     unsigned int size;
     unsigned int size;
{
{
  bfd *abfd = objfile->obfd;
  bfd *abfd = objfile->obfd;
  char *buf;
  char *buf;
 
 
  if (size == 0)
  if (size == 0)
    return NULL;
    return NULL;
 
 
  buf = (char *) obstack_alloc (&objfile->psymbol_obstack, size);
  buf = (char *) obstack_alloc (&objfile->psymbol_obstack, size);
  if ((bfd_seek (abfd, offset, SEEK_SET) != 0) ||
  if ((bfd_seek (abfd, offset, SEEK_SET) != 0) ||
      (bfd_read (buf, size, 1, abfd) != size))
      (bfd_read (buf, size, 1, abfd) != size))
    {
    {
      buf = NULL;
      buf = NULL;
      error ("Dwarf Error: Can't read DWARF data from '%s'",
      error ("Dwarf Error: Can't read DWARF data from '%s'",
             bfd_get_filename (abfd));
             bfd_get_filename (abfd));
    }
    }
  return buf;
  return buf;
}
}
 
 
/* In DWARF version 2, the description of the debugging information is
/* In DWARF version 2, the description of the debugging information is
   stored in a separate .debug_abbrev section.  Before we read any
   stored in a separate .debug_abbrev section.  Before we read any
   dies from a section we read in all abbreviations and install them
   dies from a section we read in all abbreviations and install them
   in a hash table.  */
   in a hash table.  */
 
 
static void
static void
dwarf2_read_abbrevs (abfd, offset)
dwarf2_read_abbrevs (abfd, offset)
     bfd *abfd;
     bfd *abfd;
     unsigned int offset;
     unsigned int offset;
{
{
  char *abbrev_ptr;
  char *abbrev_ptr;
  struct abbrev_info *cur_abbrev;
  struct abbrev_info *cur_abbrev;
  unsigned int abbrev_number, bytes_read, abbrev_name;
  unsigned int abbrev_number, bytes_read, abbrev_name;
  unsigned int abbrev_form, hash_number;
  unsigned int abbrev_form, hash_number;
 
 
  /* empty the table */
  /* empty the table */
  dwarf2_empty_abbrev_table (NULL);
  dwarf2_empty_abbrev_table (NULL);
 
 
  abbrev_ptr = dwarf_abbrev_buffer + offset;
  abbrev_ptr = dwarf_abbrev_buffer + offset;
  abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
  abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
  abbrev_ptr += bytes_read;
  abbrev_ptr += bytes_read;
 
 
  /* loop until we reach an abbrev number of 0 */
  /* loop until we reach an abbrev number of 0 */
  while (abbrev_number)
  while (abbrev_number)
    {
    {
      cur_abbrev = dwarf_alloc_abbrev ();
      cur_abbrev = dwarf_alloc_abbrev ();
 
 
      /* read in abbrev header */
      /* read in abbrev header */
      cur_abbrev->number = abbrev_number;
      cur_abbrev->number = abbrev_number;
      cur_abbrev->tag = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
      cur_abbrev->tag = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
      abbrev_ptr += bytes_read;
      abbrev_ptr += bytes_read;
      cur_abbrev->has_children = read_1_byte (abfd, abbrev_ptr);
      cur_abbrev->has_children = read_1_byte (abfd, abbrev_ptr);
      abbrev_ptr += 1;
      abbrev_ptr += 1;
 
 
      /* now read in declarations */
      /* now read in declarations */
      abbrev_name = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
      abbrev_name = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
      abbrev_ptr += bytes_read;
      abbrev_ptr += bytes_read;
      abbrev_form = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
      abbrev_form = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
      abbrev_ptr += bytes_read;
      abbrev_ptr += bytes_read;
      while (abbrev_name)
      while (abbrev_name)
        {
        {
          if ((cur_abbrev->num_attrs % ATTR_ALLOC_CHUNK) == 0)
          if ((cur_abbrev->num_attrs % ATTR_ALLOC_CHUNK) == 0)
            {
            {
              cur_abbrev->attrs = (struct attr_abbrev *)
              cur_abbrev->attrs = (struct attr_abbrev *)
                xrealloc (cur_abbrev->attrs,
                xrealloc (cur_abbrev->attrs,
                          (cur_abbrev->num_attrs + ATTR_ALLOC_CHUNK)
                          (cur_abbrev->num_attrs + ATTR_ALLOC_CHUNK)
                          * sizeof (struct attr_abbrev));
                          * sizeof (struct attr_abbrev));
            }
            }
          cur_abbrev->attrs[cur_abbrev->num_attrs].name = abbrev_name;
          cur_abbrev->attrs[cur_abbrev->num_attrs].name = abbrev_name;
          cur_abbrev->attrs[cur_abbrev->num_attrs++].form = abbrev_form;
          cur_abbrev->attrs[cur_abbrev->num_attrs++].form = abbrev_form;
          abbrev_name = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
          abbrev_name = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
          abbrev_ptr += bytes_read;
          abbrev_ptr += bytes_read;
          abbrev_form = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
          abbrev_form = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
          abbrev_ptr += bytes_read;
          abbrev_ptr += bytes_read;
        }
        }
 
 
      hash_number = abbrev_number % ABBREV_HASH_SIZE;
      hash_number = abbrev_number % ABBREV_HASH_SIZE;
      cur_abbrev->next = dwarf2_abbrevs[hash_number];
      cur_abbrev->next = dwarf2_abbrevs[hash_number];
      dwarf2_abbrevs[hash_number] = cur_abbrev;
      dwarf2_abbrevs[hash_number] = cur_abbrev;
 
 
      /* Get next abbreviation.
      /* Get next abbreviation.
         Under Irix6 the abbreviations for a compilation unit are not
         Under Irix6 the abbreviations for a compilation unit are not
         always properly terminated with an abbrev number of 0.
         always properly terminated with an abbrev number of 0.
         Exit loop if we encounter an abbreviation which we have
         Exit loop if we encounter an abbreviation which we have
         already read (which means we are about to read the abbreviations
         already read (which means we are about to read the abbreviations
         for the next compile unit) or if the end of the abbreviation
         for the next compile unit) or if the end of the abbreviation
         table is reached.  */
         table is reached.  */
      if ((unsigned int) (abbrev_ptr - dwarf_abbrev_buffer)
      if ((unsigned int) (abbrev_ptr - dwarf_abbrev_buffer)
          >= dwarf_abbrev_size)
          >= dwarf_abbrev_size)
        break;
        break;
      abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
      abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
      abbrev_ptr += bytes_read;
      abbrev_ptr += bytes_read;
      if (dwarf2_lookup_abbrev (abbrev_number) != NULL)
      if (dwarf2_lookup_abbrev (abbrev_number) != NULL)
        break;
        break;
    }
    }
}
}
 
 
/* Empty the abbrev table for a new compilation unit.  */
/* Empty the abbrev table for a new compilation unit.  */
 
 
/* ARGSUSED */
/* ARGSUSED */
static void
static void
dwarf2_empty_abbrev_table (ignore)
dwarf2_empty_abbrev_table (ignore)
     PTR ignore;
     PTR ignore;
{
{
  int i;
  int i;
  struct abbrev_info *abbrev, *next;
  struct abbrev_info *abbrev, *next;
 
 
  for (i = 0; i < ABBREV_HASH_SIZE; ++i)
  for (i = 0; i < ABBREV_HASH_SIZE; ++i)
    {
    {
      next = NULL;
      next = NULL;
      abbrev = dwarf2_abbrevs[i];
      abbrev = dwarf2_abbrevs[i];
      while (abbrev)
      while (abbrev)
        {
        {
          next = abbrev->next;
          next = abbrev->next;
          free (abbrev->attrs);
          free (abbrev->attrs);
          free (abbrev);
          free (abbrev);
          abbrev = next;
          abbrev = next;
        }
        }
      dwarf2_abbrevs[i] = NULL;
      dwarf2_abbrevs[i] = NULL;
    }
    }
}
}
 
 
/* Lookup an abbrev_info structure in the abbrev hash table.  */
/* Lookup an abbrev_info structure in the abbrev hash table.  */
 
 
static struct abbrev_info *
static struct abbrev_info *
dwarf2_lookup_abbrev (number)
dwarf2_lookup_abbrev (number)
     unsigned int number;
     unsigned int number;
{
{
  unsigned int hash_number;
  unsigned int hash_number;
  struct abbrev_info *abbrev;
  struct abbrev_info *abbrev;
 
 
  hash_number = number % ABBREV_HASH_SIZE;
  hash_number = number % ABBREV_HASH_SIZE;
  abbrev = dwarf2_abbrevs[hash_number];
  abbrev = dwarf2_abbrevs[hash_number];
 
 
  while (abbrev)
  while (abbrev)
    {
    {
      if (abbrev->number == number)
      if (abbrev->number == number)
        return abbrev;
        return abbrev;
      else
      else
        abbrev = abbrev->next;
        abbrev = abbrev->next;
    }
    }
  return NULL;
  return NULL;
}
}
 
 
/* Read a minimal amount of information into the minimal die structure.  */
/* Read a minimal amount of information into the minimal die structure.  */
 
 
static char *
static char *
read_partial_die (part_die, abfd, info_ptr, has_pc_info)
read_partial_die (part_die, abfd, info_ptr, has_pc_info)
     struct partial_die_info *part_die;
     struct partial_die_info *part_die;
     bfd *abfd;
     bfd *abfd;
     char *info_ptr;
     char *info_ptr;
     int *has_pc_info;
     int *has_pc_info;
{
{
  unsigned int abbrev_number, bytes_read, i;
  unsigned int abbrev_number, bytes_read, i;
  struct abbrev_info *abbrev;
  struct abbrev_info *abbrev;
  struct attribute attr;
  struct attribute attr;
  struct attribute spec_attr;
  struct attribute spec_attr;
  int found_spec_attr = 0;
  int found_spec_attr = 0;
  int has_low_pc_attr = 0;
  int has_low_pc_attr = 0;
  int has_high_pc_attr = 0;
  int has_high_pc_attr = 0;
 
 
  *part_die = zeroed_partial_die;
  *part_die = zeroed_partial_die;
  *has_pc_info = 0;
  *has_pc_info = 0;
  abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
  abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
  info_ptr += bytes_read;
  info_ptr += bytes_read;
  if (!abbrev_number)
  if (!abbrev_number)
    return info_ptr;
    return info_ptr;
 
 
  abbrev = dwarf2_lookup_abbrev (abbrev_number);
  abbrev = dwarf2_lookup_abbrev (abbrev_number);
  if (!abbrev)
  if (!abbrev)
    {
    {
      error ("Dwarf Error: Could not find abbrev number %d.", abbrev_number);
      error ("Dwarf Error: Could not find abbrev number %d.", abbrev_number);
    }
    }
  part_die->offset = info_ptr - dwarf_info_buffer;
  part_die->offset = info_ptr - dwarf_info_buffer;
  part_die->tag = abbrev->tag;
  part_die->tag = abbrev->tag;
  part_die->has_children = abbrev->has_children;
  part_die->has_children = abbrev->has_children;
  part_die->abbrev = abbrev_number;
  part_die->abbrev = abbrev_number;
 
 
  for (i = 0; i < abbrev->num_attrs; ++i)
  for (i = 0; i < abbrev->num_attrs; ++i)
    {
    {
      info_ptr = read_attribute (&attr, &abbrev->attrs[i], abfd, info_ptr);
      info_ptr = read_attribute (&attr, &abbrev->attrs[i], abfd, info_ptr);
 
 
      /* Store the data if it is of an attribute we want to keep in a
      /* Store the data if it is of an attribute we want to keep in a
         partial symbol table.  */
         partial symbol table.  */
      switch (attr.name)
      switch (attr.name)
        {
        {
        case DW_AT_name:
        case DW_AT_name:
 
 
          /* Prefer DW_AT_MIPS_linkage_name over DW_AT_name.  */
          /* Prefer DW_AT_MIPS_linkage_name over DW_AT_name.  */
          if (part_die->name == NULL)
          if (part_die->name == NULL)
            part_die->name = DW_STRING (&attr);
            part_die->name = DW_STRING (&attr);
          break;
          break;
        case DW_AT_MIPS_linkage_name:
        case DW_AT_MIPS_linkage_name:
          part_die->name = DW_STRING (&attr);
          part_die->name = DW_STRING (&attr);
          break;
          break;
        case DW_AT_low_pc:
        case DW_AT_low_pc:
          has_low_pc_attr = 1;
          has_low_pc_attr = 1;
          part_die->lowpc = DW_ADDR (&attr);
          part_die->lowpc = DW_ADDR (&attr);
          break;
          break;
        case DW_AT_high_pc:
        case DW_AT_high_pc:
          has_high_pc_attr = 1;
          has_high_pc_attr = 1;
          part_die->highpc = DW_ADDR (&attr);
          part_die->highpc = DW_ADDR (&attr);
          break;
          break;
        case DW_AT_location:
        case DW_AT_location:
          part_die->locdesc = DW_BLOCK (&attr);
          part_die->locdesc = DW_BLOCK (&attr);
          break;
          break;
        case DW_AT_language:
        case DW_AT_language:
          part_die->language = DW_UNSND (&attr);
          part_die->language = DW_UNSND (&attr);
          break;
          break;
        case DW_AT_external:
        case DW_AT_external:
          part_die->is_external = DW_UNSND (&attr);
          part_die->is_external = DW_UNSND (&attr);
          break;
          break;
        case DW_AT_declaration:
        case DW_AT_declaration:
          part_die->is_declaration = DW_UNSND (&attr);
          part_die->is_declaration = DW_UNSND (&attr);
          break;
          break;
        case DW_AT_type:
        case DW_AT_type:
          part_die->has_type = 1;
          part_die->has_type = 1;
          break;
          break;
        case DW_AT_abstract_origin:
        case DW_AT_abstract_origin:
        case DW_AT_specification:
        case DW_AT_specification:
          found_spec_attr = 1;
          found_spec_attr = 1;
          spec_attr = attr;
          spec_attr = attr;
          break;
          break;
        case DW_AT_sibling:
        case DW_AT_sibling:
          /* Ignore absolute siblings, they might point outside of
          /* Ignore absolute siblings, they might point outside of
             the current compile unit.  */
             the current compile unit.  */
          if (attr.form == DW_FORM_ref_addr)
          if (attr.form == DW_FORM_ref_addr)
            complain (&dwarf2_absolute_sibling_complaint);
            complain (&dwarf2_absolute_sibling_complaint);
          else
          else
            part_die->sibling =
            part_die->sibling =
              dwarf_info_buffer + dwarf2_get_ref_die_offset (&attr);
              dwarf_info_buffer + dwarf2_get_ref_die_offset (&attr);
          break;
          break;
        default:
        default:
          break;
          break;
        }
        }
    }
    }
 
 
  /* If we found a reference attribute and the die has no name, try
  /* If we found a reference attribute and the die has no name, try
     to find a name in the referred to die.  */
     to find a name in the referred to die.  */
 
 
  if (found_spec_attr && part_die->name == NULL)
  if (found_spec_attr && part_die->name == NULL)
    {
    {
      struct partial_die_info spec_die;
      struct partial_die_info spec_die;
      char *spec_ptr;
      char *spec_ptr;
      int dummy;
      int dummy;
 
 
      spec_ptr = dwarf_info_buffer + dwarf2_get_ref_die_offset (&spec_attr);
      spec_ptr = dwarf_info_buffer + dwarf2_get_ref_die_offset (&spec_attr);
      read_partial_die (&spec_die, abfd, spec_ptr, &dummy);
      read_partial_die (&spec_die, abfd, spec_ptr, &dummy);
      if (spec_die.name)
      if (spec_die.name)
        {
        {
          part_die->name = spec_die.name;
          part_die->name = spec_die.name;
 
 
          /* Copy DW_AT_external attribute if it is set.  */
          /* Copy DW_AT_external attribute if it is set.  */
          if (spec_die.is_external)
          if (spec_die.is_external)
            part_die->is_external = spec_die.is_external;
            part_die->is_external = spec_die.is_external;
        }
        }
    }
    }
 
 
  /* When using the GNU linker, .gnu.linkonce. sections are used to
  /* When using the GNU linker, .gnu.linkonce. sections are used to
     eliminate duplicate copies of functions and vtables and such.
     eliminate duplicate copies of functions and vtables and such.
     The linker will arbitrarily choose one and discard the others.
     The linker will arbitrarily choose one and discard the others.
     The AT_*_pc values for such functions refer to local labels in
     The AT_*_pc values for such functions refer to local labels in
     these sections.  If the section from that file was discarded, the
     these sections.  If the section from that file was discarded, the
     labels are not in the output, so the relocs get a value of 0.
     labels are not in the output, so the relocs get a value of 0.
     If this is a discarded function, mark the pc bounds as invalid,
     If this is a discarded function, mark the pc bounds as invalid,
     so that GDB will ignore it.  */
     so that GDB will ignore it.  */
  if (has_low_pc_attr && has_high_pc_attr
  if (has_low_pc_attr && has_high_pc_attr
      && part_die->lowpc < part_die->highpc
      && part_die->lowpc < part_die->highpc
      && (part_die->lowpc != 0
      && (part_die->lowpc != 0
          || (bfd_get_file_flags (abfd) & HAS_RELOC)))
          || (bfd_get_file_flags (abfd) & HAS_RELOC)))
    *has_pc_info = 1;
    *has_pc_info = 1;
  return info_ptr;
  return info_ptr;
}
}
 
 
/* Read the die from the .debug_info section buffer.  And set diep to
/* Read the die from the .debug_info section buffer.  And set diep to
   point to a newly allocated die with its information.  */
   point to a newly allocated die with its information.  */
 
 
static char *
static char *
read_full_die (diep, abfd, info_ptr)
read_full_die (diep, abfd, info_ptr)
     struct die_info **diep;
     struct die_info **diep;
     bfd *abfd;
     bfd *abfd;
     char *info_ptr;
     char *info_ptr;
{
{
  unsigned int abbrev_number, bytes_read, i, offset;
  unsigned int abbrev_number, bytes_read, i, offset;
  struct abbrev_info *abbrev;
  struct abbrev_info *abbrev;
  struct die_info *die;
  struct die_info *die;
 
 
  offset = info_ptr - dwarf_info_buffer;
  offset = info_ptr - dwarf_info_buffer;
  abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
  abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
  info_ptr += bytes_read;
  info_ptr += bytes_read;
  if (!abbrev_number)
  if (!abbrev_number)
    {
    {
      die = dwarf_alloc_die ();
      die = dwarf_alloc_die ();
      die->tag = 0;
      die->tag = 0;
      die->abbrev = abbrev_number;
      die->abbrev = abbrev_number;
      die->type = NULL;
      die->type = NULL;
      *diep = die;
      *diep = die;
      return info_ptr;
      return info_ptr;
    }
    }
 
 
  abbrev = dwarf2_lookup_abbrev (abbrev_number);
  abbrev = dwarf2_lookup_abbrev (abbrev_number);
  if (!abbrev)
  if (!abbrev)
    {
    {
      error ("Dwarf Error: could not find abbrev number %d.", abbrev_number);
      error ("Dwarf Error: could not find abbrev number %d.", abbrev_number);
    }
    }
  die = dwarf_alloc_die ();
  die = dwarf_alloc_die ();
  die->offset = offset;
  die->offset = offset;
  die->tag = abbrev->tag;
  die->tag = abbrev->tag;
  die->has_children = abbrev->has_children;
  die->has_children = abbrev->has_children;
  die->abbrev = abbrev_number;
  die->abbrev = abbrev_number;
  die->type = NULL;
  die->type = NULL;
 
 
  die->num_attrs = abbrev->num_attrs;
  die->num_attrs = abbrev->num_attrs;
  die->attrs = (struct attribute *)
  die->attrs = (struct attribute *)
    xmalloc (die->num_attrs * sizeof (struct attribute));
    xmalloc (die->num_attrs * sizeof (struct attribute));
 
 
  for (i = 0; i < abbrev->num_attrs; ++i)
  for (i = 0; i < abbrev->num_attrs; ++i)
    {
    {
      info_ptr = read_attribute (&die->attrs[i], &abbrev->attrs[i],
      info_ptr = read_attribute (&die->attrs[i], &abbrev->attrs[i],
                                 abfd, info_ptr);
                                 abfd, info_ptr);
    }
    }
 
 
  *diep = die;
  *diep = die;
  return info_ptr;
  return info_ptr;
}
}
 
 
/* Read an attribute described by an abbreviated attribute.  */
/* Read an attribute described by an abbreviated attribute.  */
 
 
static char *
static char *
read_attribute (attr, abbrev, abfd, info_ptr)
read_attribute (attr, abbrev, abfd, info_ptr)
     struct attribute *attr;
     struct attribute *attr;
     struct attr_abbrev *abbrev;
     struct attr_abbrev *abbrev;
     bfd *abfd;
     bfd *abfd;
     char *info_ptr;
     char *info_ptr;
{
{
  unsigned int bytes_read;
  unsigned int bytes_read;
  struct dwarf_block *blk;
  struct dwarf_block *blk;
 
 
  attr->name = abbrev->name;
  attr->name = abbrev->name;
  attr->form = abbrev->form;
  attr->form = abbrev->form;
  switch (abbrev->form)
  switch (abbrev->form)
    {
    {
    case DW_FORM_addr:
    case DW_FORM_addr:
    case DW_FORM_ref_addr:
    case DW_FORM_ref_addr:
      DW_ADDR (attr) = read_address (abfd, info_ptr);
      DW_ADDR (attr) = read_address (abfd, info_ptr);
      info_ptr += address_size;
      info_ptr += address_size;
      break;
      break;
    case DW_FORM_block2:
    case DW_FORM_block2:
      blk = dwarf_alloc_block ();
      blk = dwarf_alloc_block ();
      blk->size = read_2_bytes (abfd, info_ptr);
      blk->size = read_2_bytes (abfd, info_ptr);
      info_ptr += 2;
      info_ptr += 2;
      blk->data = read_n_bytes (abfd, info_ptr, blk->size);
      blk->data = read_n_bytes (abfd, info_ptr, blk->size);
      info_ptr += blk->size;
      info_ptr += blk->size;
      DW_BLOCK (attr) = blk;
      DW_BLOCK (attr) = blk;
      break;
      break;
    case DW_FORM_block4:
    case DW_FORM_block4:
      blk = dwarf_alloc_block ();
      blk = dwarf_alloc_block ();
      blk->size = read_4_bytes (abfd, info_ptr);
      blk->size = read_4_bytes (abfd, info_ptr);
      info_ptr += 4;
      info_ptr += 4;
      blk->data = read_n_bytes (abfd, info_ptr, blk->size);
      blk->data = read_n_bytes (abfd, info_ptr, blk->size);
      info_ptr += blk->size;
      info_ptr += blk->size;
      DW_BLOCK (attr) = blk;
      DW_BLOCK (attr) = blk;
      break;
      break;
    case DW_FORM_data2:
    case DW_FORM_data2:
      DW_UNSND (attr) = read_2_bytes (abfd, info_ptr);
      DW_UNSND (attr) = read_2_bytes (abfd, info_ptr);
      info_ptr += 2;
      info_ptr += 2;
      break;
      break;
    case DW_FORM_data4:
    case DW_FORM_data4:
      DW_UNSND (attr) = read_4_bytes (abfd, info_ptr);
      DW_UNSND (attr) = read_4_bytes (abfd, info_ptr);
      info_ptr += 4;
      info_ptr += 4;
      break;
      break;
    case DW_FORM_data8:
    case DW_FORM_data8:
      DW_UNSND (attr) = read_8_bytes (abfd, info_ptr);
      DW_UNSND (attr) = read_8_bytes (abfd, info_ptr);
      info_ptr += 8;
      info_ptr += 8;
      break;
      break;
    case DW_FORM_string:
    case DW_FORM_string:
      DW_STRING (attr) = read_string (abfd, info_ptr, &bytes_read);
      DW_STRING (attr) = read_string (abfd, info_ptr, &bytes_read);
      info_ptr += bytes_read;
      info_ptr += bytes_read;
      break;
      break;
    case DW_FORM_block:
    case DW_FORM_block:
      blk = dwarf_alloc_block ();
      blk = dwarf_alloc_block ();
      blk->size = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
      blk->size = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
      info_ptr += bytes_read;
      info_ptr += bytes_read;
      blk->data = read_n_bytes (abfd, info_ptr, blk->size);
      blk->data = read_n_bytes (abfd, info_ptr, blk->size);
      info_ptr += blk->size;
      info_ptr += blk->size;
      DW_BLOCK (attr) = blk;
      DW_BLOCK (attr) = blk;
      break;
      break;
    case DW_FORM_block1:
    case DW_FORM_block1:
      blk = dwarf_alloc_block ();
      blk = dwarf_alloc_block ();
      blk->size = read_1_byte (abfd, info_ptr);
      blk->size = read_1_byte (abfd, info_ptr);
      info_ptr += 1;
      info_ptr += 1;
      blk->data = read_n_bytes (abfd, info_ptr, blk->size);
      blk->data = read_n_bytes (abfd, info_ptr, blk->size);
      info_ptr += blk->size;
      info_ptr += blk->size;
      DW_BLOCK (attr) = blk;
      DW_BLOCK (attr) = blk;
      break;
      break;
    case DW_FORM_data1:
    case DW_FORM_data1:
      DW_UNSND (attr) = read_1_byte (abfd, info_ptr);
      DW_UNSND (attr) = read_1_byte (abfd, info_ptr);
      info_ptr += 1;
      info_ptr += 1;
      break;
      break;
    case DW_FORM_flag:
    case DW_FORM_flag:
      DW_UNSND (attr) = read_1_byte (abfd, info_ptr);
      DW_UNSND (attr) = read_1_byte (abfd, info_ptr);
      info_ptr += 1;
      info_ptr += 1;
      break;
      break;
    case DW_FORM_sdata:
    case DW_FORM_sdata:
      DW_SND (attr) = read_signed_leb128 (abfd, info_ptr, &bytes_read);
      DW_SND (attr) = read_signed_leb128 (abfd, info_ptr, &bytes_read);
      info_ptr += bytes_read;
      info_ptr += bytes_read;
      break;
      break;
    case DW_FORM_udata:
    case DW_FORM_udata:
      DW_UNSND (attr) = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
      DW_UNSND (attr) = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
      info_ptr += bytes_read;
      info_ptr += bytes_read;
      break;
      break;
    case DW_FORM_ref1:
    case DW_FORM_ref1:
      DW_UNSND (attr) = read_1_byte (abfd, info_ptr);
      DW_UNSND (attr) = read_1_byte (abfd, info_ptr);
      info_ptr += 1;
      info_ptr += 1;
      break;
      break;
    case DW_FORM_ref2:
    case DW_FORM_ref2:
      DW_UNSND (attr) = read_2_bytes (abfd, info_ptr);
      DW_UNSND (attr) = read_2_bytes (abfd, info_ptr);
      info_ptr += 2;
      info_ptr += 2;
      break;
      break;
    case DW_FORM_ref4:
    case DW_FORM_ref4:
      DW_UNSND (attr) = read_4_bytes (abfd, info_ptr);
      DW_UNSND (attr) = read_4_bytes (abfd, info_ptr);
      info_ptr += 4;
      info_ptr += 4;
      break;
      break;
    case DW_FORM_ref_udata:
    case DW_FORM_ref_udata:
      DW_UNSND (attr) = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
      DW_UNSND (attr) = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
      info_ptr += bytes_read;
      info_ptr += bytes_read;
      break;
      break;
    case DW_FORM_strp:
    case DW_FORM_strp:
    case DW_FORM_indirect:
    case DW_FORM_indirect:
    default:
    default:
      error ("Dwarf Error: Cannot handle %s in DWARF reader.",
      error ("Dwarf Error: Cannot handle %s in DWARF reader.",
             dwarf_form_name (abbrev->form));
             dwarf_form_name (abbrev->form));
    }
    }
  return info_ptr;
  return info_ptr;
}
}
 
 
/* read dwarf information from a buffer */
/* read dwarf information from a buffer */
 
 
static unsigned int
static unsigned int
read_1_byte (abfd, buf)
read_1_byte (abfd, buf)
     bfd *abfd;
     bfd *abfd;
     char *buf;
     char *buf;
{
{
  return bfd_get_8 (abfd, (bfd_byte *) buf);
  return bfd_get_8 (abfd, (bfd_byte *) buf);
}
}
 
 
static int
static int
read_1_signed_byte (abfd, buf)
read_1_signed_byte (abfd, buf)
     bfd *abfd;
     bfd *abfd;
     char *buf;
     char *buf;
{
{
  return bfd_get_signed_8 (abfd, (bfd_byte *) buf);
  return bfd_get_signed_8 (abfd, (bfd_byte *) buf);
}
}
 
 
static unsigned int
static unsigned int
read_2_bytes (abfd, buf)
read_2_bytes (abfd, buf)
     bfd *abfd;
     bfd *abfd;
     char *buf;
     char *buf;
{
{
  return bfd_get_16 (abfd, (bfd_byte *) buf);
  return bfd_get_16 (abfd, (bfd_byte *) buf);
}
}
 
 
static int
static int
read_2_signed_bytes (abfd, buf)
read_2_signed_bytes (abfd, buf)
     bfd *abfd;
     bfd *abfd;
     char *buf;
     char *buf;
{
{
  return bfd_get_signed_16 (abfd, (bfd_byte *) buf);
  return bfd_get_signed_16 (abfd, (bfd_byte *) buf);
}
}
 
 
static unsigned int
static unsigned int
read_4_bytes (abfd, buf)
read_4_bytes (abfd, buf)
     bfd *abfd;
     bfd *abfd;
     char *buf;
     char *buf;
{
{
  return bfd_get_32 (abfd, (bfd_byte *) buf);
  return bfd_get_32 (abfd, (bfd_byte *) buf);
}
}
 
 
static int
static int
read_4_signed_bytes (abfd, buf)
read_4_signed_bytes (abfd, buf)
     bfd *abfd;
     bfd *abfd;
     char *buf;
     char *buf;
{
{
  return bfd_get_signed_32 (abfd, (bfd_byte *) buf);
  return bfd_get_signed_32 (abfd, (bfd_byte *) buf);
}
}
 
 
static unsigned int
static unsigned int
read_8_bytes (abfd, buf)
read_8_bytes (abfd, buf)
     bfd *abfd;
     bfd *abfd;
     char *buf;
     char *buf;
{
{
  return bfd_get_64 (abfd, (bfd_byte *) buf);
  return bfd_get_64 (abfd, (bfd_byte *) buf);
}
}
 
 
static CORE_ADDR
static CORE_ADDR
read_address (abfd, buf)
read_address (abfd, buf)
     bfd *abfd;
     bfd *abfd;
     char *buf;
     char *buf;
{
{
  CORE_ADDR retval = 0;
  CORE_ADDR retval = 0;
 
 
  switch (address_size)
  switch (address_size)
    {
    {
    case 2:
    case 2:
      retval = bfd_get_16 (abfd, (bfd_byte *) buf);
      retval = bfd_get_16 (abfd, (bfd_byte *) buf);
      break;
      break;
    case 4:
    case 4:
      retval = bfd_get_32 (abfd, (bfd_byte *) buf);
      retval = bfd_get_32 (abfd, (bfd_byte *) buf);
      break;
      break;
    case 8:
    case 8:
      retval = bfd_get_64 (abfd, (bfd_byte *) buf);
      retval = bfd_get_64 (abfd, (bfd_byte *) buf);
      break;
      break;
    default:
    default:
      /* *THE* alternative is 8, right? */
      /* *THE* alternative is 8, right? */
      abort ();
      abort ();
    }
    }
 
 
 return retval;
 return retval;
}
}
 
 
static char *
static char *
read_n_bytes (abfd, buf, size)
read_n_bytes (abfd, buf, size)
     bfd *abfd;
     bfd *abfd;
     char *buf;
     char *buf;
     unsigned int size;
     unsigned int size;
{
{
  /* If the size of a host char is 8 bits, we can return a pointer
  /* If the size of a host char is 8 bits, we can return a pointer
     to the buffer, otherwise we have to copy the data to a buffer
     to the buffer, otherwise we have to copy the data to a buffer
     allocated on the temporary obstack.  */
     allocated on the temporary obstack.  */
#if HOST_CHAR_BIT == 8
#if HOST_CHAR_BIT == 8
  return buf;
  return buf;
#else
#else
  char *ret;
  char *ret;
  unsigned int i;
  unsigned int i;
 
 
  ret = obstack_alloc (&dwarf2_tmp_obstack, size);
  ret = obstack_alloc (&dwarf2_tmp_obstack, size);
  for (i = 0; i < size; ++i)
  for (i = 0; i < size; ++i)
    {
    {
      ret[i] = bfd_get_8 (abfd, (bfd_byte *) buf);
      ret[i] = bfd_get_8 (abfd, (bfd_byte *) buf);
      buf++;
      buf++;
    }
    }
  return ret;
  return ret;
#endif
#endif
}
}
 
 
static char *
static char *
read_string (abfd, buf, bytes_read_ptr)
read_string (abfd, buf, bytes_read_ptr)
     bfd *abfd;
     bfd *abfd;
     char *buf;
     char *buf;
     unsigned int *bytes_read_ptr;
     unsigned int *bytes_read_ptr;
{
{
  /* If the size of a host char is 8 bits, we can return a pointer
  /* If the size of a host char is 8 bits, we can return a pointer
     to the string, otherwise we have to copy the string to a buffer
     to the string, otherwise we have to copy the string to a buffer
     allocated on the temporary obstack.  */
     allocated on the temporary obstack.  */
#if HOST_CHAR_BIT == 8
#if HOST_CHAR_BIT == 8
  if (*buf == '\0')
  if (*buf == '\0')
    {
    {
      *bytes_read_ptr = 1;
      *bytes_read_ptr = 1;
      return NULL;
      return NULL;
    }
    }
  *bytes_read_ptr = strlen (buf) + 1;
  *bytes_read_ptr = strlen (buf) + 1;
  return buf;
  return buf;
#else
#else
  int byte;
  int byte;
  unsigned int i = 0;
  unsigned int i = 0;
 
 
  while ((byte = bfd_get_8 (abfd, (bfd_byte *) buf)) != 0)
  while ((byte = bfd_get_8 (abfd, (bfd_byte *) buf)) != 0)
    {
    {
      obstack_1grow (&dwarf2_tmp_obstack, byte);
      obstack_1grow (&dwarf2_tmp_obstack, byte);
      i++;
      i++;
      buf++;
      buf++;
    }
    }
  if (i == 0)
  if (i == 0)
    {
    {
      *bytes_read_ptr = 1;
      *bytes_read_ptr = 1;
      return NULL;
      return NULL;
    }
    }
  obstack_1grow (&dwarf2_tmp_obstack, '\0');
  obstack_1grow (&dwarf2_tmp_obstack, '\0');
  *bytes_read_ptr = i + 1;
  *bytes_read_ptr = i + 1;
  return obstack_finish (&dwarf2_tmp_obstack);
  return obstack_finish (&dwarf2_tmp_obstack);
#endif
#endif
}
}
 
 
static unsigned int
static unsigned int
read_unsigned_leb128 (abfd, buf, bytes_read_ptr)
read_unsigned_leb128 (abfd, buf, bytes_read_ptr)
     bfd *abfd;
     bfd *abfd;
     char *buf;
     char *buf;
     unsigned int *bytes_read_ptr;
     unsigned int *bytes_read_ptr;
{
{
  unsigned int result, num_read;
  unsigned int result, num_read;
  int i, shift;
  int i, shift;
  unsigned char byte;
  unsigned char byte;
 
 
  result = 0;
  result = 0;
  shift = 0;
  shift = 0;
  num_read = 0;
  num_read = 0;
  i = 0;
  i = 0;
  while (1)
  while (1)
    {
    {
      byte = bfd_get_8 (abfd, (bfd_byte *) buf);
      byte = bfd_get_8 (abfd, (bfd_byte *) buf);
      buf++;
      buf++;
      num_read++;
      num_read++;
      result |= ((byte & 127) << shift);
      result |= ((byte & 127) << shift);
      if ((byte & 128) == 0)
      if ((byte & 128) == 0)
        {
        {
          break;
          break;
        }
        }
      shift += 7;
      shift += 7;
    }
    }
  *bytes_read_ptr = num_read;
  *bytes_read_ptr = num_read;
  return result;
  return result;
}
}
 
 
static int
static int
read_signed_leb128 (abfd, buf, bytes_read_ptr)
read_signed_leb128 (abfd, buf, bytes_read_ptr)
     bfd *abfd;
     bfd *abfd;
     char *buf;
     char *buf;
     unsigned int *bytes_read_ptr;
     unsigned int *bytes_read_ptr;
{
{
  int result;
  int result;
  int i, shift, size, num_read;
  int i, shift, size, num_read;
  unsigned char byte;
  unsigned char byte;
 
 
  result = 0;
  result = 0;
  shift = 0;
  shift = 0;
  size = 32;
  size = 32;
  num_read = 0;
  num_read = 0;
  i = 0;
  i = 0;
  while (1)
  while (1)
    {
    {
      byte = bfd_get_8 (abfd, (bfd_byte *) buf);
      byte = bfd_get_8 (abfd, (bfd_byte *) buf);
      buf++;
      buf++;
      num_read++;
      num_read++;
      result |= ((byte & 127) << shift);
      result |= ((byte & 127) << shift);
      shift += 7;
      shift += 7;
      if ((byte & 128) == 0)
      if ((byte & 128) == 0)
        {
        {
          break;
          break;
        }
        }
    }
    }
  if ((shift < size) && (byte & 0x40))
  if ((shift < size) && (byte & 0x40))
    {
    {
      result |= -(1 << shift);
      result |= -(1 << shift);
    }
    }
  *bytes_read_ptr = num_read;
  *bytes_read_ptr = num_read;
  return result;
  return result;
}
}
 
 
static void
static void
set_cu_language (lang)
set_cu_language (lang)
     unsigned int lang;
     unsigned int lang;
{
{
  switch (lang)
  switch (lang)
    {
    {
    case DW_LANG_C89:
    case DW_LANG_C89:
    case DW_LANG_C:
    case DW_LANG_C:
      cu_language = language_c;
      cu_language = language_c;
      break;
      break;
    case DW_LANG_C_plus_plus:
    case DW_LANG_C_plus_plus:
      cu_language = language_cplus;
      cu_language = language_cplus;
      break;
      break;
    case DW_LANG_Fortran77:
    case DW_LANG_Fortran77:
    case DW_LANG_Fortran90:
    case DW_LANG_Fortran90:
      cu_language = language_fortran;
      cu_language = language_fortran;
      break;
      break;
    case DW_LANG_Mips_Assembler:
    case DW_LANG_Mips_Assembler:
      cu_language = language_asm;
      cu_language = language_asm;
      break;
      break;
    case DW_LANG_Ada83:
    case DW_LANG_Ada83:
    case DW_LANG_Cobol74:
    case DW_LANG_Cobol74:
    case DW_LANG_Cobol85:
    case DW_LANG_Cobol85:
    case DW_LANG_Pascal83:
    case DW_LANG_Pascal83:
    case DW_LANG_Modula2:
    case DW_LANG_Modula2:
    default:
    default:
      cu_language = language_unknown;
      cu_language = language_unknown;
      break;
      break;
    }
    }
  cu_language_defn = language_def (cu_language);
  cu_language_defn = language_def (cu_language);
}
}
 
 
/* Return the named attribute or NULL if not there.  */
/* Return the named attribute or NULL if not there.  */
 
 
static struct attribute *
static struct attribute *
dwarf_attr (die, name)
dwarf_attr (die, name)
     struct die_info *die;
     struct die_info *die;
     unsigned int name;
     unsigned int name;
{
{
  unsigned int i;
  unsigned int i;
  struct attribute *spec = NULL;
  struct attribute *spec = NULL;
 
 
  for (i = 0; i < die->num_attrs; ++i)
  for (i = 0; i < die->num_attrs; ++i)
    {
    {
      if (die->attrs[i].name == name)
      if (die->attrs[i].name == name)
        {
        {
          return &die->attrs[i];
          return &die->attrs[i];
        }
        }
      if (die->attrs[i].name == DW_AT_specification
      if (die->attrs[i].name == DW_AT_specification
          || die->attrs[i].name == DW_AT_abstract_origin)
          || die->attrs[i].name == DW_AT_abstract_origin)
        spec = &die->attrs[i];
        spec = &die->attrs[i];
    }
    }
  if (spec)
  if (spec)
    {
    {
      struct die_info *ref_die =
      struct die_info *ref_die =
      follow_die_ref (dwarf2_get_ref_die_offset (spec));
      follow_die_ref (dwarf2_get_ref_die_offset (spec));
 
 
      if (ref_die)
      if (ref_die)
        return dwarf_attr (ref_die, name);
        return dwarf_attr (ref_die, name);
    }
    }
 
 
  return NULL;
  return NULL;
}
}
 
 
static int
static int
die_is_declaration (struct die_info *die)
die_is_declaration (struct die_info *die)
{
{
  return (dwarf_attr (die, DW_AT_declaration)
  return (dwarf_attr (die, DW_AT_declaration)
          && ! dwarf_attr (die, DW_AT_specification));
          && ! dwarf_attr (die, DW_AT_specification));
}
}
 
 
/* Decode the line number information for the compilation unit whose
/* Decode the line number information for the compilation unit whose
   line number info is at OFFSET in the .debug_line section.
   line number info is at OFFSET in the .debug_line section.
   The compilation directory of the file is passed in COMP_DIR.  */
   The compilation directory of the file is passed in COMP_DIR.  */
 
 
struct filenames
struct filenames
{
{
  unsigned int num_files;
  unsigned int num_files;
  struct fileinfo
  struct fileinfo
    {
    {
      char *name;
      char *name;
      unsigned int dir;
      unsigned int dir;
      unsigned int time;
      unsigned int time;
      unsigned int size;
      unsigned int size;
    }
    }
   *files;
   *files;
};
};
 
 
struct directories
struct directories
  {
  {
    unsigned int num_dirs;
    unsigned int num_dirs;
    char **dirs;
    char **dirs;
  };
  };
 
 
static void
static void
dwarf_decode_lines (offset, comp_dir, abfd)
dwarf_decode_lines (offset, comp_dir, abfd)
     unsigned int offset;
     unsigned int offset;
     char *comp_dir;
     char *comp_dir;
     bfd *abfd;
     bfd *abfd;
{
{
  char *line_ptr;
  char *line_ptr;
  char *line_end;
  char *line_end;
  struct line_head lh;
  struct line_head lh;
  struct cleanup *back_to;
  struct cleanup *back_to;
  unsigned int i, bytes_read;
  unsigned int i, bytes_read;
  char *cur_file, *cur_dir;
  char *cur_file, *cur_dir;
  unsigned char op_code, extended_op, adj_opcode;
  unsigned char op_code, extended_op, adj_opcode;
 
 
#define FILE_ALLOC_CHUNK 5
#define FILE_ALLOC_CHUNK 5
#define DIR_ALLOC_CHUNK 5
#define DIR_ALLOC_CHUNK 5
 
 
  struct filenames files;
  struct filenames files;
  struct directories dirs;
  struct directories dirs;
 
 
  if (dwarf_line_buffer == NULL)
  if (dwarf_line_buffer == NULL)
    {
    {
      complain (&dwarf2_missing_line_number_section);
      complain (&dwarf2_missing_line_number_section);
      return;
      return;
    }
    }
 
 
  files.num_files = 0;
  files.num_files = 0;
  files.files = NULL;
  files.files = NULL;
 
 
  dirs.num_dirs = 0;
  dirs.num_dirs = 0;
  dirs.dirs = NULL;
  dirs.dirs = NULL;
 
 
  line_ptr = dwarf_line_buffer + offset;
  line_ptr = dwarf_line_buffer + offset;
 
 
  /* read in the prologue */
  /* read in the prologue */
  lh.total_length = read_4_bytes (abfd, line_ptr);
  lh.total_length = read_4_bytes (abfd, line_ptr);
  line_ptr += 4;
  line_ptr += 4;
  line_end = line_ptr + lh.total_length;
  line_end = line_ptr + lh.total_length;
  lh.version = read_2_bytes (abfd, line_ptr);
  lh.version = read_2_bytes (abfd, line_ptr);
  line_ptr += 2;
  line_ptr += 2;
  lh.prologue_length = read_4_bytes (abfd, line_ptr);
  lh.prologue_length = read_4_bytes (abfd, line_ptr);
  line_ptr += 4;
  line_ptr += 4;
  lh.minimum_instruction_length = read_1_byte (abfd, line_ptr);
  lh.minimum_instruction_length = read_1_byte (abfd, line_ptr);
  line_ptr += 1;
  line_ptr += 1;
  lh.default_is_stmt = read_1_byte (abfd, line_ptr);
  lh.default_is_stmt = read_1_byte (abfd, line_ptr);
  line_ptr += 1;
  line_ptr += 1;
  lh.line_base = read_1_signed_byte (abfd, line_ptr);
  lh.line_base = read_1_signed_byte (abfd, line_ptr);
  line_ptr += 1;
  line_ptr += 1;
  lh.line_range = read_1_byte (abfd, line_ptr);
  lh.line_range = read_1_byte (abfd, line_ptr);
  line_ptr += 1;
  line_ptr += 1;
  lh.opcode_base = read_1_byte (abfd, line_ptr);
  lh.opcode_base = read_1_byte (abfd, line_ptr);
  line_ptr += 1;
  line_ptr += 1;
  lh.standard_opcode_lengths = (unsigned char *)
  lh.standard_opcode_lengths = (unsigned char *)
    xmalloc (lh.opcode_base * sizeof (unsigned char));
    xmalloc (lh.opcode_base * sizeof (unsigned char));
  back_to = make_cleanup ((make_cleanup_func) free_current_contents,
  back_to = make_cleanup ((make_cleanup_func) free_current_contents,
                          &lh.standard_opcode_lengths);
                          &lh.standard_opcode_lengths);
 
 
  lh.standard_opcode_lengths[0] = 1;
  lh.standard_opcode_lengths[0] = 1;
  for (i = 1; i < lh.opcode_base; ++i)
  for (i = 1; i < lh.opcode_base; ++i)
    {
    {
      lh.standard_opcode_lengths[i] = read_1_byte (abfd, line_ptr);
      lh.standard_opcode_lengths[i] = read_1_byte (abfd, line_ptr);
      line_ptr += 1;
      line_ptr += 1;
    }
    }
 
 
  /* Read directory table  */
  /* Read directory table  */
  while ((cur_dir = read_string (abfd, line_ptr, &bytes_read)) != NULL)
  while ((cur_dir = read_string (abfd, line_ptr, &bytes_read)) != NULL)
    {
    {
      line_ptr += bytes_read;
      line_ptr += bytes_read;
      if ((dirs.num_dirs % DIR_ALLOC_CHUNK) == 0)
      if ((dirs.num_dirs % DIR_ALLOC_CHUNK) == 0)
        {
        {
          dirs.dirs = (char **)
          dirs.dirs = (char **)
            xrealloc (dirs.dirs,
            xrealloc (dirs.dirs,
                      (dirs.num_dirs + DIR_ALLOC_CHUNK) * sizeof (char *));
                      (dirs.num_dirs + DIR_ALLOC_CHUNK) * sizeof (char *));
          if (dirs.num_dirs == 0)
          if (dirs.num_dirs == 0)
            make_cleanup ((make_cleanup_func) free_current_contents, &dirs.dirs);
            make_cleanup ((make_cleanup_func) free_current_contents, &dirs.dirs);
        }
        }
      dirs.dirs[dirs.num_dirs++] = cur_dir;
      dirs.dirs[dirs.num_dirs++] = cur_dir;
    }
    }
  line_ptr += bytes_read;
  line_ptr += bytes_read;
 
 
  /* Read file name table */
  /* Read file name table */
  while ((cur_file = read_string (abfd, line_ptr, &bytes_read)) != NULL)
  while ((cur_file = read_string (abfd, line_ptr, &bytes_read)) != NULL)
    {
    {
      line_ptr += bytes_read;
      line_ptr += bytes_read;
      if ((files.num_files % FILE_ALLOC_CHUNK) == 0)
      if ((files.num_files % FILE_ALLOC_CHUNK) == 0)
        {
        {
          files.files = (struct fileinfo *)
          files.files = (struct fileinfo *)
            xrealloc (files.files,
            xrealloc (files.files,
                      (files.num_files + FILE_ALLOC_CHUNK)
                      (files.num_files + FILE_ALLOC_CHUNK)
                      * sizeof (struct fileinfo));
                      * sizeof (struct fileinfo));
          if (files.num_files == 0)
          if (files.num_files == 0)
            make_cleanup ((make_cleanup_func) free_current_contents,
            make_cleanup ((make_cleanup_func) free_current_contents,
                          &files.files);
                          &files.files);
        }
        }
      files.files[files.num_files].name = cur_file;
      files.files[files.num_files].name = cur_file;
      files.files[files.num_files].dir =
      files.files[files.num_files].dir =
        read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
        read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
      line_ptr += bytes_read;
      line_ptr += bytes_read;
      files.files[files.num_files].time =
      files.files[files.num_files].time =
        read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
        read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
      line_ptr += bytes_read;
      line_ptr += bytes_read;
      files.files[files.num_files].size =
      files.files[files.num_files].size =
        read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
        read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
      line_ptr += bytes_read;
      line_ptr += bytes_read;
      files.num_files++;
      files.num_files++;
    }
    }
  line_ptr += bytes_read;
  line_ptr += bytes_read;
 
 
  /* Read the statement sequences until there's nothing left.  */
  /* Read the statement sequences until there's nothing left.  */
  while (line_ptr < line_end)
  while (line_ptr < line_end)
    {
    {
      /* state machine registers  */
      /* state machine registers  */
      CORE_ADDR address = 0;
      CORE_ADDR address = 0;
      unsigned int file = 1;
      unsigned int file = 1;
      unsigned int line = 1;
      unsigned int line = 1;
      unsigned int column = 0;
      unsigned int column = 0;
      int is_stmt = lh.default_is_stmt;
      int is_stmt = lh.default_is_stmt;
      int basic_block = 0;
      int basic_block = 0;
      int end_sequence = 0;
      int end_sequence = 0;
 
 
      /* Start a subfile for the current file of the state machine.  */
      /* Start a subfile for the current file of the state machine.  */
      if (files.num_files >= file)
      if (files.num_files >= file)
        {
        {
          /* The file and directory tables are 0 based, the references
          /* The file and directory tables are 0 based, the references
             are 1 based.  */
             are 1 based.  */
          dwarf2_start_subfile (files.files[file - 1].name,
          dwarf2_start_subfile (files.files[file - 1].name,
                                (files.files[file - 1].dir
                                (files.files[file - 1].dir
                                 ? dirs.dirs[files.files[file - 1].dir - 1]
                                 ? dirs.dirs[files.files[file - 1].dir - 1]
                                 : comp_dir));
                                 : comp_dir));
        }
        }
 
 
      /* Decode the table. */
      /* Decode the table. */
      while (!end_sequence)
      while (!end_sequence)
        {
        {
          op_code = read_1_byte (abfd, line_ptr);
          op_code = read_1_byte (abfd, line_ptr);
          line_ptr += 1;
          line_ptr += 1;
          switch (op_code)
          switch (op_code)
            {
            {
            case DW_LNS_extended_op:
            case DW_LNS_extended_op:
              line_ptr += 1;    /* ignore length */
              line_ptr += 1;    /* ignore length */
              extended_op = read_1_byte (abfd, line_ptr);
              extended_op = read_1_byte (abfd, line_ptr);
              line_ptr += 1;
              line_ptr += 1;
              switch (extended_op)
              switch (extended_op)
                {
                {
                case DW_LNE_end_sequence:
                case DW_LNE_end_sequence:
                  end_sequence = 1;
                  end_sequence = 1;
                  /* Don't call record_line here.  The end_sequence
                  /* Don't call record_line here.  The end_sequence
                     instruction provides the address of the first byte
                     instruction provides the address of the first byte
                     *after* the last line in the sequence; it's not the
                     *after* the last line in the sequence; it's not the
                     address of any real source line.  However, the GDB
                     address of any real source line.  However, the GDB
                     linetable structure only records the starts of lines,
                     linetable structure only records the starts of lines,
                     not the ends.  This is a weakness of GDB.  */
                     not the ends.  This is a weakness of GDB.  */
                  break;
                  break;
                case DW_LNE_set_address:
                case DW_LNE_set_address:
                  address = read_address (abfd, line_ptr) + baseaddr;
                  address = read_address (abfd, line_ptr) + baseaddr;
                  line_ptr += address_size;
                  line_ptr += address_size;
                  break;
                  break;
                case DW_LNE_define_file:
                case DW_LNE_define_file:
                  cur_file = read_string (abfd, line_ptr, &bytes_read);
                  cur_file = read_string (abfd, line_ptr, &bytes_read);
                  line_ptr += bytes_read;
                  line_ptr += bytes_read;
                  if ((files.num_files % FILE_ALLOC_CHUNK) == 0)
                  if ((files.num_files % FILE_ALLOC_CHUNK) == 0)
                    {
                    {
                      files.files = (struct fileinfo *)
                      files.files = (struct fileinfo *)
                        xrealloc (files.files,
                        xrealloc (files.files,
                                  (files.num_files + FILE_ALLOC_CHUNK)
                                  (files.num_files + FILE_ALLOC_CHUNK)
                                  * sizeof (struct fileinfo));
                                  * sizeof (struct fileinfo));
                      if (files.num_files == 0)
                      if (files.num_files == 0)
                        make_cleanup ((make_cleanup_func) free_current_contents,
                        make_cleanup ((make_cleanup_func) free_current_contents,
                                      &files.files);
                                      &files.files);
                    }
                    }
                  files.files[files.num_files].name = cur_file;
                  files.files[files.num_files].name = cur_file;
                  files.files[files.num_files].dir =
                  files.files[files.num_files].dir =
                    read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
                    read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
                  line_ptr += bytes_read;
                  line_ptr += bytes_read;
                  files.files[files.num_files].time =
                  files.files[files.num_files].time =
                    read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
                    read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
                  line_ptr += bytes_read;
                  line_ptr += bytes_read;
                  files.files[files.num_files].size =
                  files.files[files.num_files].size =
                    read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
                    read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
                  line_ptr += bytes_read;
                  line_ptr += bytes_read;
                  files.num_files++;
                  files.num_files++;
                  break;
                  break;
                default:
                default:
                  complain (&dwarf2_mangled_line_number_section);
                  complain (&dwarf2_mangled_line_number_section);
                  goto done;
                  goto done;
                }
                }
              break;
              break;
            case DW_LNS_copy:
            case DW_LNS_copy:
              record_line (current_subfile, line, address);
              record_line (current_subfile, line, address);
              basic_block = 0;
              basic_block = 0;
              break;
              break;
            case DW_LNS_advance_pc:
            case DW_LNS_advance_pc:
              address += lh.minimum_instruction_length
              address += lh.minimum_instruction_length
                * read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
                * read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
              line_ptr += bytes_read;
              line_ptr += bytes_read;
              break;
              break;
            case DW_LNS_advance_line:
            case DW_LNS_advance_line:
              line += read_signed_leb128 (abfd, line_ptr, &bytes_read);
              line += read_signed_leb128 (abfd, line_ptr, &bytes_read);
              line_ptr += bytes_read;
              line_ptr += bytes_read;
              break;
              break;
            case DW_LNS_set_file:
            case DW_LNS_set_file:
              /* The file and directory tables are 0 based, the references
              /* The file and directory tables are 0 based, the references
                 are 1 based.  */
                 are 1 based.  */
              file = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
              file = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
              line_ptr += bytes_read;
              line_ptr += bytes_read;
              dwarf2_start_subfile
              dwarf2_start_subfile
                (files.files[file - 1].name,
                (files.files[file - 1].name,
                 (files.files[file - 1].dir
                 (files.files[file - 1].dir
                  ? dirs.dirs[files.files[file - 1].dir - 1]
                  ? dirs.dirs[files.files[file - 1].dir - 1]
                  : comp_dir));
                  : comp_dir));
              break;
              break;
            case DW_LNS_set_column:
            case DW_LNS_set_column:
              column = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
              column = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
              line_ptr += bytes_read;
              line_ptr += bytes_read;
              break;
              break;
            case DW_LNS_negate_stmt:
            case DW_LNS_negate_stmt:
              is_stmt = (!is_stmt);
              is_stmt = (!is_stmt);
              break;
              break;
            case DW_LNS_set_basic_block:
            case DW_LNS_set_basic_block:
              basic_block = 1;
              basic_block = 1;
              break;
              break;
            /* Add to the address register of the state machine the
            /* Add to the address register of the state machine the
               address increment value corresponding to special opcode
               address increment value corresponding to special opcode
               255.  Ie, this value is scaled by the minimum instruction
               255.  Ie, this value is scaled by the minimum instruction
               length since special opcode 255 would have scaled the
               length since special opcode 255 would have scaled the
               the increment.  */
               the increment.  */
            case DW_LNS_const_add_pc:
            case DW_LNS_const_add_pc:
              address += (lh.minimum_instruction_length
              address += (lh.minimum_instruction_length
                          * ((255 - lh.opcode_base) / lh.line_range));
                          * ((255 - lh.opcode_base) / lh.line_range));
              break;
              break;
            case DW_LNS_fixed_advance_pc:
            case DW_LNS_fixed_advance_pc:
              address += read_2_bytes (abfd, line_ptr);
              address += read_2_bytes (abfd, line_ptr);
              line_ptr += 2;
              line_ptr += 2;
              break;
              break;
            default:            /* special operand */
            default:            /* special operand */
              adj_opcode = op_code - lh.opcode_base;
              adj_opcode = op_code - lh.opcode_base;
              address += (adj_opcode / lh.line_range)
              address += (adj_opcode / lh.line_range)
                * lh.minimum_instruction_length;
                * lh.minimum_instruction_length;
              line += lh.line_base + (adj_opcode % lh.line_range);
              line += lh.line_base + (adj_opcode % lh.line_range);
              /* append row to matrix using current values */
              /* append row to matrix using current values */
              record_line (current_subfile, line, address);
              record_line (current_subfile, line, address);
              basic_block = 1;
              basic_block = 1;
            }
            }
        }
        }
    }
    }
done:
done:
  do_cleanups (back_to);
  do_cleanups (back_to);
}
}
 
 
/* Start a subfile for DWARF.  FILENAME is the name of the file and
/* Start a subfile for DWARF.  FILENAME is the name of the file and
   DIRNAME the name of the source directory which contains FILENAME
   DIRNAME the name of the source directory which contains FILENAME
   or NULL if not known.
   or NULL if not known.
   This routine tries to keep line numbers from identical absolute and
   This routine tries to keep line numbers from identical absolute and
   relative file names in a common subfile.
   relative file names in a common subfile.
 
 
   Using the `list' example from the GDB testsuite, which resides in
   Using the `list' example from the GDB testsuite, which resides in
   /srcdir and compiling it with Irix6.2 cc in /compdir using a filename
   /srcdir and compiling it with Irix6.2 cc in /compdir using a filename
   of /srcdir/list0.c yields the following debugging information for list0.c:
   of /srcdir/list0.c yields the following debugging information for list0.c:
 
 
   DW_AT_name:          /srcdir/list0.c
   DW_AT_name:          /srcdir/list0.c
   DW_AT_comp_dir:              /compdir
   DW_AT_comp_dir:              /compdir
   files.files[0].name: list0.h
   files.files[0].name: list0.h
   files.files[0].dir:  /srcdir
   files.files[0].dir:  /srcdir
   files.files[1].name: list0.c
   files.files[1].name: list0.c
   files.files[1].dir:  /srcdir
   files.files[1].dir:  /srcdir
 
 
   The line number information for list0.c has to end up in a single
   The line number information for list0.c has to end up in a single
   subfile, so that `break /srcdir/list0.c:1' works as expected.  */
   subfile, so that `break /srcdir/list0.c:1' works as expected.  */
 
 
static void
static void
dwarf2_start_subfile (filename, dirname)
dwarf2_start_subfile (filename, dirname)
     char *filename;
     char *filename;
     char *dirname;
     char *dirname;
{
{
  /* If the filename isn't absolute, try to match an existing subfile
  /* If the filename isn't absolute, try to match an existing subfile
     with the full pathname.  */
     with the full pathname.  */
 
 
  if (*filename != '/' && dirname != NULL)
  if (*filename != '/' && dirname != NULL)
    {
    {
      struct subfile *subfile;
      struct subfile *subfile;
      char *fullname = concat (dirname, "/", filename, NULL);
      char *fullname = concat (dirname, "/", filename, NULL);
 
 
      for (subfile = subfiles; subfile; subfile = subfile->next)
      for (subfile = subfiles; subfile; subfile = subfile->next)
        {
        {
          if (STREQ (subfile->name, fullname))
          if (STREQ (subfile->name, fullname))
            {
            {
              current_subfile = subfile;
              current_subfile = subfile;
              free (fullname);
              free (fullname);
              return;
              return;
            }
            }
        }
        }
      free (fullname);
      free (fullname);
    }
    }
  start_subfile (filename, dirname);
  start_subfile (filename, dirname);
}
}
 
 
/* Given a pointer to a DWARF information entry, figure out if we need
/* Given a pointer to a DWARF information entry, figure out if we need
   to make a symbol table entry for it, and if so, create a new entry
   to make a symbol table entry for it, and if so, create a new entry
   and return a pointer to it.
   and return a pointer to it.
   If TYPE is NULL, determine symbol type from the die, otherwise
   If TYPE is NULL, determine symbol type from the die, otherwise
   used the passed type.  */
   used the passed type.  */
 
 
static struct symbol *
static struct symbol *
new_symbol (die, type, objfile)
new_symbol (die, type, objfile)
     struct die_info *die;
     struct die_info *die;
     struct type *type;
     struct type *type;
     struct objfile *objfile;
     struct objfile *objfile;
{
{
  struct symbol *sym = NULL;
  struct symbol *sym = NULL;
  char *name;
  char *name;
  struct attribute *attr = NULL;
  struct attribute *attr = NULL;
  struct attribute *attr2 = NULL;
  struct attribute *attr2 = NULL;
  CORE_ADDR addr;
  CORE_ADDR addr;
 
 
  name = dwarf2_linkage_name (die);
  name = dwarf2_linkage_name (die);
  if (name)
  if (name)
    {
    {
      sym = (struct symbol *) obstack_alloc (&objfile->symbol_obstack,
      sym = (struct symbol *) obstack_alloc (&objfile->symbol_obstack,
                                             sizeof (struct symbol));
                                             sizeof (struct symbol));
      OBJSTAT (objfile, n_syms++);
      OBJSTAT (objfile, n_syms++);
      memset (sym, 0, sizeof (struct symbol));
      memset (sym, 0, sizeof (struct symbol));
      SYMBOL_NAME (sym) = obsavestring (name, strlen (name),
      SYMBOL_NAME (sym) = obsavestring (name, strlen (name),
                                        &objfile->symbol_obstack);
                                        &objfile->symbol_obstack);
 
 
      /* Default assumptions.
      /* Default assumptions.
         Use the passed type or decode it from the die.  */
         Use the passed type or decode it from the die.  */
      SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
      SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
      SYMBOL_CLASS (sym) = LOC_STATIC;
      SYMBOL_CLASS (sym) = LOC_STATIC;
      if (type != NULL)
      if (type != NULL)
        SYMBOL_TYPE (sym) = type;
        SYMBOL_TYPE (sym) = type;
      else
      else
        SYMBOL_TYPE (sym) = die_type (die, objfile);
        SYMBOL_TYPE (sym) = die_type (die, objfile);
      attr = dwarf_attr (die, DW_AT_decl_line);
      attr = dwarf_attr (die, DW_AT_decl_line);
      if (attr)
      if (attr)
        {
        {
          SYMBOL_LINE (sym) = DW_UNSND (attr);
          SYMBOL_LINE (sym) = DW_UNSND (attr);
        }
        }
 
 
      /* If this symbol is from a C++ compilation, then attempt to
      /* If this symbol is from a C++ compilation, then attempt to
         cache the demangled form for future reference.  This is a
         cache the demangled form for future reference.  This is a
         typical time versus space tradeoff, that was decided in favor
         typical time versus space tradeoff, that was decided in favor
         of time because it sped up C++ symbol lookups by a factor of
         of time because it sped up C++ symbol lookups by a factor of
         about 20. */
         about 20. */
 
 
      SYMBOL_LANGUAGE (sym) = cu_language;
      SYMBOL_LANGUAGE (sym) = cu_language;
      SYMBOL_INIT_DEMANGLED_NAME (sym, &objfile->symbol_obstack);
      SYMBOL_INIT_DEMANGLED_NAME (sym, &objfile->symbol_obstack);
      switch (die->tag)
      switch (die->tag)
        {
        {
        case DW_TAG_label:
        case DW_TAG_label:
          attr = dwarf_attr (die, DW_AT_low_pc);
          attr = dwarf_attr (die, DW_AT_low_pc);
          if (attr)
          if (attr)
            {
            {
              SYMBOL_VALUE_ADDRESS (sym) = DW_ADDR (attr) + baseaddr;
              SYMBOL_VALUE_ADDRESS (sym) = DW_ADDR (attr) + baseaddr;
            }
            }
          SYMBOL_CLASS (sym) = LOC_LABEL;
          SYMBOL_CLASS (sym) = LOC_LABEL;
          break;
          break;
        case DW_TAG_subprogram:
        case DW_TAG_subprogram:
          /* SYMBOL_BLOCK_VALUE (sym) will be filled in later by
          /* SYMBOL_BLOCK_VALUE (sym) will be filled in later by
             finish_block.  */
             finish_block.  */
          SYMBOL_CLASS (sym) = LOC_BLOCK;
          SYMBOL_CLASS (sym) = LOC_BLOCK;
          attr2 = dwarf_attr (die, DW_AT_external);
          attr2 = dwarf_attr (die, DW_AT_external);
          if (attr2 && (DW_UNSND (attr2) != 0))
          if (attr2 && (DW_UNSND (attr2) != 0))
            {
            {
              add_symbol_to_list (sym, &global_symbols);
              add_symbol_to_list (sym, &global_symbols);
            }
            }
          else
          else
            {
            {
              add_symbol_to_list (sym, list_in_scope);
              add_symbol_to_list (sym, list_in_scope);
            }
            }
          break;
          break;
        case DW_TAG_variable:
        case DW_TAG_variable:
          /* Compilation with minimal debug info may result in variables
          /* Compilation with minimal debug info may result in variables
             with missing type entries. Change the misleading `void' type
             with missing type entries. Change the misleading `void' type
             to something sensible.  */
             to something sensible.  */
          if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_VOID)
          if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_VOID)
            SYMBOL_TYPE (sym) = init_type (TYPE_CODE_INT,
            SYMBOL_TYPE (sym) = init_type (TYPE_CODE_INT,
                                           TARGET_INT_BIT / HOST_CHAR_BIT, 0,
                                           TARGET_INT_BIT / HOST_CHAR_BIT, 0,
                                           "<variable, no debug info>",
                                           "<variable, no debug info>",
                                           objfile);
                                           objfile);
          attr = dwarf_attr (die, DW_AT_const_value);
          attr = dwarf_attr (die, DW_AT_const_value);
          if (attr)
          if (attr)
            {
            {
              dwarf2_const_value (attr, sym, objfile);
              dwarf2_const_value (attr, sym, objfile);
              attr2 = dwarf_attr (die, DW_AT_external);
              attr2 = dwarf_attr (die, DW_AT_external);
              if (attr2 && (DW_UNSND (attr2) != 0))
              if (attr2 && (DW_UNSND (attr2) != 0))
                add_symbol_to_list (sym, &global_symbols);
                add_symbol_to_list (sym, &global_symbols);
              else
              else
                add_symbol_to_list (sym, list_in_scope);
                add_symbol_to_list (sym, list_in_scope);
              break;
              break;
            }
            }
          attr = dwarf_attr (die, DW_AT_location);
          attr = dwarf_attr (die, DW_AT_location);
          if (attr)
          if (attr)
            {
            {
              attr2 = dwarf_attr (die, DW_AT_external);
              attr2 = dwarf_attr (die, DW_AT_external);
              if (attr2 && (DW_UNSND (attr2) != 0))
              if (attr2 && (DW_UNSND (attr2) != 0))
                {
                {
                  SYMBOL_VALUE_ADDRESS (sym) =
                  SYMBOL_VALUE_ADDRESS (sym) =
                    decode_locdesc (DW_BLOCK (attr), objfile);
                    decode_locdesc (DW_BLOCK (attr), objfile);
                  add_symbol_to_list (sym, &global_symbols);
                  add_symbol_to_list (sym, &global_symbols);
 
 
                  /* In shared libraries the address of the variable
                  /* In shared libraries the address of the variable
                     in the location descriptor might still be relocatable,
                     in the location descriptor might still be relocatable,
                     so its value could be zero.
                     so its value could be zero.
                     Enter the symbol as a LOC_UNRESOLVED symbol, if its
                     Enter the symbol as a LOC_UNRESOLVED symbol, if its
                     value is zero, the address of the variable will then
                     value is zero, the address of the variable will then
                     be determined from the minimal symbol table whenever
                     be determined from the minimal symbol table whenever
                     the variable is referenced.  */
                     the variable is referenced.  */
                  if (SYMBOL_VALUE_ADDRESS (sym))
                  if (SYMBOL_VALUE_ADDRESS (sym))
                    {
                    {
                      SYMBOL_VALUE_ADDRESS (sym) += baseaddr;
                      SYMBOL_VALUE_ADDRESS (sym) += baseaddr;
                      SYMBOL_CLASS (sym) = LOC_STATIC;
                      SYMBOL_CLASS (sym) = LOC_STATIC;
                    }
                    }
                  else
                  else
                    SYMBOL_CLASS (sym) = LOC_UNRESOLVED;
                    SYMBOL_CLASS (sym) = LOC_UNRESOLVED;
                }
                }
              else
              else
                {
                {
                  SYMBOL_VALUE (sym) = addr =
                  SYMBOL_VALUE (sym) = addr =
                    decode_locdesc (DW_BLOCK (attr), objfile);
                    decode_locdesc (DW_BLOCK (attr), objfile);
                  add_symbol_to_list (sym, list_in_scope);
                  add_symbol_to_list (sym, list_in_scope);
                  if (optimized_out)
                  if (optimized_out)
                    {
                    {
                      SYMBOL_CLASS (sym) = LOC_OPTIMIZED_OUT;
                      SYMBOL_CLASS (sym) = LOC_OPTIMIZED_OUT;
                    }
                    }
                  else if (isreg)
                  else if (isreg)
                    {
                    {
                      SYMBOL_CLASS (sym) = LOC_REGISTER;
                      SYMBOL_CLASS (sym) = LOC_REGISTER;
                    }
                    }
                  else if (offreg)
                  else if (offreg)
                    {
                    {
                      SYMBOL_CLASS (sym) = LOC_BASEREG;
                      SYMBOL_CLASS (sym) = LOC_BASEREG;
                      SYMBOL_BASEREG (sym) = basereg;
                      SYMBOL_BASEREG (sym) = basereg;
                    }
                    }
                  else if (islocal)
                  else if (islocal)
                    {
                    {
                      SYMBOL_CLASS (sym) = LOC_LOCAL;
                      SYMBOL_CLASS (sym) = LOC_LOCAL;
                    }
                    }
                  else
                  else
                    {
                    {
                      SYMBOL_CLASS (sym) = LOC_STATIC;
                      SYMBOL_CLASS (sym) = LOC_STATIC;
                      SYMBOL_VALUE_ADDRESS (sym) = addr + baseaddr;
                      SYMBOL_VALUE_ADDRESS (sym) = addr + baseaddr;
                    }
                    }
                }
                }
            }
            }
          else
          else
            {
            {
              /* We do not know the address of this symbol.
              /* We do not know the address of this symbol.
                 If it is an external symbol and we have type information
                 If it is an external symbol and we have type information
                 for it, enter the symbol as a LOC_UNRESOLVED symbol.
                 for it, enter the symbol as a LOC_UNRESOLVED symbol.
                 The address of the variable will then be determined from
                 The address of the variable will then be determined from
                 the minimal symbol table whenever the variable is
                 the minimal symbol table whenever the variable is
                 referenced.  */
                 referenced.  */
              attr2 = dwarf_attr (die, DW_AT_external);
              attr2 = dwarf_attr (die, DW_AT_external);
              if (attr2 && (DW_UNSND (attr2) != 0)
              if (attr2 && (DW_UNSND (attr2) != 0)
                  && dwarf_attr (die, DW_AT_type) != NULL)
                  && dwarf_attr (die, DW_AT_type) != NULL)
                {
                {
                  SYMBOL_CLASS (sym) = LOC_UNRESOLVED;
                  SYMBOL_CLASS (sym) = LOC_UNRESOLVED;
                  add_symbol_to_list (sym, &global_symbols);
                  add_symbol_to_list (sym, &global_symbols);
                }
                }
            }
            }
          break;
          break;
        case DW_TAG_formal_parameter:
        case DW_TAG_formal_parameter:
          attr = dwarf_attr (die, DW_AT_location);
          attr = dwarf_attr (die, DW_AT_location);
          if (attr)
          if (attr)
            {
            {
              SYMBOL_VALUE (sym) = decode_locdesc (DW_BLOCK (attr), objfile);
              SYMBOL_VALUE (sym) = decode_locdesc (DW_BLOCK (attr), objfile);
              if (isreg)
              if (isreg)
                {
                {
                  SYMBOL_CLASS (sym) = LOC_REGPARM;
                  SYMBOL_CLASS (sym) = LOC_REGPARM;
                }
                }
              else if (offreg)
              else if (offreg)
                {
                {
                  if (isderef)
                  if (isderef)
                    {
                    {
                      if (basereg != frame_base_reg)
                      if (basereg != frame_base_reg)
                        complain (&dwarf2_complex_location_expr);
                        complain (&dwarf2_complex_location_expr);
                      SYMBOL_CLASS (sym) = LOC_REF_ARG;
                      SYMBOL_CLASS (sym) = LOC_REF_ARG;
                    }
                    }
                  else
                  else
                    {
                    {
                      SYMBOL_CLASS (sym) = LOC_BASEREG_ARG;
                      SYMBOL_CLASS (sym) = LOC_BASEREG_ARG;
                      SYMBOL_BASEREG (sym) = basereg;
                      SYMBOL_BASEREG (sym) = basereg;
                    }
                    }
                }
                }
              else
              else
                {
                {
                  SYMBOL_CLASS (sym) = LOC_ARG;
                  SYMBOL_CLASS (sym) = LOC_ARG;
                }
                }
            }
            }
          attr = dwarf_attr (die, DW_AT_const_value);
          attr = dwarf_attr (die, DW_AT_const_value);
          if (attr)
          if (attr)
            {
            {
              dwarf2_const_value (attr, sym, objfile);
              dwarf2_const_value (attr, sym, objfile);
            }
            }
          add_symbol_to_list (sym, list_in_scope);
          add_symbol_to_list (sym, list_in_scope);
          break;
          break;
        case DW_TAG_unspecified_parameters:
        case DW_TAG_unspecified_parameters:
          /* From varargs functions; gdb doesn't seem to have any
          /* From varargs functions; gdb doesn't seem to have any
             interest in this information, so just ignore it for now.
             interest in this information, so just ignore it for now.
             (FIXME?) */
             (FIXME?) */
          break;
          break;
        case DW_TAG_class_type:
        case DW_TAG_class_type:
        case DW_TAG_structure_type:
        case DW_TAG_structure_type:
        case DW_TAG_union_type:
        case DW_TAG_union_type:
        case DW_TAG_enumeration_type:
        case DW_TAG_enumeration_type:
          SYMBOL_CLASS (sym) = LOC_TYPEDEF;
          SYMBOL_CLASS (sym) = LOC_TYPEDEF;
          SYMBOL_NAMESPACE (sym) = STRUCT_NAMESPACE;
          SYMBOL_NAMESPACE (sym) = STRUCT_NAMESPACE;
          add_symbol_to_list (sym, list_in_scope);
          add_symbol_to_list (sym, list_in_scope);
 
 
          /* The semantics of C++ state that "struct foo { ... }" also
          /* The semantics of C++ state that "struct foo { ... }" also
             defines a typedef for "foo". Synthesize a typedef symbol so
             defines a typedef for "foo". Synthesize a typedef symbol so
             that "ptype foo" works as expected.  */
             that "ptype foo" works as expected.  */
          if (cu_language == language_cplus)
          if (cu_language == language_cplus)
            {
            {
              struct symbol *typedef_sym = (struct symbol *)
              struct symbol *typedef_sym = (struct symbol *)
              obstack_alloc (&objfile->symbol_obstack,
              obstack_alloc (&objfile->symbol_obstack,
                             sizeof (struct symbol));
                             sizeof (struct symbol));
              *typedef_sym = *sym;
              *typedef_sym = *sym;
              SYMBOL_NAMESPACE (typedef_sym) = VAR_NAMESPACE;
              SYMBOL_NAMESPACE (typedef_sym) = VAR_NAMESPACE;
              if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0)
              if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0)
                TYPE_NAME (SYMBOL_TYPE (sym)) =
                TYPE_NAME (SYMBOL_TYPE (sym)) =
                  obsavestring (SYMBOL_NAME (sym),
                  obsavestring (SYMBOL_NAME (sym),
                                strlen (SYMBOL_NAME (sym)),
                                strlen (SYMBOL_NAME (sym)),
                                &objfile->type_obstack);
                                &objfile->type_obstack);
              add_symbol_to_list (typedef_sym, list_in_scope);
              add_symbol_to_list (typedef_sym, list_in_scope);
            }
            }
          break;
          break;
        case DW_TAG_typedef:
        case DW_TAG_typedef:
        case DW_TAG_base_type:
        case DW_TAG_base_type:
          SYMBOL_CLASS (sym) = LOC_TYPEDEF;
          SYMBOL_CLASS (sym) = LOC_TYPEDEF;
          SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
          SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
          add_symbol_to_list (sym, list_in_scope);
          add_symbol_to_list (sym, list_in_scope);
          break;
          break;
        case DW_TAG_enumerator:
        case DW_TAG_enumerator:
          attr = dwarf_attr (die, DW_AT_const_value);
          attr = dwarf_attr (die, DW_AT_const_value);
          if (attr)
          if (attr)
            {
            {
              dwarf2_const_value (attr, sym, objfile);
              dwarf2_const_value (attr, sym, objfile);
            }
            }
          add_symbol_to_list (sym, list_in_scope);
          add_symbol_to_list (sym, list_in_scope);
          break;
          break;
        default:
        default:
          /* Not a tag we recognize.  Hopefully we aren't processing
          /* Not a tag we recognize.  Hopefully we aren't processing
             trash data, but since we must specifically ignore things
             trash data, but since we must specifically ignore things
             we don't recognize, there is nothing else we should do at
             we don't recognize, there is nothing else we should do at
             this point. */
             this point. */
          complain (&dwarf2_unsupported_tag, dwarf_tag_name (die->tag));
          complain (&dwarf2_unsupported_tag, dwarf_tag_name (die->tag));
          break;
          break;
        }
        }
    }
    }
  return (sym);
  return (sym);
}
}
 
 
/* Copy constant value from an attribute to a symbol.  */
/* Copy constant value from an attribute to a symbol.  */
 
 
static void
static void
dwarf2_const_value (attr, sym, objfile)
dwarf2_const_value (attr, sym, objfile)
     struct attribute *attr;
     struct attribute *attr;
     struct symbol *sym;
     struct symbol *sym;
     struct objfile *objfile;
     struct objfile *objfile;
{
{
  struct dwarf_block *blk;
  struct dwarf_block *blk;
 
 
  switch (attr->form)
  switch (attr->form)
    {
    {
    case DW_FORM_addr:
    case DW_FORM_addr:
      if (TYPE_LENGTH (SYMBOL_TYPE (sym)) != (unsigned int) address_size)
      if (TYPE_LENGTH (SYMBOL_TYPE (sym)) != (unsigned int) address_size)
        complain (&dwarf2_const_value_length_mismatch, SYMBOL_NAME (sym),
        complain (&dwarf2_const_value_length_mismatch, SYMBOL_NAME (sym),
                  address_size, TYPE_LENGTH (SYMBOL_TYPE (sym)));
                  address_size, TYPE_LENGTH (SYMBOL_TYPE (sym)));
      SYMBOL_VALUE_BYTES (sym) = (char *)
      SYMBOL_VALUE_BYTES (sym) = (char *)
        obstack_alloc (&objfile->symbol_obstack, address_size);
        obstack_alloc (&objfile->symbol_obstack, address_size);
      store_address (SYMBOL_VALUE_BYTES (sym), address_size, DW_ADDR (attr));
      store_address (SYMBOL_VALUE_BYTES (sym), address_size, DW_ADDR (attr));
      SYMBOL_CLASS (sym) = LOC_CONST_BYTES;
      SYMBOL_CLASS (sym) = LOC_CONST_BYTES;
      break;
      break;
    case DW_FORM_block1:
    case DW_FORM_block1:
    case DW_FORM_block2:
    case DW_FORM_block2:
    case DW_FORM_block4:
    case DW_FORM_block4:
    case DW_FORM_block:
    case DW_FORM_block:
      blk = DW_BLOCK (attr);
      blk = DW_BLOCK (attr);
      if (TYPE_LENGTH (SYMBOL_TYPE (sym)) != blk->size)
      if (TYPE_LENGTH (SYMBOL_TYPE (sym)) != blk->size)
        complain (&dwarf2_const_value_length_mismatch, SYMBOL_NAME (sym),
        complain (&dwarf2_const_value_length_mismatch, SYMBOL_NAME (sym),
                  blk->size, TYPE_LENGTH (SYMBOL_TYPE (sym)));
                  blk->size, TYPE_LENGTH (SYMBOL_TYPE (sym)));
      SYMBOL_VALUE_BYTES (sym) = (char *)
      SYMBOL_VALUE_BYTES (sym) = (char *)
        obstack_alloc (&objfile->symbol_obstack, blk->size);
        obstack_alloc (&objfile->symbol_obstack, blk->size);
      memcpy (SYMBOL_VALUE_BYTES (sym), blk->data, blk->size);
      memcpy (SYMBOL_VALUE_BYTES (sym), blk->data, blk->size);
      SYMBOL_CLASS (sym) = LOC_CONST_BYTES;
      SYMBOL_CLASS (sym) = LOC_CONST_BYTES;
      break;
      break;
 
 
      /* The DW_AT_const_value attributes are supposed to carry the
      /* The DW_AT_const_value attributes are supposed to carry the
         symbol's value "represented as it would be on the target
         symbol's value "represented as it would be on the target
         architecture."  By the time we get here, it's already been
         architecture."  By the time we get here, it's already been
         converted to host endianness, so we just need to sign- or
         converted to host endianness, so we just need to sign- or
         zero-extend it as appropriate.  */
         zero-extend it as appropriate.  */
    case DW_FORM_data1:
    case DW_FORM_data1:
      dwarf2_const_value_data (attr, sym, 8);
      dwarf2_const_value_data (attr, sym, 8);
      break;
      break;
    case DW_FORM_data2:
    case DW_FORM_data2:
      dwarf2_const_value_data (attr, sym, 16);
      dwarf2_const_value_data (attr, sym, 16);
      break;
      break;
    case DW_FORM_data4:
    case DW_FORM_data4:
      dwarf2_const_value_data (attr, sym, 32);
      dwarf2_const_value_data (attr, sym, 32);
      break;
      break;
    case DW_FORM_data8:
    case DW_FORM_data8:
      dwarf2_const_value_data (attr, sym, 64);
      dwarf2_const_value_data (attr, sym, 64);
      break;
      break;
 
 
    case DW_FORM_sdata:
    case DW_FORM_sdata:
      SYMBOL_VALUE (sym) = DW_SND (attr);
      SYMBOL_VALUE (sym) = DW_SND (attr);
      SYMBOL_CLASS (sym) = LOC_CONST;
      SYMBOL_CLASS (sym) = LOC_CONST;
      break;
      break;
 
 
    case DW_FORM_udata:
    case DW_FORM_udata:
      SYMBOL_VALUE (sym) = DW_UNSND (attr);
      SYMBOL_VALUE (sym) = DW_UNSND (attr);
      SYMBOL_CLASS (sym) = LOC_CONST;
      SYMBOL_CLASS (sym) = LOC_CONST;
      break;
      break;
 
 
    default:
    default:
      complain (&dwarf2_unsupported_const_value_attr,
      complain (&dwarf2_unsupported_const_value_attr,
                dwarf_form_name (attr->form));
                dwarf_form_name (attr->form));
      SYMBOL_VALUE (sym) = 0;
      SYMBOL_VALUE (sym) = 0;
      SYMBOL_CLASS (sym) = LOC_CONST;
      SYMBOL_CLASS (sym) = LOC_CONST;
      break;
      break;
    }
    }
}
}
 
 
 
 
/* Given an attr with a DW_FORM_dataN value in host byte order, sign-
/* Given an attr with a DW_FORM_dataN value in host byte order, sign-
   or zero-extend it as appropriate for the symbol's type.  */
   or zero-extend it as appropriate for the symbol's type.  */
static void
static void
dwarf2_const_value_data (struct attribute *attr,
dwarf2_const_value_data (struct attribute *attr,
                         struct symbol *sym,
                         struct symbol *sym,
                         int bits)
                         int bits)
{
{
  LONGEST l = DW_UNSND (attr);
  LONGEST l = DW_UNSND (attr);
 
 
  if (bits < sizeof (l) * 8)
  if (bits < sizeof (l) * 8)
    {
    {
      if (TYPE_UNSIGNED (SYMBOL_TYPE (sym)))
      if (TYPE_UNSIGNED (SYMBOL_TYPE (sym)))
        l &= ((LONGEST) 1 << bits) - 1;
        l &= ((LONGEST) 1 << bits) - 1;
      else
      else
        l = (l << (sizeof (l) - bits)) >> (sizeof (l) - bits);
        l = (l << (sizeof (l) - bits)) >> (sizeof (l) - bits);
    }
    }
 
 
  SYMBOL_VALUE (sym) = l;
  SYMBOL_VALUE (sym) = l;
  SYMBOL_CLASS (sym) = LOC_CONST;
  SYMBOL_CLASS (sym) = LOC_CONST;
}
}
 
 
 
 
/* Return the type of the die in question using its DW_AT_type attribute.  */
/* Return the type of the die in question using its DW_AT_type attribute.  */
 
 
static struct type *
static struct type *
die_type (die, objfile)
die_type (die, objfile)
     struct die_info *die;
     struct die_info *die;
     struct objfile *objfile;
     struct objfile *objfile;
{
{
  struct type *type;
  struct type *type;
  struct attribute *type_attr;
  struct attribute *type_attr;
  struct die_info *type_die;
  struct die_info *type_die;
  unsigned int ref;
  unsigned int ref;
 
 
  type_attr = dwarf_attr (die, DW_AT_type);
  type_attr = dwarf_attr (die, DW_AT_type);
  if (!type_attr)
  if (!type_attr)
    {
    {
      /* A missing DW_AT_type represents a void type.  */
      /* A missing DW_AT_type represents a void type.  */
      return dwarf2_fundamental_type (objfile, FT_VOID);
      return dwarf2_fundamental_type (objfile, FT_VOID);
    }
    }
  else
  else
    {
    {
      ref = dwarf2_get_ref_die_offset (type_attr);
      ref = dwarf2_get_ref_die_offset (type_attr);
      type_die = follow_die_ref (ref);
      type_die = follow_die_ref (ref);
      if (!type_die)
      if (!type_die)
        {
        {
          error ("Dwarf Error: Cannot find referent at offset %d.", ref);
          error ("Dwarf Error: Cannot find referent at offset %d.", ref);
          return NULL;
          return NULL;
        }
        }
    }
    }
  type = tag_type_to_type (type_die, objfile);
  type = tag_type_to_type (type_die, objfile);
  if (!type)
  if (!type)
    {
    {
      dump_die (type_die);
      dump_die (type_die);
      error ("Dwarf Error: Problem turning type die at offset into gdb type.");
      error ("Dwarf Error: Problem turning type die at offset into gdb type.");
    }
    }
  return type;
  return type;
}
}
 
 
/* Return the containing type of the die in question using its
/* Return the containing type of the die in question using its
   DW_AT_containing_type attribute.  */
   DW_AT_containing_type attribute.  */
 
 
static struct type *
static struct type *
die_containing_type (die, objfile)
die_containing_type (die, objfile)
     struct die_info *die;
     struct die_info *die;
     struct objfile *objfile;
     struct objfile *objfile;
{
{
  struct type *type = NULL;
  struct type *type = NULL;
  struct attribute *type_attr;
  struct attribute *type_attr;
  struct die_info *type_die = NULL;
  struct die_info *type_die = NULL;
  unsigned int ref;
  unsigned int ref;
 
 
  type_attr = dwarf_attr (die, DW_AT_containing_type);
  type_attr = dwarf_attr (die, DW_AT_containing_type);
  if (type_attr)
  if (type_attr)
    {
    {
      ref = dwarf2_get_ref_die_offset (type_attr);
      ref = dwarf2_get_ref_die_offset (type_attr);
      type_die = follow_die_ref (ref);
      type_die = follow_die_ref (ref);
      if (!type_die)
      if (!type_die)
        {
        {
          error ("Dwarf Error: Cannot find referent at offset %d.", ref);
          error ("Dwarf Error: Cannot find referent at offset %d.", ref);
          return NULL;
          return NULL;
        }
        }
      type = tag_type_to_type (type_die, objfile);
      type = tag_type_to_type (type_die, objfile);
    }
    }
  if (!type)
  if (!type)
    {
    {
      if (type_die)
      if (type_die)
        dump_die (type_die);
        dump_die (type_die);
      error ("Dwarf Error: Problem turning containing type into gdb type.");
      error ("Dwarf Error: Problem turning containing type into gdb type.");
    }
    }
  return type;
  return type;
}
}
 
 
#if 0
#if 0
static struct type *
static struct type *
type_at_offset (offset, objfile)
type_at_offset (offset, objfile)
     unsigned int offset;
     unsigned int offset;
     struct objfile *objfile;
     struct objfile *objfile;
{
{
  struct die_info *die;
  struct die_info *die;
  struct type *type;
  struct type *type;
 
 
  die = follow_die_ref (offset);
  die = follow_die_ref (offset);
  if (!die)
  if (!die)
    {
    {
      error ("Dwarf Error: Cannot find type referent at offset %d.", offset);
      error ("Dwarf Error: Cannot find type referent at offset %d.", offset);
      return NULL;
      return NULL;
    }
    }
  type = tag_type_to_type (die, objfile);
  type = tag_type_to_type (die, objfile);
  return type;
  return type;
}
}
#endif
#endif
 
 
static struct type *
static struct type *
tag_type_to_type (die, objfile)
tag_type_to_type (die, objfile)
     struct die_info *die;
     struct die_info *die;
     struct objfile *objfile;
     struct objfile *objfile;
{
{
  if (die->type)
  if (die->type)
    {
    {
      return die->type;
      return die->type;
    }
    }
  else
  else
    {
    {
      read_type_die (die, objfile);
      read_type_die (die, objfile);
      if (!die->type)
      if (!die->type)
        {
        {
          dump_die (die);
          dump_die (die);
          error ("Dwarf Error: Cannot find type of die.");
          error ("Dwarf Error: Cannot find type of die.");
        }
        }
      return die->type;
      return die->type;
    }
    }
}
}
 
 
static void
static void
read_type_die (die, objfile)
read_type_die (die, objfile)
     struct die_info *die;
     struct die_info *die;
     struct objfile *objfile;
     struct objfile *objfile;
{
{
  switch (die->tag)
  switch (die->tag)
    {
    {
    case DW_TAG_class_type:
    case DW_TAG_class_type:
    case DW_TAG_structure_type:
    case DW_TAG_structure_type:
    case DW_TAG_union_type:
    case DW_TAG_union_type:
      read_structure_scope (die, objfile);
      read_structure_scope (die, objfile);
      break;
      break;
    case DW_TAG_enumeration_type:
    case DW_TAG_enumeration_type:
      read_enumeration (die, objfile);
      read_enumeration (die, objfile);
      break;
      break;
    case DW_TAG_subprogram:
    case DW_TAG_subprogram:
    case DW_TAG_subroutine_type:
    case DW_TAG_subroutine_type:
      read_subroutine_type (die, objfile);
      read_subroutine_type (die, objfile);
      break;
      break;
    case DW_TAG_array_type:
    case DW_TAG_array_type:
      read_array_type (die, objfile);
      read_array_type (die, objfile);
      break;
      break;
    case DW_TAG_pointer_type:
    case DW_TAG_pointer_type:
      read_tag_pointer_type (die, objfile);
      read_tag_pointer_type (die, objfile);
      break;
      break;
    case DW_TAG_ptr_to_member_type:
    case DW_TAG_ptr_to_member_type:
      read_tag_ptr_to_member_type (die, objfile);
      read_tag_ptr_to_member_type (die, objfile);
      break;
      break;
    case DW_TAG_reference_type:
    case DW_TAG_reference_type:
      read_tag_reference_type (die, objfile);
      read_tag_reference_type (die, objfile);
      break;
      break;
    case DW_TAG_const_type:
    case DW_TAG_const_type:
      read_tag_const_type (die, objfile);
      read_tag_const_type (die, objfile);
      break;
      break;
    case DW_TAG_volatile_type:
    case DW_TAG_volatile_type:
      read_tag_volatile_type (die, objfile);
      read_tag_volatile_type (die, objfile);
      break;
      break;
    case DW_TAG_string_type:
    case DW_TAG_string_type:
      read_tag_string_type (die, objfile);
      read_tag_string_type (die, objfile);
      break;
      break;
    case DW_TAG_typedef:
    case DW_TAG_typedef:
      read_typedef (die, objfile);
      read_typedef (die, objfile);
      break;
      break;
    case DW_TAG_base_type:
    case DW_TAG_base_type:
      read_base_type (die, objfile);
      read_base_type (die, objfile);
      break;
      break;
    default:
    default:
      complain (&dwarf2_unexpected_tag, dwarf_tag_name (die->tag));
      complain (&dwarf2_unexpected_tag, dwarf_tag_name (die->tag));
      break;
      break;
    }
    }
}
}
 
 
static struct type *
static struct type *
dwarf_base_type (encoding, size, objfile)
dwarf_base_type (encoding, size, objfile)
     int encoding;
     int encoding;
     int size;
     int size;
     struct objfile *objfile;
     struct objfile *objfile;
{
{
  /* FIXME - this should not produce a new (struct type *)
  /* FIXME - this should not produce a new (struct type *)
     every time.  It should cache base types.  */
     every time.  It should cache base types.  */
  struct type *type;
  struct type *type;
  switch (encoding)
  switch (encoding)
    {
    {
    case DW_ATE_address:
    case DW_ATE_address:
      type = dwarf2_fundamental_type (objfile, FT_VOID);
      type = dwarf2_fundamental_type (objfile, FT_VOID);
      return type;
      return type;
    case DW_ATE_boolean:
    case DW_ATE_boolean:
      type = dwarf2_fundamental_type (objfile, FT_BOOLEAN);
      type = dwarf2_fundamental_type (objfile, FT_BOOLEAN);
      return type;
      return type;
    case DW_ATE_complex_float:
    case DW_ATE_complex_float:
      if (size == 16)
      if (size == 16)
        {
        {
          type = dwarf2_fundamental_type (objfile, FT_DBL_PREC_COMPLEX);
          type = dwarf2_fundamental_type (objfile, FT_DBL_PREC_COMPLEX);
        }
        }
      else
      else
        {
        {
          type = dwarf2_fundamental_type (objfile, FT_COMPLEX);
          type = dwarf2_fundamental_type (objfile, FT_COMPLEX);
        }
        }
      return type;
      return type;
    case DW_ATE_float:
    case DW_ATE_float:
      if (size == 8)
      if (size == 8)
        {
        {
          type = dwarf2_fundamental_type (objfile, FT_DBL_PREC_FLOAT);
          type = dwarf2_fundamental_type (objfile, FT_DBL_PREC_FLOAT);
        }
        }
      else
      else
        {
        {
          type = dwarf2_fundamental_type (objfile, FT_FLOAT);
          type = dwarf2_fundamental_type (objfile, FT_FLOAT);
        }
        }
      return type;
      return type;
    case DW_ATE_signed:
    case DW_ATE_signed:
      switch (size)
      switch (size)
        {
        {
        case 1:
        case 1:
          type = dwarf2_fundamental_type (objfile, FT_SIGNED_CHAR);
          type = dwarf2_fundamental_type (objfile, FT_SIGNED_CHAR);
          break;
          break;
        case 2:
        case 2:
          type = dwarf2_fundamental_type (objfile, FT_SIGNED_SHORT);
          type = dwarf2_fundamental_type (objfile, FT_SIGNED_SHORT);
          break;
          break;
        default:
        default:
        case 4:
        case 4:
          type = dwarf2_fundamental_type (objfile, FT_SIGNED_INTEGER);
          type = dwarf2_fundamental_type (objfile, FT_SIGNED_INTEGER);
          break;
          break;
        }
        }
      return type;
      return type;
    case DW_ATE_signed_char:
    case DW_ATE_signed_char:
      type = dwarf2_fundamental_type (objfile, FT_SIGNED_CHAR);
      type = dwarf2_fundamental_type (objfile, FT_SIGNED_CHAR);
      return type;
      return type;
    case DW_ATE_unsigned:
    case DW_ATE_unsigned:
      switch (size)
      switch (size)
        {
        {
        case 1:
        case 1:
          type = dwarf2_fundamental_type (objfile, FT_UNSIGNED_CHAR);
          type = dwarf2_fundamental_type (objfile, FT_UNSIGNED_CHAR);
          break;
          break;
        case 2:
        case 2:
          type = dwarf2_fundamental_type (objfile, FT_UNSIGNED_SHORT);
          type = dwarf2_fundamental_type (objfile, FT_UNSIGNED_SHORT);
          break;
          break;
        default:
        default:
        case 4:
        case 4:
          type = dwarf2_fundamental_type (objfile, FT_UNSIGNED_INTEGER);
          type = dwarf2_fundamental_type (objfile, FT_UNSIGNED_INTEGER);
          break;
          break;
        }
        }
      return type;
      return type;
    case DW_ATE_unsigned_char:
    case DW_ATE_unsigned_char:
      type = dwarf2_fundamental_type (objfile, FT_UNSIGNED_CHAR);
      type = dwarf2_fundamental_type (objfile, FT_UNSIGNED_CHAR);
      return type;
      return type;
    default:
    default:
      type = dwarf2_fundamental_type (objfile, FT_SIGNED_INTEGER);
      type = dwarf2_fundamental_type (objfile, FT_SIGNED_INTEGER);
      return type;
      return type;
    }
    }
}
}
 
 
#if 0
#if 0
struct die_info *
struct die_info *
copy_die (old_die)
copy_die (old_die)
     struct die_info *old_die;
     struct die_info *old_die;
{
{
  struct die_info *new_die;
  struct die_info *new_die;
  int i, num_attrs;
  int i, num_attrs;
 
 
  new_die = (struct die_info *) xmalloc (sizeof (struct die_info));
  new_die = (struct die_info *) xmalloc (sizeof (struct die_info));
  memset (new_die, 0, sizeof (struct die_info));
  memset (new_die, 0, sizeof (struct die_info));
 
 
  new_die->tag = old_die->tag;
  new_die->tag = old_die->tag;
  new_die->has_children = old_die->has_children;
  new_die->has_children = old_die->has_children;
  new_die->abbrev = old_die->abbrev;
  new_die->abbrev = old_die->abbrev;
  new_die->offset = old_die->offset;
  new_die->offset = old_die->offset;
  new_die->type = NULL;
  new_die->type = NULL;
 
 
  num_attrs = old_die->num_attrs;
  num_attrs = old_die->num_attrs;
  new_die->num_attrs = num_attrs;
  new_die->num_attrs = num_attrs;
  new_die->attrs = (struct attribute *)
  new_die->attrs = (struct attribute *)
    xmalloc (num_attrs * sizeof (struct attribute));
    xmalloc (num_attrs * sizeof (struct attribute));
 
 
  for (i = 0; i < old_die->num_attrs; ++i)
  for (i = 0; i < old_die->num_attrs; ++i)
    {
    {
      new_die->attrs[i].name = old_die->attrs[i].name;
      new_die->attrs[i].name = old_die->attrs[i].name;
      new_die->attrs[i].form = old_die->attrs[i].form;
      new_die->attrs[i].form = old_die->attrs[i].form;
      new_die->attrs[i].u.addr = old_die->attrs[i].u.addr;
      new_die->attrs[i].u.addr = old_die->attrs[i].u.addr;
    }
    }
 
 
  new_die->next = NULL;
  new_die->next = NULL;
  return new_die;
  return new_die;
}
}
#endif
#endif
 
 
/* Return sibling of die, NULL if no sibling.  */
/* Return sibling of die, NULL if no sibling.  */
 
 
struct die_info *
struct die_info *
sibling_die (die)
sibling_die (die)
     struct die_info *die;
     struct die_info *die;
{
{
  int nesting_level = 0;
  int nesting_level = 0;
 
 
  if (!die->has_children)
  if (!die->has_children)
    {
    {
      if (die->next && (die->next->tag == 0))
      if (die->next && (die->next->tag == 0))
        {
        {
          return NULL;
          return NULL;
        }
        }
      else
      else
        {
        {
          return die->next;
          return die->next;
        }
        }
    }
    }
  else
  else
    {
    {
      do
      do
        {
        {
          if (die->has_children)
          if (die->has_children)
            {
            {
              nesting_level++;
              nesting_level++;
            }
            }
          if (die->tag == 0)
          if (die->tag == 0)
            {
            {
              nesting_level--;
              nesting_level--;
            }
            }
          die = die->next;
          die = die->next;
        }
        }
      while (nesting_level);
      while (nesting_level);
      if (die && (die->tag == 0))
      if (die && (die->tag == 0))
        {
        {
          return NULL;
          return NULL;
        }
        }
      else
      else
        {
        {
          return die;
          return die;
        }
        }
    }
    }
}
}
 
 
/* Get linkage name of a die, return NULL if not found.  */
/* Get linkage name of a die, return NULL if not found.  */
 
 
static char *
static char *
dwarf2_linkage_name (die)
dwarf2_linkage_name (die)
     struct die_info *die;
     struct die_info *die;
{
{
  struct attribute *attr;
  struct attribute *attr;
 
 
  attr = dwarf_attr (die, DW_AT_MIPS_linkage_name);
  attr = dwarf_attr (die, DW_AT_MIPS_linkage_name);
  if (attr && DW_STRING (attr))
  if (attr && DW_STRING (attr))
    return DW_STRING (attr);
    return DW_STRING (attr);
  attr = dwarf_attr (die, DW_AT_name);
  attr = dwarf_attr (die, DW_AT_name);
  if (attr && DW_STRING (attr))
  if (attr && DW_STRING (attr))
    return DW_STRING (attr);
    return DW_STRING (attr);
  return NULL;
  return NULL;
}
}
 
 
/* Convert a DIE tag into its string name.  */
/* Convert a DIE tag into its string name.  */
 
 
static char *
static char *
dwarf_tag_name (tag)
dwarf_tag_name (tag)
     register unsigned tag;
     register unsigned tag;
{
{
  switch (tag)
  switch (tag)
    {
    {
    case DW_TAG_padding:
    case DW_TAG_padding:
      return "DW_TAG_padding";
      return "DW_TAG_padding";
    case DW_TAG_array_type:
    case DW_TAG_array_type:
      return "DW_TAG_array_type";
      return "DW_TAG_array_type";
    case DW_TAG_class_type:
    case DW_TAG_class_type:
      return "DW_TAG_class_type";
      return "DW_TAG_class_type";
    case DW_TAG_entry_point:
    case DW_TAG_entry_point:
      return "DW_TAG_entry_point";
      return "DW_TAG_entry_point";
    case DW_TAG_enumeration_type:
    case DW_TAG_enumeration_type:
      return "DW_TAG_enumeration_type";
      return "DW_TAG_enumeration_type";
    case DW_TAG_formal_parameter:
    case DW_TAG_formal_parameter:
      return "DW_TAG_formal_parameter";
      return "DW_TAG_formal_parameter";
    case DW_TAG_imported_declaration:
    case DW_TAG_imported_declaration:
      return "DW_TAG_imported_declaration";
      return "DW_TAG_imported_declaration";
    case DW_TAG_label:
    case DW_TAG_label:
      return "DW_TAG_label";
      return "DW_TAG_label";
    case DW_TAG_lexical_block:
    case DW_TAG_lexical_block:
      return "DW_TAG_lexical_block";
      return "DW_TAG_lexical_block";
    case DW_TAG_member:
    case DW_TAG_member:
      return "DW_TAG_member";
      return "DW_TAG_member";
    case DW_TAG_pointer_type:
    case DW_TAG_pointer_type:
      return "DW_TAG_pointer_type";
      return "DW_TAG_pointer_type";
    case DW_TAG_reference_type:
    case DW_TAG_reference_type:
      return "DW_TAG_reference_type";
      return "DW_TAG_reference_type";
    case DW_TAG_compile_unit:
    case DW_TAG_compile_unit:
      return "DW_TAG_compile_unit";
      return "DW_TAG_compile_unit";
    case DW_TAG_string_type:
    case DW_TAG_string_type:
      return "DW_TAG_string_type";
      return "DW_TAG_string_type";
    case DW_TAG_structure_type:
    case DW_TAG_structure_type:
      return "DW_TAG_structure_type";
      return "DW_TAG_structure_type";
    case DW_TAG_subroutine_type:
    case DW_TAG_subroutine_type:
      return "DW_TAG_subroutine_type";
      return "DW_TAG_subroutine_type";
    case DW_TAG_typedef:
    case DW_TAG_typedef:
      return "DW_TAG_typedef";
      return "DW_TAG_typedef";
    case DW_TAG_union_type:
    case DW_TAG_union_type:
      return "DW_TAG_union_type";
      return "DW_TAG_union_type";
    case DW_TAG_unspecified_parameters:
    case DW_TAG_unspecified_parameters:
      return "DW_TAG_unspecified_parameters";
      return "DW_TAG_unspecified_parameters";
    case DW_TAG_variant:
    case DW_TAG_variant:
      return "DW_TAG_variant";
      return "DW_TAG_variant";
    case DW_TAG_common_block:
    case DW_TAG_common_block:
      return "DW_TAG_common_block";
      return "DW_TAG_common_block";
    case DW_TAG_common_inclusion:
    case DW_TAG_common_inclusion:
      return "DW_TAG_common_inclusion";
      return "DW_TAG_common_inclusion";
    case DW_TAG_inheritance:
    case DW_TAG_inheritance:
      return "DW_TAG_inheritance";
      return "DW_TAG_inheritance";
    case DW_TAG_inlined_subroutine:
    case DW_TAG_inlined_subroutine:
      return "DW_TAG_inlined_subroutine";
      return "DW_TAG_inlined_subroutine";
    case DW_TAG_module:
    case DW_TAG_module:
      return "DW_TAG_module";
      return "DW_TAG_module";
    case DW_TAG_ptr_to_member_type:
    case DW_TAG_ptr_to_member_type:
      return "DW_TAG_ptr_to_member_type";
      return "DW_TAG_ptr_to_member_type";
    case DW_TAG_set_type:
    case DW_TAG_set_type:
      return "DW_TAG_set_type";
      return "DW_TAG_set_type";
    case DW_TAG_subrange_type:
    case DW_TAG_subrange_type:
      return "DW_TAG_subrange_type";
      return "DW_TAG_subrange_type";
    case DW_TAG_with_stmt:
    case DW_TAG_with_stmt:
      return "DW_TAG_with_stmt";
      return "DW_TAG_with_stmt";
    case DW_TAG_access_declaration:
    case DW_TAG_access_declaration:
      return "DW_TAG_access_declaration";
      return "DW_TAG_access_declaration";
    case DW_TAG_base_type:
    case DW_TAG_base_type:
      return "DW_TAG_base_type";
      return "DW_TAG_base_type";
    case DW_TAG_catch_block:
    case DW_TAG_catch_block:
      return "DW_TAG_catch_block";
      return "DW_TAG_catch_block";
    case DW_TAG_const_type:
    case DW_TAG_const_type:
      return "DW_TAG_const_type";
      return "DW_TAG_const_type";
    case DW_TAG_constant:
    case DW_TAG_constant:
      return "DW_TAG_constant";
      return "DW_TAG_constant";
    case DW_TAG_enumerator:
    case DW_TAG_enumerator:
      return "DW_TAG_enumerator";
      return "DW_TAG_enumerator";
    case DW_TAG_file_type:
    case DW_TAG_file_type:
      return "DW_TAG_file_type";
      return "DW_TAG_file_type";
    case DW_TAG_friend:
    case DW_TAG_friend:
      return "DW_TAG_friend";
      return "DW_TAG_friend";
    case DW_TAG_namelist:
    case DW_TAG_namelist:
      return "DW_TAG_namelist";
      return "DW_TAG_namelist";
    case DW_TAG_namelist_item:
    case DW_TAG_namelist_item:
      return "DW_TAG_namelist_item";
      return "DW_TAG_namelist_item";
    case DW_TAG_packed_type:
    case DW_TAG_packed_type:
      return "DW_TAG_packed_type";
      return "DW_TAG_packed_type";
    case DW_TAG_subprogram:
    case DW_TAG_subprogram:
      return "DW_TAG_subprogram";
      return "DW_TAG_subprogram";
    case DW_TAG_template_type_param:
    case DW_TAG_template_type_param:
      return "DW_TAG_template_type_param";
      return "DW_TAG_template_type_param";
    case DW_TAG_template_value_param:
    case DW_TAG_template_value_param:
      return "DW_TAG_template_value_param";
      return "DW_TAG_template_value_param";
    case DW_TAG_thrown_type:
    case DW_TAG_thrown_type:
      return "DW_TAG_thrown_type";
      return "DW_TAG_thrown_type";
    case DW_TAG_try_block:
    case DW_TAG_try_block:
      return "DW_TAG_try_block";
      return "DW_TAG_try_block";
    case DW_TAG_variant_part:
    case DW_TAG_variant_part:
      return "DW_TAG_variant_part";
      return "DW_TAG_variant_part";
    case DW_TAG_variable:
    case DW_TAG_variable:
      return "DW_TAG_variable";
      return "DW_TAG_variable";
    case DW_TAG_volatile_type:
    case DW_TAG_volatile_type:
      return "DW_TAG_volatile_type";
      return "DW_TAG_volatile_type";
    case DW_TAG_MIPS_loop:
    case DW_TAG_MIPS_loop:
      return "DW_TAG_MIPS_loop";
      return "DW_TAG_MIPS_loop";
    case DW_TAG_format_label:
    case DW_TAG_format_label:
      return "DW_TAG_format_label";
      return "DW_TAG_format_label";
    case DW_TAG_function_template:
    case DW_TAG_function_template:
      return "DW_TAG_function_template";
      return "DW_TAG_function_template";
    case DW_TAG_class_template:
    case DW_TAG_class_template:
      return "DW_TAG_class_template";
      return "DW_TAG_class_template";
    default:
    default:
      return "DW_TAG_<unknown>";
      return "DW_TAG_<unknown>";
    }
    }
}
}
 
 
/* Convert a DWARF attribute code into its string name.  */
/* Convert a DWARF attribute code into its string name.  */
 
 
static char *
static char *
dwarf_attr_name (attr)
dwarf_attr_name (attr)
     register unsigned attr;
     register unsigned attr;
{
{
  switch (attr)
  switch (attr)
    {
    {
    case DW_AT_sibling:
    case DW_AT_sibling:
      return "DW_AT_sibling";
      return "DW_AT_sibling";
    case DW_AT_location:
    case DW_AT_location:
      return "DW_AT_location";
      return "DW_AT_location";
    case DW_AT_name:
    case DW_AT_name:
      return "DW_AT_name";
      return "DW_AT_name";
    case DW_AT_ordering:
    case DW_AT_ordering:
      return "DW_AT_ordering";
      return "DW_AT_ordering";
    case DW_AT_subscr_data:
    case DW_AT_subscr_data:
      return "DW_AT_subscr_data";
      return "DW_AT_subscr_data";
    case DW_AT_byte_size:
    case DW_AT_byte_size:
      return "DW_AT_byte_size";
      return "DW_AT_byte_size";
    case DW_AT_bit_offset:
    case DW_AT_bit_offset:
      return "DW_AT_bit_offset";
      return "DW_AT_bit_offset";
    case DW_AT_bit_size:
    case DW_AT_bit_size:
      return "DW_AT_bit_size";
      return "DW_AT_bit_size";
    case DW_AT_element_list:
    case DW_AT_element_list:
      return "DW_AT_element_list";
      return "DW_AT_element_list";
    case DW_AT_stmt_list:
    case DW_AT_stmt_list:
      return "DW_AT_stmt_list";
      return "DW_AT_stmt_list";
    case DW_AT_low_pc:
    case DW_AT_low_pc:
      return "DW_AT_low_pc";
      return "DW_AT_low_pc";
    case DW_AT_high_pc:
    case DW_AT_high_pc:
      return "DW_AT_high_pc";
      return "DW_AT_high_pc";
    case DW_AT_language:
    case DW_AT_language:
      return "DW_AT_language";
      return "DW_AT_language";
    case DW_AT_member:
    case DW_AT_member:
      return "DW_AT_member";
      return "DW_AT_member";
    case DW_AT_discr:
    case DW_AT_discr:
      return "DW_AT_discr";
      return "DW_AT_discr";
    case DW_AT_discr_value:
    case DW_AT_discr_value:
      return "DW_AT_discr_value";
      return "DW_AT_discr_value";
    case DW_AT_visibility:
    case DW_AT_visibility:
      return "DW_AT_visibility";
      return "DW_AT_visibility";
    case DW_AT_import:
    case DW_AT_import:
      return "DW_AT_import";
      return "DW_AT_import";
    case DW_AT_string_length:
    case DW_AT_string_length:
      return "DW_AT_string_length";
      return "DW_AT_string_length";
    case DW_AT_common_reference:
    case DW_AT_common_reference:
      return "DW_AT_common_reference";
      return "DW_AT_common_reference";
    case DW_AT_comp_dir:
    case DW_AT_comp_dir:
      return "DW_AT_comp_dir";
      return "DW_AT_comp_dir";
    case DW_AT_const_value:
    case DW_AT_const_value:
      return "DW_AT_const_value";
      return "DW_AT_const_value";
    case DW_AT_containing_type:
    case DW_AT_containing_type:
      return "DW_AT_containing_type";
      return "DW_AT_containing_type";
    case DW_AT_default_value:
    case DW_AT_default_value:
      return "DW_AT_default_value";
      return "DW_AT_default_value";
    case DW_AT_inline:
    case DW_AT_inline:
      return "DW_AT_inline";
      return "DW_AT_inline";
    case DW_AT_is_optional:
    case DW_AT_is_optional:
      return "DW_AT_is_optional";
      return "DW_AT_is_optional";
    case DW_AT_lower_bound:
    case DW_AT_lower_bound:
      return "DW_AT_lower_bound";
      return "DW_AT_lower_bound";
    case DW_AT_producer:
    case DW_AT_producer:
      return "DW_AT_producer";
      return "DW_AT_producer";
    case DW_AT_prototyped:
    case DW_AT_prototyped:
      return "DW_AT_prototyped";
      return "DW_AT_prototyped";
    case DW_AT_return_addr:
    case DW_AT_return_addr:
      return "DW_AT_return_addr";
      return "DW_AT_return_addr";
    case DW_AT_start_scope:
    case DW_AT_start_scope:
      return "DW_AT_start_scope";
      return "DW_AT_start_scope";
    case DW_AT_stride_size:
    case DW_AT_stride_size:
      return "DW_AT_stride_size";
      return "DW_AT_stride_size";
    case DW_AT_upper_bound:
    case DW_AT_upper_bound:
      return "DW_AT_upper_bound";
      return "DW_AT_upper_bound";
    case DW_AT_abstract_origin:
    case DW_AT_abstract_origin:
      return "DW_AT_abstract_origin";
      return "DW_AT_abstract_origin";
    case DW_AT_accessibility:
    case DW_AT_accessibility:
      return "DW_AT_accessibility";
      return "DW_AT_accessibility";
    case DW_AT_address_class:
    case DW_AT_address_class:
      return "DW_AT_address_class";
      return "DW_AT_address_class";
    case DW_AT_artificial:
    case DW_AT_artificial:
      return "DW_AT_artificial";
      return "DW_AT_artificial";
    case DW_AT_base_types:
    case DW_AT_base_types:
      return "DW_AT_base_types";
      return "DW_AT_base_types";
    case DW_AT_calling_convention:
    case DW_AT_calling_convention:
      return "DW_AT_calling_convention";
      return "DW_AT_calling_convention";
    case DW_AT_count:
    case DW_AT_count:
      return "DW_AT_count";
      return "DW_AT_count";
    case DW_AT_data_member_location:
    case DW_AT_data_member_location:
      return "DW_AT_data_member_location";
      return "DW_AT_data_member_location";
    case DW_AT_decl_column:
    case DW_AT_decl_column:
      return "DW_AT_decl_column";
      return "DW_AT_decl_column";
    case DW_AT_decl_file:
    case DW_AT_decl_file:
      return "DW_AT_decl_file";
      return "DW_AT_decl_file";
    case DW_AT_decl_line:
    case DW_AT_decl_line:
      return "DW_AT_decl_line";
      return "DW_AT_decl_line";
    case DW_AT_declaration:
    case DW_AT_declaration:
      return "DW_AT_declaration";
      return "DW_AT_declaration";
    case DW_AT_discr_list:
    case DW_AT_discr_list:
      return "DW_AT_discr_list";
      return "DW_AT_discr_list";
    case DW_AT_encoding:
    case DW_AT_encoding:
      return "DW_AT_encoding";
      return "DW_AT_encoding";
    case DW_AT_external:
    case DW_AT_external:
      return "DW_AT_external";
      return "DW_AT_external";
    case DW_AT_frame_base:
    case DW_AT_frame_base:
      return "DW_AT_frame_base";
      return "DW_AT_frame_base";
    case DW_AT_friend:
    case DW_AT_friend:
      return "DW_AT_friend";
      return "DW_AT_friend";
    case DW_AT_identifier_case:
    case DW_AT_identifier_case:
      return "DW_AT_identifier_case";
      return "DW_AT_identifier_case";
    case DW_AT_macro_info:
    case DW_AT_macro_info:
      return "DW_AT_macro_info";
      return "DW_AT_macro_info";
    case DW_AT_namelist_items:
    case DW_AT_namelist_items:
      return "DW_AT_namelist_items";
      return "DW_AT_namelist_items";
    case DW_AT_priority:
    case DW_AT_priority:
      return "DW_AT_priority";
      return "DW_AT_priority";
    case DW_AT_segment:
    case DW_AT_segment:
      return "DW_AT_segment";
      return "DW_AT_segment";
    case DW_AT_specification:
    case DW_AT_specification:
      return "DW_AT_specification";
      return "DW_AT_specification";
    case DW_AT_static_link:
    case DW_AT_static_link:
      return "DW_AT_static_link";
      return "DW_AT_static_link";
    case DW_AT_type:
    case DW_AT_type:
      return "DW_AT_type";
      return "DW_AT_type";
    case DW_AT_use_location:
    case DW_AT_use_location:
      return "DW_AT_use_location";
      return "DW_AT_use_location";
    case DW_AT_variable_parameter:
    case DW_AT_variable_parameter:
      return "DW_AT_variable_parameter";
      return "DW_AT_variable_parameter";
    case DW_AT_virtuality:
    case DW_AT_virtuality:
      return "DW_AT_virtuality";
      return "DW_AT_virtuality";
    case DW_AT_vtable_elem_location:
    case DW_AT_vtable_elem_location:
      return "DW_AT_vtable_elem_location";
      return "DW_AT_vtable_elem_location";
 
 
#ifdef MIPS
#ifdef MIPS
    case DW_AT_MIPS_fde:
    case DW_AT_MIPS_fde:
      return "DW_AT_MIPS_fde";
      return "DW_AT_MIPS_fde";
    case DW_AT_MIPS_loop_begin:
    case DW_AT_MIPS_loop_begin:
      return "DW_AT_MIPS_loop_begin";
      return "DW_AT_MIPS_loop_begin";
    case DW_AT_MIPS_tail_loop_begin:
    case DW_AT_MIPS_tail_loop_begin:
      return "DW_AT_MIPS_tail_loop_begin";
      return "DW_AT_MIPS_tail_loop_begin";
    case DW_AT_MIPS_epilog_begin:
    case DW_AT_MIPS_epilog_begin:
      return "DW_AT_MIPS_epilog_begin";
      return "DW_AT_MIPS_epilog_begin";
    case DW_AT_MIPS_loop_unroll_factor:
    case DW_AT_MIPS_loop_unroll_factor:
      return "DW_AT_MIPS_loop_unroll_factor";
      return "DW_AT_MIPS_loop_unroll_factor";
    case DW_AT_MIPS_software_pipeline_depth:
    case DW_AT_MIPS_software_pipeline_depth:
      return "DW_AT_MIPS_software_pipeline_depth";
      return "DW_AT_MIPS_software_pipeline_depth";
    case DW_AT_MIPS_linkage_name:
    case DW_AT_MIPS_linkage_name:
      return "DW_AT_MIPS_linkage_name";
      return "DW_AT_MIPS_linkage_name";
#endif
#endif
 
 
    case DW_AT_sf_names:
    case DW_AT_sf_names:
      return "DW_AT_sf_names";
      return "DW_AT_sf_names";
    case DW_AT_src_info:
    case DW_AT_src_info:
      return "DW_AT_src_info";
      return "DW_AT_src_info";
    case DW_AT_mac_info:
    case DW_AT_mac_info:
      return "DW_AT_mac_info";
      return "DW_AT_mac_info";
    case DW_AT_src_coords:
    case DW_AT_src_coords:
      return "DW_AT_src_coords";
      return "DW_AT_src_coords";
    case DW_AT_body_begin:
    case DW_AT_body_begin:
      return "DW_AT_body_begin";
      return "DW_AT_body_begin";
    case DW_AT_body_end:
    case DW_AT_body_end:
      return "DW_AT_body_end";
      return "DW_AT_body_end";
    default:
    default:
      return "DW_AT_<unknown>";
      return "DW_AT_<unknown>";
    }
    }
}
}
 
 
/* Convert a DWARF value form code into its string name.  */
/* Convert a DWARF value form code into its string name.  */
 
 
static char *
static char *
dwarf_form_name (form)
dwarf_form_name (form)
     register unsigned form;
     register unsigned form;
{
{
  switch (form)
  switch (form)
    {
    {
    case DW_FORM_addr:
    case DW_FORM_addr:
      return "DW_FORM_addr";
      return "DW_FORM_addr";
    case DW_FORM_block2:
    case DW_FORM_block2:
      return "DW_FORM_block2";
      return "DW_FORM_block2";
    case DW_FORM_block4:
    case DW_FORM_block4:
      return "DW_FORM_block4";
      return "DW_FORM_block4";
    case DW_FORM_data2:
    case DW_FORM_data2:
      return "DW_FORM_data2";
      return "DW_FORM_data2";
    case DW_FORM_data4:
    case DW_FORM_data4:
      return "DW_FORM_data4";
      return "DW_FORM_data4";
    case DW_FORM_data8:
    case DW_FORM_data8:
      return "DW_FORM_data8";
      return "DW_FORM_data8";
    case DW_FORM_string:
    case DW_FORM_string:
      return "DW_FORM_string";
      return "DW_FORM_string";
    case DW_FORM_block:
    case DW_FORM_block:
      return "DW_FORM_block";
      return "DW_FORM_block";
    case DW_FORM_block1:
    case DW_FORM_block1:
      return "DW_FORM_block1";
      return "DW_FORM_block1";
    case DW_FORM_data1:
    case DW_FORM_data1:
      return "DW_FORM_data1";
      return "DW_FORM_data1";
    case DW_FORM_flag:
    case DW_FORM_flag:
      return "DW_FORM_flag";
      return "DW_FORM_flag";
    case DW_FORM_sdata:
    case DW_FORM_sdata:
      return "DW_FORM_sdata";
      return "DW_FORM_sdata";
    case DW_FORM_strp:
    case DW_FORM_strp:
      return "DW_FORM_strp";
      return "DW_FORM_strp";
    case DW_FORM_udata:
    case DW_FORM_udata:
      return "DW_FORM_udata";
      return "DW_FORM_udata";
    case DW_FORM_ref_addr:
    case DW_FORM_ref_addr:
      return "DW_FORM_ref_addr";
      return "DW_FORM_ref_addr";
    case DW_FORM_ref1:
    case DW_FORM_ref1:
      return "DW_FORM_ref1";
      return "DW_FORM_ref1";
    case DW_FORM_ref2:
    case DW_FORM_ref2:
      return "DW_FORM_ref2";
      return "DW_FORM_ref2";
    case DW_FORM_ref4:
    case DW_FORM_ref4:
      return "DW_FORM_ref4";
      return "DW_FORM_ref4";
    case DW_FORM_ref8:
    case DW_FORM_ref8:
      return "DW_FORM_ref8";
      return "DW_FORM_ref8";
    case DW_FORM_ref_udata:
    case DW_FORM_ref_udata:
      return "DW_FORM_ref_udata";
      return "DW_FORM_ref_udata";
    case DW_FORM_indirect:
    case DW_FORM_indirect:
      return "DW_FORM_indirect";
      return "DW_FORM_indirect";
    default:
    default:
      return "DW_FORM_<unknown>";
      return "DW_FORM_<unknown>";
    }
    }
}
}
 
 
/* Convert a DWARF stack opcode into its string name.  */
/* Convert a DWARF stack opcode into its string name.  */
 
 
static char *
static char *
dwarf_stack_op_name (op)
dwarf_stack_op_name (op)
     register unsigned op;
     register unsigned op;
{
{
  switch (op)
  switch (op)
    {
    {
    case DW_OP_addr:
    case DW_OP_addr:
      return "DW_OP_addr";
      return "DW_OP_addr";
    case DW_OP_deref:
    case DW_OP_deref:
      return "DW_OP_deref";
      return "DW_OP_deref";
    case DW_OP_const1u:
    case DW_OP_const1u:
      return "DW_OP_const1u";
      return "DW_OP_const1u";
    case DW_OP_const1s:
    case DW_OP_const1s:
      return "DW_OP_const1s";
      return "DW_OP_const1s";
    case DW_OP_const2u:
    case DW_OP_const2u:
      return "DW_OP_const2u";
      return "DW_OP_const2u";
    case DW_OP_const2s:
    case DW_OP_const2s:
      return "DW_OP_const2s";
      return "DW_OP_const2s";
    case DW_OP_const4u:
    case DW_OP_const4u:
      return "DW_OP_const4u";
      return "DW_OP_const4u";
    case DW_OP_const4s:
    case DW_OP_const4s:
      return "DW_OP_const4s";
      return "DW_OP_const4s";
    case DW_OP_const8u:
    case DW_OP_const8u:
      return "DW_OP_const8u";
      return "DW_OP_const8u";
    case DW_OP_const8s:
    case DW_OP_const8s:
      return "DW_OP_const8s";
      return "DW_OP_const8s";
    case DW_OP_constu:
    case DW_OP_constu:
      return "DW_OP_constu";
      return "DW_OP_constu";
    case DW_OP_consts:
    case DW_OP_consts:
      return "DW_OP_consts";
      return "DW_OP_consts";
    case DW_OP_dup:
    case DW_OP_dup:
      return "DW_OP_dup";
      return "DW_OP_dup";
    case DW_OP_drop:
    case DW_OP_drop:
      return "DW_OP_drop";
      return "DW_OP_drop";
    case DW_OP_over:
    case DW_OP_over:
      return "DW_OP_over";
      return "DW_OP_over";
    case DW_OP_pick:
    case DW_OP_pick:
      return "DW_OP_pick";
      return "DW_OP_pick";
    case DW_OP_swap:
    case DW_OP_swap:
      return "DW_OP_swap";
      return "DW_OP_swap";
    case DW_OP_rot:
    case DW_OP_rot:
      return "DW_OP_rot";
      return "DW_OP_rot";
    case DW_OP_xderef:
    case DW_OP_xderef:
      return "DW_OP_xderef";
      return "DW_OP_xderef";
    case DW_OP_abs:
    case DW_OP_abs:
      return "DW_OP_abs";
      return "DW_OP_abs";
    case DW_OP_and:
    case DW_OP_and:
      return "DW_OP_and";
      return "DW_OP_and";
    case DW_OP_div:
    case DW_OP_div:
      return "DW_OP_div";
      return "DW_OP_div";
    case DW_OP_minus:
    case DW_OP_minus:
      return "DW_OP_minus";
      return "DW_OP_minus";
    case DW_OP_mod:
    case DW_OP_mod:
      return "DW_OP_mod";
      return "DW_OP_mod";
    case DW_OP_mul:
    case DW_OP_mul:
      return "DW_OP_mul";
      return "DW_OP_mul";
    case DW_OP_neg:
    case DW_OP_neg:
      return "DW_OP_neg";
      return "DW_OP_neg";
    case DW_OP_not:
    case DW_OP_not:
      return "DW_OP_not";
      return "DW_OP_not";
    case DW_OP_or:
    case DW_OP_or:
      return "DW_OP_or";
      return "DW_OP_or";
    case DW_OP_plus:
    case DW_OP_plus:
      return "DW_OP_plus";
      return "DW_OP_plus";
    case DW_OP_plus_uconst:
    case DW_OP_plus_uconst:
      return "DW_OP_plus_uconst";
      return "DW_OP_plus_uconst";
    case DW_OP_shl:
    case DW_OP_shl:
      return "DW_OP_shl";
      return "DW_OP_shl";
    case DW_OP_shr:
    case DW_OP_shr:
      return "DW_OP_shr";
      return "DW_OP_shr";
    case DW_OP_shra:
    case DW_OP_shra:
      return "DW_OP_shra";
      return "DW_OP_shra";
    case DW_OP_xor:
    case DW_OP_xor:
      return "DW_OP_xor";
      return "DW_OP_xor";
    case DW_OP_bra:
    case DW_OP_bra:
      return "DW_OP_bra";
      return "DW_OP_bra";
    case DW_OP_eq:
    case DW_OP_eq:
      return "DW_OP_eq";
      return "DW_OP_eq";
    case DW_OP_ge:
    case DW_OP_ge:
      return "DW_OP_ge";
      return "DW_OP_ge";
    case DW_OP_gt:
    case DW_OP_gt:
      return "DW_OP_gt";
      return "DW_OP_gt";
    case DW_OP_le:
    case DW_OP_le:
      return "DW_OP_le";
      return "DW_OP_le";
    case DW_OP_lt:
    case DW_OP_lt:
      return "DW_OP_lt";
      return "DW_OP_lt";
    case DW_OP_ne:
    case DW_OP_ne:
      return "DW_OP_ne";
      return "DW_OP_ne";
    case DW_OP_skip:
    case DW_OP_skip:
      return "DW_OP_skip";
      return "DW_OP_skip";
    case DW_OP_lit0:
    case DW_OP_lit0:
      return "DW_OP_lit0";
      return "DW_OP_lit0";
    case DW_OP_lit1:
    case DW_OP_lit1:
      return "DW_OP_lit1";
      return "DW_OP_lit1";
    case DW_OP_lit2:
    case DW_OP_lit2:
      return "DW_OP_lit2";
      return "DW_OP_lit2";
    case DW_OP_lit3:
    case DW_OP_lit3:
      return "DW_OP_lit3";
      return "DW_OP_lit3";
    case DW_OP_lit4:
    case DW_OP_lit4:
      return "DW_OP_lit4";
      return "DW_OP_lit4";
    case DW_OP_lit5:
    case DW_OP_lit5:
      return "DW_OP_lit5";
      return "DW_OP_lit5";
    case DW_OP_lit6:
    case DW_OP_lit6:
      return "DW_OP_lit6";
      return "DW_OP_lit6";
    case DW_OP_lit7:
    case DW_OP_lit7:
      return "DW_OP_lit7";
      return "DW_OP_lit7";
    case DW_OP_lit8:
    case DW_OP_lit8:
      return "DW_OP_lit8";
      return "DW_OP_lit8";
    case DW_OP_lit9:
    case DW_OP_lit9:
      return "DW_OP_lit9";
      return "DW_OP_lit9";
    case DW_OP_lit10:
    case DW_OP_lit10:
      return "DW_OP_lit10";
      return "DW_OP_lit10";
    case DW_OP_lit11:
    case DW_OP_lit11:
      return "DW_OP_lit11";
      return "DW_OP_lit11";
    case DW_OP_lit12:
    case DW_OP_lit12:
      return "DW_OP_lit12";
      return "DW_OP_lit12";
    case DW_OP_lit13:
    case DW_OP_lit13:
      return "DW_OP_lit13";
      return "DW_OP_lit13";
    case DW_OP_lit14:
    case DW_OP_lit14:
      return "DW_OP_lit14";
      return "DW_OP_lit14";
    case DW_OP_lit15:
    case DW_OP_lit15:
      return "DW_OP_lit15";
      return "DW_OP_lit15";
    case DW_OP_lit16:
    case DW_OP_lit16:
      return "DW_OP_lit16";
      return "DW_OP_lit16";
    case DW_OP_lit17:
    case DW_OP_lit17:
      return "DW_OP_lit17";
      return "DW_OP_lit17";
    case DW_OP_lit18:
    case DW_OP_lit18:
      return "DW_OP_lit18";
      return "DW_OP_lit18";
    case DW_OP_lit19:
    case DW_OP_lit19:
      return "DW_OP_lit19";
      return "DW_OP_lit19";
    case DW_OP_lit20:
    case DW_OP_lit20:
      return "DW_OP_lit20";
      return "DW_OP_lit20";
    case DW_OP_lit21:
    case DW_OP_lit21:
      return "DW_OP_lit21";
      return "DW_OP_lit21";
    case DW_OP_lit22:
    case DW_OP_lit22:
      return "DW_OP_lit22";
      return "DW_OP_lit22";
    case DW_OP_lit23:
    case DW_OP_lit23:
      return "DW_OP_lit23";
      return "DW_OP_lit23";
    case DW_OP_lit24:
    case DW_OP_lit24:
      return "DW_OP_lit24";
      return "DW_OP_lit24";
    case DW_OP_lit25:
    case DW_OP_lit25:
      return "DW_OP_lit25";
      return "DW_OP_lit25";
    case DW_OP_lit26:
    case DW_OP_lit26:
      return "DW_OP_lit26";
      return "DW_OP_lit26";
    case DW_OP_lit27:
    case DW_OP_lit27:
      return "DW_OP_lit27";
      return "DW_OP_lit27";
    case DW_OP_lit28:
    case DW_OP_lit28:
      return "DW_OP_lit28";
      return "DW_OP_lit28";
    case DW_OP_lit29:
    case DW_OP_lit29:
      return "DW_OP_lit29";
      return "DW_OP_lit29";
    case DW_OP_lit30:
    case DW_OP_lit30:
      return "DW_OP_lit30";
      return "DW_OP_lit30";
    case DW_OP_lit31:
    case DW_OP_lit31:
      return "DW_OP_lit31";
      return "DW_OP_lit31";
    case DW_OP_reg0:
    case DW_OP_reg0:
      return "DW_OP_reg0";
      return "DW_OP_reg0";
    case DW_OP_reg1:
    case DW_OP_reg1:
      return "DW_OP_reg1";
      return "DW_OP_reg1";
    case DW_OP_reg2:
    case DW_OP_reg2:
      return "DW_OP_reg2";
      return "DW_OP_reg2";
    case DW_OP_reg3:
    case DW_OP_reg3:
      return "DW_OP_reg3";
      return "DW_OP_reg3";
    case DW_OP_reg4:
    case DW_OP_reg4:
      return "DW_OP_reg4";
      return "DW_OP_reg4";
    case DW_OP_reg5:
    case DW_OP_reg5:
      return "DW_OP_reg5";
      return "DW_OP_reg5";
    case DW_OP_reg6:
    case DW_OP_reg6:
      return "DW_OP_reg6";
      return "DW_OP_reg6";
    case DW_OP_reg7:
    case DW_OP_reg7:
      return "DW_OP_reg7";
      return "DW_OP_reg7";
    case DW_OP_reg8:
    case DW_OP_reg8:
      return "DW_OP_reg8";
      return "DW_OP_reg8";
    case DW_OP_reg9:
    case DW_OP_reg9:
      return "DW_OP_reg9";
      return "DW_OP_reg9";
    case DW_OP_reg10:
    case DW_OP_reg10:
      return "DW_OP_reg10";
      return "DW_OP_reg10";
    case DW_OP_reg11:
    case DW_OP_reg11:
      return "DW_OP_reg11";
      return "DW_OP_reg11";
    case DW_OP_reg12:
    case DW_OP_reg12:
      return "DW_OP_reg12";
      return "DW_OP_reg12";
    case DW_OP_reg13:
    case DW_OP_reg13:
      return "DW_OP_reg13";
      return "DW_OP_reg13";
    case DW_OP_reg14:
    case DW_OP_reg14:
      return "DW_OP_reg14";
      return "DW_OP_reg14";
    case DW_OP_reg15:
    case DW_OP_reg15:
      return "DW_OP_reg15";
      return "DW_OP_reg15";
    case DW_OP_reg16:
    case DW_OP_reg16:
      return "DW_OP_reg16";
      return "DW_OP_reg16";
    case DW_OP_reg17:
    case DW_OP_reg17:
      return "DW_OP_reg17";
      return "DW_OP_reg17";
    case DW_OP_reg18:
    case DW_OP_reg18:
      return "DW_OP_reg18";
      return "DW_OP_reg18";
    case DW_OP_reg19:
    case DW_OP_reg19:
      return "DW_OP_reg19";
      return "DW_OP_reg19";
    case DW_OP_reg20:
    case DW_OP_reg20:
      return "DW_OP_reg20";
      return "DW_OP_reg20";
    case DW_OP_reg21:
    case DW_OP_reg21:
      return "DW_OP_reg21";
      return "DW_OP_reg21";
    case DW_OP_reg22:
    case DW_OP_reg22:
      return "DW_OP_reg22";
      return "DW_OP_reg22";
    case DW_OP_reg23:
    case DW_OP_reg23:
      return "DW_OP_reg23";
      return "DW_OP_reg23";
    case DW_OP_reg24:
    case DW_OP_reg24:
      return "DW_OP_reg24";
      return "DW_OP_reg24";
    case DW_OP_reg25:
    case DW_OP_reg25:
      return "DW_OP_reg25";
      return "DW_OP_reg25";
    case DW_OP_reg26:
    case DW_OP_reg26:
      return "DW_OP_reg26";
      return "DW_OP_reg26";
    case DW_OP_reg27:
    case DW_OP_reg27:
      return "DW_OP_reg27";
      return "DW_OP_reg27";
    case DW_OP_reg28:
    case DW_OP_reg28:
      return "DW_OP_reg28";
      return "DW_OP_reg28";
    case DW_OP_reg29:
    case DW_OP_reg29:
      return "DW_OP_reg29";
      return "DW_OP_reg29";
    case DW_OP_reg30:
    case DW_OP_reg30:
      return "DW_OP_reg30";
      return "DW_OP_reg30";
    case DW_OP_reg31:
    case DW_OP_reg31:
      return "DW_OP_reg31";
      return "DW_OP_reg31";
    case DW_OP_breg0:
    case DW_OP_breg0:
      return "DW_OP_breg0";
      return "DW_OP_breg0";
    case DW_OP_breg1:
    case DW_OP_breg1:
      return "DW_OP_breg1";
      return "DW_OP_breg1";
    case DW_OP_breg2:
    case DW_OP_breg2:
      return "DW_OP_breg2";
      return "DW_OP_breg2";
    case DW_OP_breg3:
    case DW_OP_breg3:
      return "DW_OP_breg3";
      return "DW_OP_breg3";
    case DW_OP_breg4:
    case DW_OP_breg4:
      return "DW_OP_breg4";
      return "DW_OP_breg4";
    case DW_OP_breg5:
    case DW_OP_breg5:
      return "DW_OP_breg5";
      return "DW_OP_breg5";
    case DW_OP_breg6:
    case DW_OP_breg6:
      return "DW_OP_breg6";
      return "DW_OP_breg6";
    case DW_OP_breg7:
    case DW_OP_breg7:
      return "DW_OP_breg7";
      return "DW_OP_breg7";
    case DW_OP_breg8:
    case DW_OP_breg8:
      return "DW_OP_breg8";
      return "DW_OP_breg8";
    case DW_OP_breg9:
    case DW_OP_breg9:
      return "DW_OP_breg9";
      return "DW_OP_breg9";
    case DW_OP_breg10:
    case DW_OP_breg10:
      return "DW_OP_breg10";
      return "DW_OP_breg10";
    case DW_OP_breg11:
    case DW_OP_breg11:
      return "DW_OP_breg11";
      return "DW_OP_breg11";
    case DW_OP_breg12:
    case DW_OP_breg12:
      return "DW_OP_breg12";
      return "DW_OP_breg12";
    case DW_OP_breg13:
    case DW_OP_breg13:
      return "DW_OP_breg13";
      return "DW_OP_breg13";
    case DW_OP_breg14:
    case DW_OP_breg14:
      return "DW_OP_breg14";
      return "DW_OP_breg14";
    case DW_OP_breg15:
    case DW_OP_breg15:
      return "DW_OP_breg15";
      return "DW_OP_breg15";
    case DW_OP_breg16:
    case DW_OP_breg16:
      return "DW_OP_breg16";
      return "DW_OP_breg16";
    case DW_OP_breg17:
    case DW_OP_breg17:
      return "DW_OP_breg17";
      return "DW_OP_breg17";
    case DW_OP_breg18:
    case DW_OP_breg18:
      return "DW_OP_breg18";
      return "DW_OP_breg18";
    case DW_OP_breg19:
    case DW_OP_breg19:
      return "DW_OP_breg19";
      return "DW_OP_breg19";
    case DW_OP_breg20:
    case DW_OP_breg20:
      return "DW_OP_breg20";
      return "DW_OP_breg20";
    case DW_OP_breg21:
    case DW_OP_breg21:
      return "DW_OP_breg21";
      return "DW_OP_breg21";
    case DW_OP_breg22:
    case DW_OP_breg22:
      return "DW_OP_breg22";
      return "DW_OP_breg22";
    case DW_OP_breg23:
    case DW_OP_breg23:
      return "DW_OP_breg23";
      return "DW_OP_breg23";
    case DW_OP_breg24:
    case DW_OP_breg24:
      return "DW_OP_breg24";
      return "DW_OP_breg24";
    case DW_OP_breg25:
    case DW_OP_breg25:
      return "DW_OP_breg25";
      return "DW_OP_breg25";
    case DW_OP_breg26:
    case DW_OP_breg26:
      return "DW_OP_breg26";
      return "DW_OP_breg26";
    case DW_OP_breg27:
    case DW_OP_breg27:
      return "DW_OP_breg27";
      return "DW_OP_breg27";
    case DW_OP_breg28:
    case DW_OP_breg28:
      return "DW_OP_breg28";
      return "DW_OP_breg28";
    case DW_OP_breg29:
    case DW_OP_breg29:
      return "DW_OP_breg29";
      return "DW_OP_breg29";
    case DW_OP_breg30:
    case DW_OP_breg30:
      return "DW_OP_breg30";
      return "DW_OP_breg30";
    case DW_OP_breg31:
    case DW_OP_breg31:
      return "DW_OP_breg31";
      return "DW_OP_breg31";
    case DW_OP_regx:
    case DW_OP_regx:
      return "DW_OP_regx";
      return "DW_OP_regx";
    case DW_OP_fbreg:
    case DW_OP_fbreg:
      return "DW_OP_fbreg";
      return "DW_OP_fbreg";
    case DW_OP_bregx:
    case DW_OP_bregx:
      return "DW_OP_bregx";
      return "DW_OP_bregx";
    case DW_OP_piece:
    case DW_OP_piece:
      return "DW_OP_piece";
      return "DW_OP_piece";
    case DW_OP_deref_size:
    case DW_OP_deref_size:
      return "DW_OP_deref_size";
      return "DW_OP_deref_size";
    case DW_OP_xderef_size:
    case DW_OP_xderef_size:
      return "DW_OP_xderef_size";
      return "DW_OP_xderef_size";
    case DW_OP_nop:
    case DW_OP_nop:
      return "DW_OP_nop";
      return "DW_OP_nop";
    default:
    default:
      return "OP_<unknown>";
      return "OP_<unknown>";
    }
    }
}
}
 
 
static char *
static char *
dwarf_bool_name (mybool)
dwarf_bool_name (mybool)
     unsigned mybool;
     unsigned mybool;
{
{
  if (mybool)
  if (mybool)
    return "TRUE";
    return "TRUE";
  else
  else
    return "FALSE";
    return "FALSE";
}
}
 
 
/* Convert a DWARF type code into its string name.  */
/* Convert a DWARF type code into its string name.  */
 
 
static char *
static char *
dwarf_type_encoding_name (enc)
dwarf_type_encoding_name (enc)
     register unsigned enc;
     register unsigned enc;
{
{
  switch (enc)
  switch (enc)
    {
    {
    case DW_ATE_address:
    case DW_ATE_address:
      return "DW_ATE_address";
      return "DW_ATE_address";
    case DW_ATE_boolean:
    case DW_ATE_boolean:
      return "DW_ATE_boolean";
      return "DW_ATE_boolean";
    case DW_ATE_complex_float:
    case DW_ATE_complex_float:
      return "DW_ATE_complex_float";
      return "DW_ATE_complex_float";
    case DW_ATE_float:
    case DW_ATE_float:
      return "DW_ATE_float";
      return "DW_ATE_float";
    case DW_ATE_signed:
    case DW_ATE_signed:
      return "DW_ATE_signed";
      return "DW_ATE_signed";
    case DW_ATE_signed_char:
    case DW_ATE_signed_char:
      return "DW_ATE_signed_char";
      return "DW_ATE_signed_char";
    case DW_ATE_unsigned:
    case DW_ATE_unsigned:
      return "DW_ATE_unsigned";
      return "DW_ATE_unsigned";
    case DW_ATE_unsigned_char:
    case DW_ATE_unsigned_char:
      return "DW_ATE_unsigned_char";
      return "DW_ATE_unsigned_char";
    default:
    default:
      return "DW_ATE_<unknown>";
      return "DW_ATE_<unknown>";
    }
    }
}
}
 
 
/* Convert a DWARF call frame info operation to its string name. */
/* Convert a DWARF call frame info operation to its string name. */
 
 
#if 0
#if 0
static char *
static char *
dwarf_cfi_name (cfi_opc)
dwarf_cfi_name (cfi_opc)
     register unsigned cfi_opc;
     register unsigned cfi_opc;
{
{
  switch (cfi_opc)
  switch (cfi_opc)
    {
    {
    case DW_CFA_advance_loc:
    case DW_CFA_advance_loc:
      return "DW_CFA_advance_loc";
      return "DW_CFA_advance_loc";
    case DW_CFA_offset:
    case DW_CFA_offset:
      return "DW_CFA_offset";
      return "DW_CFA_offset";
    case DW_CFA_restore:
    case DW_CFA_restore:
      return "DW_CFA_restore";
      return "DW_CFA_restore";
    case DW_CFA_nop:
    case DW_CFA_nop:
      return "DW_CFA_nop";
      return "DW_CFA_nop";
    case DW_CFA_set_loc:
    case DW_CFA_set_loc:
      return "DW_CFA_set_loc";
      return "DW_CFA_set_loc";
    case DW_CFA_advance_loc1:
    case DW_CFA_advance_loc1:
      return "DW_CFA_advance_loc1";
      return "DW_CFA_advance_loc1";
    case DW_CFA_advance_loc2:
    case DW_CFA_advance_loc2:
      return "DW_CFA_advance_loc2";
      return "DW_CFA_advance_loc2";
    case DW_CFA_advance_loc4:
    case DW_CFA_advance_loc4:
      return "DW_CFA_advance_loc4";
      return "DW_CFA_advance_loc4";
    case DW_CFA_offset_extended:
    case DW_CFA_offset_extended:
      return "DW_CFA_offset_extended";
      return "DW_CFA_offset_extended";
    case DW_CFA_restore_extended:
    case DW_CFA_restore_extended:
      return "DW_CFA_restore_extended";
      return "DW_CFA_restore_extended";
    case DW_CFA_undefined:
    case DW_CFA_undefined:
      return "DW_CFA_undefined";
      return "DW_CFA_undefined";
    case DW_CFA_same_value:
    case DW_CFA_same_value:
      return "DW_CFA_same_value";
      return "DW_CFA_same_value";
    case DW_CFA_register:
    case DW_CFA_register:
      return "DW_CFA_register";
      return "DW_CFA_register";
    case DW_CFA_remember_state:
    case DW_CFA_remember_state:
      return "DW_CFA_remember_state";
      return "DW_CFA_remember_state";
    case DW_CFA_restore_state:
    case DW_CFA_restore_state:
      return "DW_CFA_restore_state";
      return "DW_CFA_restore_state";
    case DW_CFA_def_cfa:
    case DW_CFA_def_cfa:
      return "DW_CFA_def_cfa";
      return "DW_CFA_def_cfa";
    case DW_CFA_def_cfa_register:
    case DW_CFA_def_cfa_register:
      return "DW_CFA_def_cfa_register";
      return "DW_CFA_def_cfa_register";
    case DW_CFA_def_cfa_offset:
    case DW_CFA_def_cfa_offset:
      return "DW_CFA_def_cfa_offset";
      return "DW_CFA_def_cfa_offset";
      /* SGI/MIPS specific */
      /* SGI/MIPS specific */
    case DW_CFA_MIPS_advance_loc8:
    case DW_CFA_MIPS_advance_loc8:
      return "DW_CFA_MIPS_advance_loc8";
      return "DW_CFA_MIPS_advance_loc8";
    default:
    default:
      return "DW_CFA_<unknown>";
      return "DW_CFA_<unknown>";
    }
    }
}
}
#endif
#endif
 
 
void
void
dump_die (die)
dump_die (die)
     struct die_info *die;
     struct die_info *die;
{
{
  unsigned int i;
  unsigned int i;
 
 
  fprintf (stderr, "Die: %s (abbrev = %d, offset = %d)\n",
  fprintf (stderr, "Die: %s (abbrev = %d, offset = %d)\n",
           dwarf_tag_name (die->tag), die->abbrev, die->offset);
           dwarf_tag_name (die->tag), die->abbrev, die->offset);
  fprintf (stderr, "\thas children: %s\n",
  fprintf (stderr, "\thas children: %s\n",
           dwarf_bool_name (die->has_children));
           dwarf_bool_name (die->has_children));
 
 
  fprintf (stderr, "\tattributes:\n");
  fprintf (stderr, "\tattributes:\n");
  for (i = 0; i < die->num_attrs; ++i)
  for (i = 0; i < die->num_attrs; ++i)
    {
    {
      fprintf (stderr, "\t\t%s (%s) ",
      fprintf (stderr, "\t\t%s (%s) ",
               dwarf_attr_name (die->attrs[i].name),
               dwarf_attr_name (die->attrs[i].name),
               dwarf_form_name (die->attrs[i].form));
               dwarf_form_name (die->attrs[i].form));
      switch (die->attrs[i].form)
      switch (die->attrs[i].form)
        {
        {
        case DW_FORM_ref_addr:
        case DW_FORM_ref_addr:
        case DW_FORM_addr:
        case DW_FORM_addr:
          fprintf (stderr, "address: ");
          fprintf (stderr, "address: ");
          print_address_numeric (DW_ADDR (&die->attrs[i]), 1, gdb_stderr);
          print_address_numeric (DW_ADDR (&die->attrs[i]), 1, gdb_stderr);
          break;
          break;
        case DW_FORM_block2:
        case DW_FORM_block2:
        case DW_FORM_block4:
        case DW_FORM_block4:
        case DW_FORM_block:
        case DW_FORM_block:
        case DW_FORM_block1:
        case DW_FORM_block1:
          fprintf (stderr, "block: size %d", DW_BLOCK (&die->attrs[i])->size);
          fprintf (stderr, "block: size %d", DW_BLOCK (&die->attrs[i])->size);
          break;
          break;
        case DW_FORM_data1:
        case DW_FORM_data1:
        case DW_FORM_data2:
        case DW_FORM_data2:
        case DW_FORM_data4:
        case DW_FORM_data4:
        case DW_FORM_ref1:
        case DW_FORM_ref1:
        case DW_FORM_ref2:
        case DW_FORM_ref2:
        case DW_FORM_ref4:
        case DW_FORM_ref4:
        case DW_FORM_udata:
        case DW_FORM_udata:
        case DW_FORM_sdata:
        case DW_FORM_sdata:
          fprintf (stderr, "constant: %d", DW_UNSND (&die->attrs[i]));
          fprintf (stderr, "constant: %d", DW_UNSND (&die->attrs[i]));
          break;
          break;
        case DW_FORM_string:
        case DW_FORM_string:
          fprintf (stderr, "string: \"%s\"",
          fprintf (stderr, "string: \"%s\"",
                   DW_STRING (&die->attrs[i])
                   DW_STRING (&die->attrs[i])
                   ? DW_STRING (&die->attrs[i]) : "");
                   ? DW_STRING (&die->attrs[i]) : "");
          break;
          break;
        case DW_FORM_flag:
        case DW_FORM_flag:
          if (DW_UNSND (&die->attrs[i]))
          if (DW_UNSND (&die->attrs[i]))
            fprintf (stderr, "flag: TRUE");
            fprintf (stderr, "flag: TRUE");
          else
          else
            fprintf (stderr, "flag: FALSE");
            fprintf (stderr, "flag: FALSE");
          break;
          break;
        case DW_FORM_strp:      /* we do not support separate string
        case DW_FORM_strp:      /* we do not support separate string
                                   section yet */
                                   section yet */
        case DW_FORM_indirect:  /* we do not handle indirect yet */
        case DW_FORM_indirect:  /* we do not handle indirect yet */
        case DW_FORM_data8:     /* we do not have 64 bit quantities */
        case DW_FORM_data8:     /* we do not have 64 bit quantities */
        default:
        default:
          fprintf (stderr, "unsupported attribute form: %d.",
          fprintf (stderr, "unsupported attribute form: %d.",
                   die->attrs[i].form);
                   die->attrs[i].form);
        }
        }
      fprintf (stderr, "\n");
      fprintf (stderr, "\n");
    }
    }
}
}
 
 
void
void
dump_die_list (die)
dump_die_list (die)
     struct die_info *die;
     struct die_info *die;
{
{
  while (die)
  while (die)
    {
    {
      dump_die (die);
      dump_die (die);
      die = die->next;
      die = die->next;
    }
    }
}
}
 
 
void
void
store_in_ref_table (offset, die)
store_in_ref_table (offset, die)
     unsigned int offset;
     unsigned int offset;
     struct die_info *die;
     struct die_info *die;
{
{
  int h;
  int h;
  struct die_info *old;
  struct die_info *old;
 
 
  h = (offset % REF_HASH_SIZE);
  h = (offset % REF_HASH_SIZE);
  old = die_ref_table[h];
  old = die_ref_table[h];
  die->next_ref = old;
  die->next_ref = old;
  die_ref_table[h] = die;
  die_ref_table[h] = die;
}
}
 
 
 
 
static void
static void
dwarf2_empty_die_ref_table ()
dwarf2_empty_die_ref_table ()
{
{
  memset (die_ref_table, 0, sizeof (die_ref_table));
  memset (die_ref_table, 0, sizeof (die_ref_table));
}
}
 
 
static unsigned int
static unsigned int
dwarf2_get_ref_die_offset (attr)
dwarf2_get_ref_die_offset (attr)
     struct attribute *attr;
     struct attribute *attr;
{
{
  unsigned int result = 0;
  unsigned int result = 0;
 
 
  switch (attr->form)
  switch (attr->form)
    {
    {
    case DW_FORM_ref_addr:
    case DW_FORM_ref_addr:
      result = DW_ADDR (attr);
      result = DW_ADDR (attr);
      break;
      break;
    case DW_FORM_ref1:
    case DW_FORM_ref1:
    case DW_FORM_ref2:
    case DW_FORM_ref2:
    case DW_FORM_ref4:
    case DW_FORM_ref4:
    case DW_FORM_ref_udata:
    case DW_FORM_ref_udata:
      result = cu_header_offset + DW_UNSND (attr);
      result = cu_header_offset + DW_UNSND (attr);
      break;
      break;
    default:
    default:
      complain (&dwarf2_unsupported_die_ref_attr, dwarf_form_name (attr->form));
      complain (&dwarf2_unsupported_die_ref_attr, dwarf_form_name (attr->form));
    }
    }
  return result;
  return result;
}
}
 
 
struct die_info *
struct die_info *
follow_die_ref (offset)
follow_die_ref (offset)
     unsigned int offset;
     unsigned int offset;
{
{
  struct die_info *die;
  struct die_info *die;
  int h;
  int h;
 
 
  h = (offset % REF_HASH_SIZE);
  h = (offset % REF_HASH_SIZE);
  die = die_ref_table[h];
  die = die_ref_table[h];
  while (die)
  while (die)
    {
    {
      if (die->offset == offset)
      if (die->offset == offset)
        {
        {
          return die;
          return die;
        }
        }
      die = die->next_ref;
      die = die->next_ref;
    }
    }
  return NULL;
  return NULL;
}
}
 
 
static struct type *
static struct type *
dwarf2_fundamental_type (objfile, typeid)
dwarf2_fundamental_type (objfile, typeid)
     struct objfile *objfile;
     struct objfile *objfile;
     int typeid;
     int typeid;
{
{
  if (typeid < 0 || typeid >= FT_NUM_MEMBERS)
  if (typeid < 0 || typeid >= FT_NUM_MEMBERS)
    {
    {
      error ("Dwarf Error: internal error - invalid fundamental type id %d.",
      error ("Dwarf Error: internal error - invalid fundamental type id %d.",
             typeid);
             typeid);
    }
    }
 
 
  /* Look for this particular type in the fundamental type vector.  If
  /* Look for this particular type in the fundamental type vector.  If
     one is not found, create and install one appropriate for the
     one is not found, create and install one appropriate for the
     current language and the current target machine. */
     current language and the current target machine. */
 
 
  if (ftypes[typeid] == NULL)
  if (ftypes[typeid] == NULL)
    {
    {
      ftypes[typeid] = cu_language_defn->la_fund_type (objfile, typeid);
      ftypes[typeid] = cu_language_defn->la_fund_type (objfile, typeid);
    }
    }
 
 
  return (ftypes[typeid]);
  return (ftypes[typeid]);
}
}
 
 
/* Decode simple location descriptions.
/* Decode simple location descriptions.
   Given a pointer to a dwarf block that defines a location, compute
   Given a pointer to a dwarf block that defines a location, compute
   the location and return the value.
   the location and return the value.
 
 
   FIXME: This is a kludge until we figure out a better
   FIXME: This is a kludge until we figure out a better
   way to handle the location descriptions.
   way to handle the location descriptions.
   Gdb's design does not mesh well with the DWARF2 notion of a location
   Gdb's design does not mesh well with the DWARF2 notion of a location
   computing interpreter, which is a shame because the flexibility goes unused.
   computing interpreter, which is a shame because the flexibility goes unused.
   FIXME: Implement more operations as necessary.
   FIXME: Implement more operations as necessary.
 
 
   A location description containing no operations indicates that the
   A location description containing no operations indicates that the
   object is optimized out. The global optimized_out flag is set for
   object is optimized out. The global optimized_out flag is set for
   those, the return value is meaningless.
   those, the return value is meaningless.
 
 
   When the result is a register number, the global isreg flag is set,
   When the result is a register number, the global isreg flag is set,
   otherwise it is cleared.
   otherwise it is cleared.
 
 
   When the result is a base register offset, the global offreg flag is set
   When the result is a base register offset, the global offreg flag is set
   and the register number is returned in basereg, otherwise it is cleared.
   and the register number is returned in basereg, otherwise it is cleared.
 
 
   When the DW_OP_fbreg operation is encountered without a corresponding
   When the DW_OP_fbreg operation is encountered without a corresponding
   DW_AT_frame_base attribute, the global islocal flag is set.
   DW_AT_frame_base attribute, the global islocal flag is set.
   Hopefully the machine dependent code knows how to set up a virtual
   Hopefully the machine dependent code knows how to set up a virtual
   frame pointer for the local references.
   frame pointer for the local references.
 
 
   Note that stack[0] is unused except as a default error return.
   Note that stack[0] is unused except as a default error return.
   Note that stack overflow is not yet handled.  */
   Note that stack overflow is not yet handled.  */
 
 
static CORE_ADDR
static CORE_ADDR
decode_locdesc (blk, objfile)
decode_locdesc (blk, objfile)
     struct dwarf_block *blk;
     struct dwarf_block *blk;
     struct objfile *objfile;
     struct objfile *objfile;
{
{
  int i;
  int i;
  int size = blk->size;
  int size = blk->size;
  char *data = blk->data;
  char *data = blk->data;
  CORE_ADDR stack[64];
  CORE_ADDR stack[64];
  int stacki;
  int stacki;
  unsigned int bytes_read, unsnd;
  unsigned int bytes_read, unsnd;
  unsigned char op;
  unsigned char op;
 
 
  i = 0;
  i = 0;
  stacki = 0;
  stacki = 0;
  stack[stacki] = 0;
  stack[stacki] = 0;
  isreg = 0;
  isreg = 0;
  offreg = 0;
  offreg = 0;
  isderef = 0;
  isderef = 0;
  islocal = 0;
  islocal = 0;
  optimized_out = 1;
  optimized_out = 1;
 
 
  while (i < size)
  while (i < size)
    {
    {
      optimized_out = 0;
      optimized_out = 0;
      op = data[i++];
      op = data[i++];
      switch (op)
      switch (op)
        {
        {
        case DW_OP_reg0:
        case DW_OP_reg0:
        case DW_OP_reg1:
        case DW_OP_reg1:
        case DW_OP_reg2:
        case DW_OP_reg2:
        case DW_OP_reg3:
        case DW_OP_reg3:
        case DW_OP_reg4:
        case DW_OP_reg4:
        case DW_OP_reg5:
        case DW_OP_reg5:
        case DW_OP_reg6:
        case DW_OP_reg6:
        case DW_OP_reg7:
        case DW_OP_reg7:
        case DW_OP_reg8:
        case DW_OP_reg8:
        case DW_OP_reg9:
        case DW_OP_reg9:
        case DW_OP_reg10:
        case DW_OP_reg10:
        case DW_OP_reg11:
        case DW_OP_reg11:
        case DW_OP_reg12:
        case DW_OP_reg12:
        case DW_OP_reg13:
        case DW_OP_reg13:
        case DW_OP_reg14:
        case DW_OP_reg14:
        case DW_OP_reg15:
        case DW_OP_reg15:
        case DW_OP_reg16:
        case DW_OP_reg16:
        case DW_OP_reg17:
        case DW_OP_reg17:
        case DW_OP_reg18:
        case DW_OP_reg18:
        case DW_OP_reg19:
        case DW_OP_reg19:
        case DW_OP_reg20:
        case DW_OP_reg20:
        case DW_OP_reg21:
        case DW_OP_reg21:
        case DW_OP_reg22:
        case DW_OP_reg22:
        case DW_OP_reg23:
        case DW_OP_reg23:
        case DW_OP_reg24:
        case DW_OP_reg24:
        case DW_OP_reg25:
        case DW_OP_reg25:
        case DW_OP_reg26:
        case DW_OP_reg26:
        case DW_OP_reg27:
        case DW_OP_reg27:
        case DW_OP_reg28:
        case DW_OP_reg28:
        case DW_OP_reg29:
        case DW_OP_reg29:
        case DW_OP_reg30:
        case DW_OP_reg30:
        case DW_OP_reg31:
        case DW_OP_reg31:
          isreg = 1;
          isreg = 1;
          stack[++stacki] = op - DW_OP_reg0;
          stack[++stacki] = op - DW_OP_reg0;
          break;
          break;
 
 
        case DW_OP_regx:
        case DW_OP_regx:
          isreg = 1;
          isreg = 1;
          unsnd = read_unsigned_leb128 (NULL, (data + i), &bytes_read);
          unsnd = read_unsigned_leb128 (NULL, (data + i), &bytes_read);
          i += bytes_read;
          i += bytes_read;
#if defined(HARRIS_TARGET) && defined(_M88K)
#if defined(HARRIS_TARGET) && defined(_M88K)
          /* The Harris 88110 gdb ports have long kept their special reg
          /* The Harris 88110 gdb ports have long kept their special reg
             numbers between their gp-regs and their x-regs.  This is
             numbers between their gp-regs and their x-regs.  This is
             not how our dwarf is generated.  Punt. */
             not how our dwarf is generated.  Punt. */
          unsnd += 6;
          unsnd += 6;
#endif
#endif
          stack[++stacki] = unsnd;
          stack[++stacki] = unsnd;
          break;
          break;
 
 
        case DW_OP_breg0:
        case DW_OP_breg0:
        case DW_OP_breg1:
        case DW_OP_breg1:
        case DW_OP_breg2:
        case DW_OP_breg2:
        case DW_OP_breg3:
        case DW_OP_breg3:
        case DW_OP_breg4:
        case DW_OP_breg4:
        case DW_OP_breg5:
        case DW_OP_breg5:
        case DW_OP_breg6:
        case DW_OP_breg6:
        case DW_OP_breg7:
        case DW_OP_breg7:
        case DW_OP_breg8:
        case DW_OP_breg8:
        case DW_OP_breg9:
        case DW_OP_breg9:
        case DW_OP_breg10:
        case DW_OP_breg10:
        case DW_OP_breg11:
        case DW_OP_breg11:
        case DW_OP_breg12:
        case DW_OP_breg12:
        case DW_OP_breg13:
        case DW_OP_breg13:
        case DW_OP_breg14:
        case DW_OP_breg14:
        case DW_OP_breg15:
        case DW_OP_breg15:
        case DW_OP_breg16:
        case DW_OP_breg16:
        case DW_OP_breg17:
        case DW_OP_breg17:
        case DW_OP_breg18:
        case DW_OP_breg18:
        case DW_OP_breg19:
        case DW_OP_breg19:
        case DW_OP_breg20:
        case DW_OP_breg20:
        case DW_OP_breg21:
        case DW_OP_breg21:
        case DW_OP_breg22:
        case DW_OP_breg22:
        case DW_OP_breg23:
        case DW_OP_breg23:
        case DW_OP_breg24:
        case DW_OP_breg24:
        case DW_OP_breg25:
        case DW_OP_breg25:
        case DW_OP_breg26:
        case DW_OP_breg26:
        case DW_OP_breg27:
        case DW_OP_breg27:
        case DW_OP_breg28:
        case DW_OP_breg28:
        case DW_OP_breg29:
        case DW_OP_breg29:
        case DW_OP_breg30:
        case DW_OP_breg30:
        case DW_OP_breg31:
        case DW_OP_breg31:
          offreg = 1;
          offreg = 1;
          basereg = op - DW_OP_breg0;
          basereg = op - DW_OP_breg0;
          stack[++stacki] = read_signed_leb128 (NULL, (data + i), &bytes_read);
          stack[++stacki] = read_signed_leb128 (NULL, (data + i), &bytes_read);
          i += bytes_read;
          i += bytes_read;
          break;
          break;
 
 
        case DW_OP_bregx:
        case DW_OP_bregx:
          offreg = 1;
          offreg = 1;
          basereg = read_unsigned_leb128 (NULL, (data + i), &bytes_read);
          basereg = read_unsigned_leb128 (NULL, (data + i), &bytes_read);
          i += bytes_read;
          i += bytes_read;
          stack[++stacki] = read_signed_leb128 (NULL, (data + i), &bytes_read);
          stack[++stacki] = read_signed_leb128 (NULL, (data + i), &bytes_read);
          i += bytes_read;
          i += bytes_read;
          break;
          break;
 
 
        case DW_OP_fbreg:
        case DW_OP_fbreg:
          stack[++stacki] = read_signed_leb128 (NULL, (data + i), &bytes_read);
          stack[++stacki] = read_signed_leb128 (NULL, (data + i), &bytes_read);
          i += bytes_read;
          i += bytes_read;
          if (frame_base_reg >= 0)
          if (frame_base_reg >= 0)
            {
            {
              offreg = 1;
              offreg = 1;
              basereg = frame_base_reg;
              basereg = frame_base_reg;
              stack[stacki] += frame_base_offset;
              stack[stacki] += frame_base_offset;
            }
            }
          else
          else
            {
            {
              complain (&dwarf2_missing_at_frame_base);
              complain (&dwarf2_missing_at_frame_base);
              islocal = 1;
              islocal = 1;
            }
            }
          break;
          break;
 
 
        case DW_OP_addr:
        case DW_OP_addr:
          stack[++stacki] = read_address (objfile->obfd, &data[i]);
          stack[++stacki] = read_address (objfile->obfd, &data[i]);
          i += address_size;
          i += address_size;
          break;
          break;
 
 
        case DW_OP_const1u:
        case DW_OP_const1u:
          stack[++stacki] = read_1_byte (objfile->obfd, &data[i]);
          stack[++stacki] = read_1_byte (objfile->obfd, &data[i]);
          i += 1;
          i += 1;
          break;
          break;
 
 
        case DW_OP_const1s:
        case DW_OP_const1s:
          stack[++stacki] = read_1_signed_byte (objfile->obfd, &data[i]);
          stack[++stacki] = read_1_signed_byte (objfile->obfd, &data[i]);
          i += 1;
          i += 1;
          break;
          break;
 
 
        case DW_OP_const2u:
        case DW_OP_const2u:
          stack[++stacki] = read_2_bytes (objfile->obfd, &data[i]);
          stack[++stacki] = read_2_bytes (objfile->obfd, &data[i]);
          i += 2;
          i += 2;
          break;
          break;
 
 
        case DW_OP_const2s:
        case DW_OP_const2s:
          stack[++stacki] = read_2_signed_bytes (objfile->obfd, &data[i]);
          stack[++stacki] = read_2_signed_bytes (objfile->obfd, &data[i]);
          i += 2;
          i += 2;
          break;
          break;
 
 
        case DW_OP_const4u:
        case DW_OP_const4u:
          stack[++stacki] = read_4_bytes (objfile->obfd, &data[i]);
          stack[++stacki] = read_4_bytes (objfile->obfd, &data[i]);
          i += 4;
          i += 4;
          break;
          break;
 
 
        case DW_OP_const4s:
        case DW_OP_const4s:
          stack[++stacki] = read_4_signed_bytes (objfile->obfd, &data[i]);
          stack[++stacki] = read_4_signed_bytes (objfile->obfd, &data[i]);
          i += 4;
          i += 4;
          break;
          break;
 
 
        case DW_OP_constu:
        case DW_OP_constu:
          stack[++stacki] = read_unsigned_leb128 (NULL, (data + i),
          stack[++stacki] = read_unsigned_leb128 (NULL, (data + i),
                                                  &bytes_read);
                                                  &bytes_read);
          i += bytes_read;
          i += bytes_read;
          break;
          break;
 
 
        case DW_OP_consts:
        case DW_OP_consts:
          stack[++stacki] = read_signed_leb128 (NULL, (data + i), &bytes_read);
          stack[++stacki] = read_signed_leb128 (NULL, (data + i), &bytes_read);
          i += bytes_read;
          i += bytes_read;
          break;
          break;
 
 
        case DW_OP_plus:
        case DW_OP_plus:
          stack[stacki - 1] += stack[stacki];
          stack[stacki - 1] += stack[stacki];
          stacki--;
          stacki--;
          break;
          break;
 
 
        case DW_OP_plus_uconst:
        case DW_OP_plus_uconst:
          stack[stacki] += read_unsigned_leb128 (NULL, (data + i), &bytes_read);
          stack[stacki] += read_unsigned_leb128 (NULL, (data + i), &bytes_read);
          i += bytes_read;
          i += bytes_read;
          break;
          break;
 
 
        case DW_OP_minus:
        case DW_OP_minus:
          stack[stacki - 1] = stack[stacki] - stack[stacki - 1];
          stack[stacki - 1] = stack[stacki] - stack[stacki - 1];
          stacki--;
          stacki--;
          break;
          break;
 
 
        case DW_OP_deref:
        case DW_OP_deref:
          isderef = 1;
          isderef = 1;
          /* If we're not the last op, then we definitely can't encode
          /* If we're not the last op, then we definitely can't encode
             this using GDB's address_class enum.  */
             this using GDB's address_class enum.  */
          if (i < size)
          if (i < size)
            complain (&dwarf2_complex_location_expr);
            complain (&dwarf2_complex_location_expr);
          break;
          break;
 
 
        default:
        default:
          complain (&dwarf2_unsupported_stack_op, dwarf_stack_op_name (op));
          complain (&dwarf2_unsupported_stack_op, dwarf_stack_op_name (op));
          return (stack[stacki]);
          return (stack[stacki]);
        }
        }
    }
    }
  return (stack[stacki]);
  return (stack[stacki]);
}
}
 
 
/* memory allocation interface */
/* memory allocation interface */
 
 
/* ARGSUSED */
/* ARGSUSED */
static void
static void
dwarf2_free_tmp_obstack (ignore)
dwarf2_free_tmp_obstack (ignore)
     PTR ignore;
     PTR ignore;
{
{
  obstack_free (&dwarf2_tmp_obstack, NULL);
  obstack_free (&dwarf2_tmp_obstack, NULL);
}
}
 
 
static struct dwarf_block *
static struct dwarf_block *
dwarf_alloc_block ()
dwarf_alloc_block ()
{
{
  struct dwarf_block *blk;
  struct dwarf_block *blk;
 
 
  blk = (struct dwarf_block *)
  blk = (struct dwarf_block *)
    obstack_alloc (&dwarf2_tmp_obstack, sizeof (struct dwarf_block));
    obstack_alloc (&dwarf2_tmp_obstack, sizeof (struct dwarf_block));
  return (blk);
  return (blk);
}
}
 
 
static struct abbrev_info *
static struct abbrev_info *
dwarf_alloc_abbrev ()
dwarf_alloc_abbrev ()
{
{
  struct abbrev_info *abbrev;
  struct abbrev_info *abbrev;
 
 
  abbrev = (struct abbrev_info *) xmalloc (sizeof (struct abbrev_info));
  abbrev = (struct abbrev_info *) xmalloc (sizeof (struct abbrev_info));
  memset (abbrev, 0, sizeof (struct abbrev_info));
  memset (abbrev, 0, sizeof (struct abbrev_info));
  return (abbrev);
  return (abbrev);
}
}
 
 
static struct die_info *
static struct die_info *
dwarf_alloc_die ()
dwarf_alloc_die ()
{
{
  struct die_info *die;
  struct die_info *die;
 
 
  die = (struct die_info *) xmalloc (sizeof (struct die_info));
  die = (struct die_info *) xmalloc (sizeof (struct die_info));
  memset (die, 0, sizeof (struct die_info));
  memset (die, 0, sizeof (struct die_info));
  return (die);
  return (die);
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.