/* DWARF 2 debugging format support for GDB.
- Copyright 1994, 1995, 1996 Free Software Foundation, Inc.
+ Copyright 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology,
Inc. with support from Florida State University (under contract
based on Fred Fish's (Cygnus Support) implementation of DWARF 1
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
-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
-your option) any later version.
+ 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
+ the Free Software Foundation; either version 2 of the License, or (at
+ your option) any later version.
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "bfd.h"
#include "buildsym.h"
#include "demangle.h"
#include "expression.h"
+
#include "language.h"
#include "complaints.h"
-
+#include "bcache.h"
#include <fcntl.h>
#include "gdb_string.h"
#include <sys/types.h>
-/* .debug_info header for a compilation unit
+#ifndef DWARF2_REG_TO_REGNUM
+#define DWARF2_REG_TO_REGNUM(REG) (REG)
+#endif
+
+#if 0
+/* .debug_info header for a compilation unit
Because of alignment constraints, this structure has padding and cannot
be mapped directly onto the beginning of the .debug_info section. */
typedef struct comp_unit_header
}
_COMP_UNIT_HEADER;
#define _ACTUAL_COMP_UNIT_HEADER_SIZE 11
+#endif
/* .debug_pubnames header
Because of alignment constraints, this structure has padding and cannot
#define MACINFO_SECTION ".debug_macinfo"
#define STR_SECTION ".debug_str"
-/* Get at parts of an attribute structure */
-
-#define DW_STRING(attr) ((attr)->u.str)
-#define DW_UNSND(attr) ((attr)->u.unsnd)
-#define DW_BLOCK(attr) ((attr)->u.blk)
-#define DW_SND(attr) ((attr)->u.snd)
-#define DW_ADDR(attr) ((attr)->u.addr)
-
/* local data types */
-/* The data in a compilation unit header looks like this. */
+/* The data in a compilation unit header, after target2host
+ translation, looks like this. */
struct comp_unit_head
{
- int length;
+ unsigned long length;
short version;
- int abbrev_offset;
+ unsigned int abbrev_offset;
unsigned char addr_size;
+ unsigned char signed_addr_p;
+ unsigned int offset_size; /* size of file offsets; either 4 or 8 */
+ unsigned int initial_length_size; /* size of the length field; either
+ 4 or 12 */
};
/* The data in the .debug_line statement prologue looks like this. */
need this much information. */
struct partial_die_info
{
- unsigned short tag;
+ enum dwarf_tag tag;
unsigned char has_children;
unsigned char is_external;
unsigned char is_declaration;
+ unsigned char has_type;
unsigned int offset;
unsigned int abbrev;
char *name;
CORE_ADDR highpc;
struct dwarf_block *locdesc;
unsigned int language;
- int value;
+ char *sibling;
};
/* This data structure holds the information of an abbrev. */
struct abbrev_info
{
unsigned int number; /* number identifying abbrev */
- unsigned int tag; /* dwarf tag */
+ enum dwarf_tag tag; /* dwarf tag */
int has_children; /* boolean */
unsigned int num_attrs; /* number of attributes */
struct attr_abbrev *attrs; /* an array of attribute descriptions */
struct attr_abbrev
{
- unsigned int name;
- unsigned int form;
+ enum dwarf_attribute name;
+ enum dwarf_form form;
};
/* This data structure holds a complete die structure. */
struct die_info
{
- unsigned short tag; /* Tag indicating type of die */
- unsigned short has_children; /* Does the die have children */
- unsigned int abbrev; /* Abbrev number */
- unsigned int offset; /* Offset in .debug_info section */
- unsigned int num_attrs; /* Number of attributes */
- struct attribute *attrs; /* An array of attributes */
- struct die_info *next_ref; /* Next die in ref hash table */
- struct die_info *next; /* Next die in linked list */
- struct type *type; /* Cached type information */
+ enum dwarf_tag tag; /* Tag indicating type of die */
+ unsigned short has_children; /* Does the die have children */
+ unsigned int abbrev; /* Abbrev number */
+ unsigned int offset; /* Offset in .debug_info section */
+ unsigned int num_attrs; /* Number of attributes */
+ struct attribute *attrs; /* An array of attributes */
+ struct die_info *next_ref; /* Next die in ref hash table */
+ struct die_info *next; /* Next die in linked list */
+ struct type *type; /* Cached type information */
};
/* Attributes have a name and a value */
struct attribute
{
- unsigned short name;
- unsigned short form;
+ enum dwarf_attribute name;
+ enum dwarf_form form;
union
{
char *str;
struct dwarf_block *blk;
- unsigned int unsnd;
- int snd;
+ unsigned long unsnd;
+ long int snd;
CORE_ADDR addr;
}
u;
};
+/* Get at parts of an attribute structure */
+
+#define DW_STRING(attr) ((attr)->u.str)
+#define DW_UNSND(attr) ((attr)->u.unsnd)
+#define DW_BLOCK(attr) ((attr)->u.blk)
+#define DW_SND(attr) ((attr)->u.snd)
+#define DW_ADDR(attr) ((attr)->u.addr)
+
/* Blocks are a bunch of untyped bytes. */
struct dwarf_block
{
in buildsym.c. */
static struct pending **list_in_scope = &file_symbols;
-/* FIXME: The following variables pass additional information from
- decode_locdesc to the caller. */
-static int optimized_out; /* Kludge to identify optimized out variables */
-static int isreg; /* Kludge to identify register variables */
-static int offreg; /* Kludge to identify basereg references */
-static int basereg; /* Which base register is it relative to? */
-static int islocal; /* Kludge to identify local variables */
+/* FIXME: decode_locdesc sets these variables to describe the location
+ 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
+ by decode_locdesc. */
+
+static int optimized_out; /* No ops in location in expression,
+ so object was optimized out. */
+static int isreg; /* Object lives in register.
+ decode_locdesc's return value is
+ the register number. */
+static int offreg; /* Object's address is the sum of the
+ register specified by basereg, plus
+ the offset returned. */
+static int basereg; /* See `offreg'. */
+static int isderef; /* Value described by flags above is
+ the address of a pointer to the object. */
+static int islocal; /* Variable is at the returned offset
+ from the frame start, but there's
+ no identified frame pointer for
+ this function, so we can't say
+ which register it's relative to;
+ use LOC_LOCAL. */
/* DW_AT_frame_base values for the current function.
frame_base_reg is -1 if DW_AT_frame_base is missing, otherwise it
static int frame_base_reg;
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,
pass the appropriate section number to end_symtab). */
static CORE_ADDR baseaddr; /* Add to each symbol value */
of symbols read from an object file. */
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 DWARF_INFO_BUFFER(p) (PST_PRIVATE(p)->dwarf_info_buffer)
fundamental types gdb knows how to construct. */
static struct type *ftypes[FT_NUM_MEMBERS]; /* Fundamental types */
-/* FIXME - set from bfd function */
+/* 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
+ and friends. */
static int bits_per_byte = 8;
+/* 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
+ in an instance of a field_info structure, as defined below. */
+struct field_info
+ {
+ /* List of data member and baseclasses fields. */
+ struct nextfield
+ {
+ struct nextfield *next;
+ int accessibility;
+ int virtuality;
+ struct field field;
+ }
+ *fields;
+
+ /* Number of fields. */
+ int nfields;
+
+ /* Number of baseclasses. */
+ int nbaseclasses;
+
+ /* Set if the accesibility of one of the fields is not public. */
+ int non_public_fields;
+
+ /* Member function fields array, entries are allocated in the order they
+ are encountered in the object file. */
+ struct nextfnfield
+ {
+ struct nextfnfield *next;
+ struct fn_field fnfield;
+ }
+ *fnfields;
+
+ /* Member function fieldlist array, contains name of possibly overloaded
+ member function, number of overloaded member functions and a pointer
+ to the head of the member function field chain. */
+ struct fnfieldlist
+ {
+ char *name;
+ int length;
+ struct nextfnfield *head;
+ }
+ *fnfieldlists;
+
+ /* Number of entries in the fnfieldlists array. */
+ int nfnfields;
+ };
+
+/* FIXME: Kludge to mark a varargs function type for C++ member function
+ argument processing. */
+#define TYPE_FLAG_VARARGS (1 << 10)
+
+/* 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
+ member functions (which is the this pointer) as artificial.
+ We pass this information between dwarf2_add_member_fn and
+ read_subroutine_type via TYPE_FIELD_ARTIFICIAL. */
+#define TYPE_FIELD_ARTIFICIAL TYPE_FIELD_BITPOS
+
/* Various complaints about symbol reading that don't abort the process */
static struct complaint dwarf2_const_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_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 =
{
"unsupported stack op: '%s'", 0, 0
};
+static struct complaint dwarf2_complex_location_expr =
+{
+ "location expression too complex", 0, 0
+};
static struct complaint dwarf2_unsupported_tag =
{
"unsupported tag: '%s'", 0, 0
{
"unsupported DW_AT_frame_base for function '%s'", 0, 0
};
+static struct complaint dwarf2_unexpected_tag =
+{
+ "unexepected tag in read_type_die: '%s'", 0, 0
+};
static struct complaint dwarf2_missing_at_frame_base =
{
"DW_AT_frame_base missing for DW_OP_fbreg", 0, 0
};
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 =
+{
+ "unsupported accessibility %d", 0, 0
+};
+static struct complaint dwarf2_bad_member_name_complaint =
+{
+ "cannot extract member name from '%s'", 0, 0
+};
+static struct complaint dwarf2_missing_member_fn_type_complaint =
+{
+ "member function type missing for '%s'", 0, 0
+};
+static struct complaint dwarf2_vtbl_not_found_complaint =
+{
+ "virtual function table pointer not found when defining class '%s'", 0, 0
+};
+static struct complaint dwarf2_absolute_sibling_complaint =
+{
+ "ignoring absolute DW_AT_sibling", 0, 0
+};
+static struct complaint dwarf2_const_value_length_mismatch =
+{
+ "const value length mismatch for '%s', got %d, expected %d", 0, 0
+};
+static struct complaint dwarf2_unsupported_const_value_attr =
+{
+ "unsupported const value attribute form: '%s'", 0, 0
};
-
-/* Remember the addr_size read from the dwarf.
- If a target expects to link compilation units with differing address
- sizes, gdb needs to be sure that the appropriate size is here for
- whatever scope is currently getting read. */
-static int address_size;
/* Externals references. */
extern int info_verbose; /* From main.c; nonzero => verbose */
/* local function prototypes */
-static void dwarf2_locate_sections PARAMS ((bfd *, asection *, PTR));
+static void dwarf2_locate_sections (bfd *, asection *, PTR);
#if 0
-static void dwarf2_build_psymtabs_easy PARAMS ((struct objfile *,
- struct section_offsets *,
- int));
+static void dwarf2_build_psymtabs_easy (struct objfile *, int);
#endif
-static void dwarf2_build_psymtabs_hard PARAMS ((struct objfile *,
- struct section_offsets *,
- int));
+static void dwarf2_build_psymtabs_hard (struct objfile *, int);
+
+static char *scan_partial_symbols (char *, struct objfile *,
+ CORE_ADDR *, CORE_ADDR *,
+ const struct comp_unit_head *);
-static char *scan_partial_symbols PARAMS ((char *, struct objfile *,
- CORE_ADDR *, CORE_ADDR *));
+static void add_partial_symbol (struct partial_die_info *, struct objfile *,
+ const struct comp_unit_head *);
-static void add_partial_symbol PARAMS ((struct partial_die_info *,
- struct objfile *));
+static void dwarf2_psymtab_to_symtab (struct partial_symtab *);
-static void dwarf2_psymtab_to_symtab PARAMS ((struct partial_symtab *));
+static void psymtab_to_symtab_1 (struct partial_symtab *);
-static void psymtab_to_symtab_1 PARAMS ((struct partial_symtab *));
+static char *dwarf2_read_section (struct objfile *, file_ptr, unsigned int);
-static char *dwarf2_read_section PARAMS ((struct objfile *, file_ptr,
- unsigned int));
+static void dwarf2_read_abbrevs (bfd *, unsigned int);
-static void dwarf2_read_abbrevs PARAMS ((bfd *, unsigned int));
+static void dwarf2_empty_abbrev_table (PTR);
-static void dwarf2_empty_abbrev_table PARAMS ((PTR));
+static struct abbrev_info *dwarf2_lookup_abbrev (unsigned int);
-static struct abbrev_info *dwarf2_lookup_abbrev PARAMS ((unsigned int));
+static char *read_partial_die (struct partial_die_info *,
+ bfd *, char *, int *,
+ const struct comp_unit_head *);
-static char *read_partial_die PARAMS ((struct partial_die_info *,
- bfd *, char *, int *));
+static char *read_full_die (struct die_info **, bfd *, char *,
+ const struct comp_unit_head *);
-static char *read_full_die PARAMS ((struct die_info **, bfd *, char *));
+static char *read_attribute (struct attribute *, struct attr_abbrev *,
+ bfd *, char *, const struct comp_unit_head *);
-static unsigned int read_1_byte PARAMS ((bfd *, char *));
+static unsigned int read_1_byte (bfd *, char *);
-static int read_1_signed_byte PARAMS ((bfd *, char *));
+static int read_1_signed_byte (bfd *, char *);
-static unsigned int read_2_bytes PARAMS ((bfd *, char *));
+static unsigned int read_2_bytes (bfd *, char *);
-static unsigned int read_4_bytes PARAMS ((bfd *, char *));
+static unsigned int read_4_bytes (bfd *, char *);
-static unsigned int read_8_bytes PARAMS ((bfd *, char *));
+static unsigned long read_8_bytes (bfd *, char *);
-static CORE_ADDR read_address PARAMS ((bfd *, char *));
+static CORE_ADDR read_address (bfd *, char *ptr, const struct comp_unit_head *,
+ int *bytes_read);
-static char *read_n_bytes PARAMS ((bfd *, char *, unsigned int));
+static LONGEST read_initial_length (bfd *, char *,
+ struct comp_unit_head *, int *bytes_read);
-static char *read_string PARAMS ((bfd *, char *, unsigned int *));
+static LONGEST read_offset (bfd *, char *, const struct comp_unit_head *,
+ int *bytes_read);
-static unsigned int read_unsigned_leb128 PARAMS ((bfd *, char *,
- unsigned int *));
+static char *read_n_bytes (bfd *, char *, unsigned int);
-static int read_signed_leb128 PARAMS ((bfd *, char *, unsigned int *));
+static char *read_string (bfd *, char *, unsigned int *);
-static void set_cu_language PARAMS ((unsigned int));
+static unsigned long read_unsigned_leb128 (bfd *, char *, unsigned int *);
-static struct attribute *dwarf_attr PARAMS ((struct die_info *,
- unsigned int));
+static long read_signed_leb128 (bfd *, char *, unsigned int *);
-static void dwarf_decode_lines PARAMS ((unsigned int, char *, bfd *));
+static void set_cu_language (unsigned int);
-static void dwarf2_start_subfile PARAMS ((char *, char *));
+static struct attribute *dwarf_attr (struct die_info *, unsigned int);
-static struct symbol *new_symbol PARAMS ((struct die_info *, struct type *,
- struct objfile *));
+static int die_is_declaration (struct die_info *);
-static struct type *die_type PARAMS ((struct die_info *, struct objfile *));
+static void dwarf_decode_lines (unsigned int, char *, bfd *,
+ const struct comp_unit_head *);
-static struct type *die_containing_type PARAMS ((struct die_info *,
- struct objfile *));
+static void dwarf2_start_subfile (char *, char *);
+
+static struct symbol *new_symbol (struct die_info *, struct type *,
+ struct objfile *, const struct comp_unit_head *);
+
+static void dwarf2_const_value (struct attribute *, struct symbol *,
+ struct objfile *, const struct comp_unit_head *);
+
+static void dwarf2_const_value_data (struct attribute *attr,
+ struct symbol *sym,
+ int bits);
+
+static struct type *die_type (struct die_info *, struct objfile *,
+ const struct comp_unit_head *);
+
+static struct type *die_containing_type (struct die_info *, struct objfile *,
+ const struct comp_unit_head *);
#if 0
-static struct type *type_at_offset PARAMS ((unsigned int, struct objfile *));
+static struct type *type_at_offset (unsigned int, struct objfile *);
#endif
-static struct type *tag_type_to_type PARAMS ((struct die_info *,
- struct objfile *));
+static struct type *tag_type_to_type (struct die_info *, struct objfile *,
+ const struct comp_unit_head *);
+
+static void read_type_die (struct die_info *, struct objfile *,
+ const struct comp_unit_head *);
+
+static void read_typedef (struct die_info *, struct objfile *,
+ const struct comp_unit_head *);
+
+static void read_base_type (struct die_info *, struct objfile *);
-static void read_type_die PARAMS ((struct die_info *, struct objfile *));
+static void read_file_scope (struct die_info *, struct objfile *,
+ const struct comp_unit_head *);
-static void read_typedef PARAMS ((struct die_info *, struct objfile *));
+static void read_func_scope (struct die_info *, struct objfile *,
+ const struct comp_unit_head *);
-static void read_base_type PARAMS ((struct die_info *, struct objfile *));
+static void read_lexical_block_scope (struct die_info *, struct objfile *,
+ const struct comp_unit_head *);
-static void read_file_scope PARAMS ((struct die_info *, struct objfile *));
+static int dwarf2_get_pc_bounds (struct die_info *,
+ CORE_ADDR *, CORE_ADDR *, struct objfile *);
-static void read_func_scope PARAMS ((struct die_info *, struct objfile *));
+static void dwarf2_add_field (struct field_info *, struct die_info *,
+ struct objfile *, const struct comp_unit_head *);
-static void read_lexical_block_scope PARAMS ((struct die_info *,
- struct objfile *));
+static void dwarf2_attach_fields_to_type (struct field_info *,
+ struct type *, struct objfile *);
-static void read_structure_scope PARAMS ((struct die_info *, struct objfile *));
+static void dwarf2_add_member_fn (struct field_info *,
+ struct die_info *, struct type *,
+ struct objfile *objfile,
+ const struct comp_unit_head *);
-static void read_common_block PARAMS ((struct die_info *, struct objfile *));
+static void dwarf2_attach_fn_fields_to_type (struct field_info *,
+ struct type *, struct objfile *);
-static void read_enumeration PARAMS ((struct die_info *, struct objfile *));
+static void read_structure_scope (struct die_info *, struct objfile *,
+ const struct comp_unit_head *);
-static struct type * dwarf_base_type PARAMS ((int, int));
+static void read_common_block (struct die_info *, struct objfile *,
+ const struct comp_unit_head *);
-static CORE_ADDR decode_locdesc PARAMS ((struct dwarf_block *,
- struct objfile *));
+static void read_enumeration (struct die_info *, struct objfile *,
+ const struct comp_unit_head *);
-static void dwarf_read_array_type PARAMS ((struct die_info *,
- struct objfile *));
+static struct type *dwarf_base_type (int, int, struct objfile *);
-static void read_tag_pointer_type PARAMS ((struct die_info *,
- struct objfile *));
+static CORE_ADDR decode_locdesc (struct dwarf_block *, struct objfile *,
+ const struct comp_unit_head *);
-static void read_tag_ptr_to_member_type PARAMS ((struct die_info *,
- struct objfile *));
+static void read_array_type (struct die_info *, struct objfile *,
+ const struct comp_unit_head *);
-static void read_tag_reference_type PARAMS ((struct die_info *,
- struct objfile *));
+static void read_tag_pointer_type (struct die_info *, struct objfile *,
+ const struct comp_unit_head *);
-static void read_tag_const_type PARAMS ((struct die_info *, struct objfile *));
+static void read_tag_ptr_to_member_type (struct die_info *, struct objfile *,
+ const struct comp_unit_head *);
-static void read_tag_volatile_type PARAMS ((struct die_info *,
- struct objfile *));
+static void read_tag_reference_type (struct die_info *, struct objfile *,
+ const struct comp_unit_head *);
-static void read_tag_string_type PARAMS ((struct die_info *,
- struct objfile *));
+static void read_tag_const_type (struct die_info *, struct objfile *,
+ const struct comp_unit_head *);
-static void read_subroutine_type PARAMS ((struct die_info *,
- struct objfile *));
+static void read_tag_volatile_type (struct die_info *, struct objfile *,
+ const struct comp_unit_head *);
-struct die_info *read_comp_unit PARAMS ((char *, bfd *));
+static void read_tag_string_type (struct die_info *, struct objfile *);
-static void free_die_list PARAMS ((struct die_info *));
+static void read_subroutine_type (struct die_info *, struct objfile *,
+ const struct comp_unit_head *);
-static void process_die PARAMS ((struct die_info *, struct objfile *));
+struct die_info *read_comp_unit (char *, bfd *, const struct comp_unit_head *);
-static char *dwarf_tag_name PARAMS ((unsigned int));
+static void free_die_list (struct die_info *);
-static char *dwarf_attr_name PARAMS ((unsigned int));
+static struct cleanup *make_cleanup_free_die_list (struct die_info *);
-static char *dwarf_form_name PARAMS ((unsigned int));
+static void process_die (struct die_info *, struct objfile *,
+ const struct comp_unit_head *);
-static char *dwarf_stack_op_name PARAMS ((unsigned int));
+static char *dwarf2_linkage_name (struct die_info *);
-static char *dwarf_bool_name PARAMS ((unsigned int));
+static char *dwarf_tag_name (unsigned int);
-static char *dwarf_bool_name PARAMS ((unsigned int));
+static char *dwarf_attr_name (unsigned int);
-static char *dwarf_type_encoding_name PARAMS ((unsigned int));
+static char *dwarf_form_name (unsigned int);
+
+static char *dwarf_stack_op_name (unsigned int);
+
+static char *dwarf_bool_name (unsigned int);
+
+static char *dwarf_type_encoding_name (unsigned int);
#if 0
-static char *dwarf_cfi_name PARAMS ((unsigned int));
+static char *dwarf_cfi_name (unsigned int);
-struct die_info *copy_die PARAMS ((struct die_info *));
+struct die_info *copy_die (struct die_info *);
#endif
-struct die_info *sibling_die PARAMS ((struct die_info *));
+struct die_info *sibling_die (struct die_info *);
-void dump_die PARAMS ((struct die_info *));
+void dump_die (struct die_info *);
-void dump_die_list PARAMS ((struct die_info *));
+void dump_die_list (struct die_info *);
-void store_in_ref_table PARAMS ((unsigned int, struct die_info *));
+void store_in_ref_table (unsigned int, struct die_info *);
-static void dwarf2_empty_die_ref_table PARAMS ((void));
+static void dwarf2_empty_hash_tables (void);
-static unsigned int dwarf2_get_ref_die_offset PARAMS ((struct attribute *));
+static unsigned int dwarf2_get_ref_die_offset (struct attribute *);
-struct die_info *follow_die_ref PARAMS ((unsigned int));
+struct die_info *follow_die_ref (unsigned int);
-static struct type *dwarf2_fundamental_type PARAMS ((struct objfile *, int));
+static struct type *dwarf2_fundamental_type (struct objfile *, int);
/* memory allocation interface */
-static void dwarf2_free_tmp_obstack PARAMS ((PTR));
+static void dwarf2_free_tmp_obstack (PTR);
-static struct dwarf_block *dwarf_alloc_block PARAMS ((void));
+static struct dwarf_block *dwarf_alloc_block (void);
-static struct abbrev_info *dwarf_alloc_abbrev PARAMS ((void));
+static struct abbrev_info *dwarf_alloc_abbrev (void);
-static struct die_info *dwarf_alloc_die PARAMS ((void));
+static struct die_info *dwarf_alloc_die (void);
/* Try to locate the sections we need for DWARF 2 debugging
information and return true if we have enough to do something. */
int
-dwarf2_has_info (abfd)
- bfd *abfd;
+dwarf2_has_info (bfd *abfd)
{
dwarf_info_offset = dwarf_abbrev_offset = dwarf_line_offset = 0;
bfd_map_over_sections (abfd, dwarf2_locate_sections, NULL);
in. */
static void
-dwarf2_locate_sections (ignore_abfd, sectp, ignore_ptr)
- bfd *ignore_abfd;
- asection *sectp;
- PTR ignore_ptr;
+dwarf2_locate_sections (bfd *ignore_abfd, asection *sectp, PTR ignore_ptr)
{
if (STREQ (sectp->name, INFO_SECTION))
{
/* Build a partial symbol table. */
void
-dwarf2_build_psymtabs (objfile, section_offsets, mainline)
- struct objfile *objfile;
- struct section_offsets *section_offsets;
- int mainline;
+dwarf2_build_psymtabs (struct objfile *objfile, int mainline)
{
/* We definitely need the .debug_info and .debug_abbrev sections */
#if 0
if (dwarf_aranges_offset && dwarf_pubnames_offset)
{
- /* Things are significanlty easier if we have .debug_aranges and
+ /* Things are significantly easier if we have .debug_aranges and
.debug_pubnames sections */
- dwarf2_build_psymtabs_easy (objfile, section_offsets, mainline);
+ dwarf2_build_psymtabs_easy (objfile, mainline);
}
else
#endif
/* only test this case for now */
- {
+ {
/* In this case we have to work a bit harder */
- dwarf2_build_psymtabs_hard (objfile, section_offsets, mainline);
+ dwarf2_build_psymtabs_hard (objfile, mainline);
}
}
.debug_pubnames and .debug_aranges sections. */
static void
-dwarf2_build_psymtabs_easy (objfile, section_offsets, mainline)
- struct objfile *objfile;
- struct section_offsets *section_offsets;
- int mainline;
+dwarf2_build_psymtabs_easy (struct objfile *objfile, int mainline)
{
bfd *abfd = objfile->obfd;
char *aranges_buffer, *pubnames_buffer;
pubnames_ptr = pubnames_buffer;
while ((pubnames_ptr - pubnames_buffer) < dwarf_pubnames_size)
{
- entry_length = read_4_bytes (abfd, pubnames_ptr);
- pubnames_ptr += 4;
+ struct comp_unit_head cu_header;
+ int bytes_read;
+
+ entry_length = read_initial_length (abfd, pubnames_ptr, &cu_header,
+ &bytes_read);
+ pubnames_ptr += bytes_read;
version = read_1_byte (abfd, pubnames_ptr);
pubnames_ptr += 1;
info_offset = read_4_bytes (abfd, pubnames_ptr);
}
#endif
+/* Read in the comp unit header information from the debug_info at
+ info_ptr. */
+
+static char *
+read_comp_unit_head (struct comp_unit_head *cu_header,
+ char *info_ptr, bfd *abfd)
+{
+ int signed_addr;
+ int bytes_read;
+ cu_header->length = read_initial_length (abfd, info_ptr, cu_header,
+ &bytes_read);
+ info_ptr += bytes_read;
+ cu_header->version = read_2_bytes (abfd, info_ptr);
+ info_ptr += 2;
+ cu_header->abbrev_offset = read_offset (abfd, info_ptr, cu_header,
+ &bytes_read);
+ info_ptr += bytes_read;
+ cu_header->addr_size = read_1_byte (abfd, info_ptr);
+ info_ptr += 1;
+ signed_addr = bfd_get_sign_extend_vma (abfd);
+ if (signed_addr < 0)
+ internal_error ("read_comp_unit_head: dwarf from non elf file");
+ cu_header->signed_addr_p = signed_addr;
+ return info_ptr;
+}
+
/* Build the partial symbol table by doing a quick pass through the
.debug_info and .debug_abbrev sections. */
static void
-dwarf2_build_psymtabs_hard (objfile, section_offsets, mainline)
- struct objfile *objfile;
- struct section_offsets *section_offsets;
- int mainline;
+dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline)
{
/* Instead of reading this into a big buffer, we should probably use
mmap() on architectures that support it. (FIXME) */
bfd *abfd = objfile->obfd;
char *info_ptr, *abbrev_ptr;
char *beg_of_comp_unit;
- struct comp_unit_head cu_header;
struct partial_die_info comp_unit_die;
struct partial_symtab *pst;
struct cleanup *back_to;
back_to = make_cleanup (dwarf2_free_tmp_obstack, NULL);
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)
{
+ struct comp_unit_head cu_header;
beg_of_comp_unit = info_ptr;
- cu_header.length = read_4_bytes (abfd, info_ptr);
- info_ptr += 4;
- cu_header.version = read_2_bytes (abfd, info_ptr);
- info_ptr += 2;
- cu_header.abbrev_offset = read_4_bytes (abfd, info_ptr);
- info_ptr += 4;
- cu_header.addr_size = read_1_byte (abfd, info_ptr);
- info_ptr += 1;
- address_size = cu_header.addr_size;
+ info_ptr = read_comp_unit_head (&cu_header, info_ptr, abfd);
if (cu_header.version != 2)
{
error ("Dwarf Error: wrong version in compilation unit header.");
return;
}
-
+ if (cu_header.abbrev_offset >= dwarf_abbrev_size)
+ {
+ error ("Dwarf Error: bad offset (0x%lx) in compilation unit header (offset 0x%lx + 6).",
+ (long) cu_header.abbrev_offset,
+ (long) (beg_of_comp_unit - dwarf_info_buffer));
+ return;
+ }
+ if (beg_of_comp_unit + cu_header.length + cu_header.initial_length_size
+ > dwarf_info_buffer + dwarf_info_size)
+ {
+ error ("Dwarf Error: bad length (0x%lx) in compilation unit header (offset 0x%lx + 0).",
+ (long) cu_header.length,
+ (long) (beg_of_comp_unit - dwarf_info_buffer));
+ return;
+ }
/* Read the abbrevs for this compilation unit into a table */
dwarf2_read_abbrevs (abfd, cu_header.abbrev_offset);
make_cleanup (dwarf2_empty_abbrev_table, NULL);
/* Read the compilation unit die */
- info_ptr = read_partial_die (&comp_unit_die, abfd,
- info_ptr, &comp_unit_has_pc_info);
+ info_ptr = read_partial_die (&comp_unit_die, abfd, info_ptr,
+ &comp_unit_has_pc_info, &cu_header);
/* Set the language we're debugging */
set_cu_language (comp_unit_die.language);
/* Allocate a new partial symbol table structure */
- pst = start_psymtab_common (objfile, section_offsets,
- comp_unit_die.name,
+ pst = start_psymtab_common (objfile, objfile->section_offsets,
+ comp_unit_die.name ? comp_unit_die.name : "",
comp_unit_die.lowpc,
objfile->global_psymbols.next,
objfile->static_psymbols.next);
pst->read_symtab_private = (char *)
obstack_alloc (&objfile->psymbol_obstack, sizeof (struct dwarf2_pinfo));
- DWARF_INFO_BUFFER(pst) = dwarf_info_buffer;
- DWARF_INFO_OFFSET(pst) = beg_of_comp_unit - dwarf_info_buffer;
- DWARF_ABBREV_BUFFER(pst) = dwarf_abbrev_buffer;
- DWARF_ABBREV_SIZE(pst) = dwarf_abbrev_size;
- DWARF_LINE_BUFFER(pst) = dwarf_line_buffer;
- baseaddr = ANOFFSET (section_offsets, 0);
+ cu_header_offset = beg_of_comp_unit - dwarf_info_buffer;
+ DWARF_INFO_BUFFER (pst) = dwarf_info_buffer;
+ DWARF_INFO_OFFSET (pst) = beg_of_comp_unit - dwarf_info_buffer;
+ DWARF_ABBREV_BUFFER (pst) = dwarf_abbrev_buffer;
+ DWARF_ABBREV_SIZE (pst) = dwarf_abbrev_size;
+ DWARF_LINE_BUFFER (pst) = dwarf_line_buffer;
+ baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
/* Store the function that reads in the rest of the symbol table */
pst->read_symtab = dwarf2_psymtab_to_symtab;
- /* Read the rest of the partial symbols from this comp unit */
- info_ptr = scan_partial_symbols (info_ptr, objfile, &lowpc, &highpc);
-
- /* If the compilation unit didn't have an explicit address range,
- then use the information extracted from its child dies. */
- if (!comp_unit_has_pc_info)
+ /* Check if comp unit has_children.
+ 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 (comp_unit_die.has_children)
{
- comp_unit_die.lowpc = lowpc;
- comp_unit_die.highpc = highpc;
- }
- pst->textlow = comp_unit_die.lowpc + baseaddr;
+ info_ptr = scan_partial_symbols (info_ptr, objfile, &lowpc, &highpc,
+ &cu_header);
+
+ /* If the compilation unit didn't have an explicit address range,
+ then use the information extracted from its child dies. */
+ if (!comp_unit_has_pc_info)
+ {
+ comp_unit_die.lowpc = lowpc;
+ comp_unit_die.highpc = highpc;
+ }
+ }
+ pst->textlow = comp_unit_die.lowpc + baseaddr;
pst->texthigh = comp_unit_die.highpc + baseaddr;
pst->n_global_syms = objfile->global_psymbols.next -
also happen.) This happens in VxWorks. */
free_named_symtabs (pst->filename);
- info_ptr = beg_of_comp_unit + cu_header.length + 4;
+ info_ptr = beg_of_comp_unit + cu_header.length
+ + cu_header.initial_length_size;
}
do_cleanups (back_to);
}
/* Read in all interesting dies to the end of the compilation unit. */
static char *
-scan_partial_symbols (info_ptr, objfile, lowpc, highpc)
- char *info_ptr;
- struct objfile *objfile;
- CORE_ADDR *lowpc;
- CORE_ADDR *highpc;
+scan_partial_symbols (char *info_ptr, struct objfile *objfile,
+ CORE_ADDR *lowpc, CORE_ADDR *highpc,
+ const struct comp_unit_head *cu_header)
{
bfd *abfd = objfile->obfd;
struct partial_die_info pdi;
- int nesting_level = 1; /* we've already read in comp_unit_die */
+
+ /* 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
+ 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
+ back to that level. */
+
+ int nesting_level = 1;
int has_pc_info;
- *lowpc = ((CORE_ADDR) -1);
+ *lowpc = ((CORE_ADDR) -1);
*highpc = ((CORE_ADDR) 0);
- do
+
+ while (nesting_level)
{
- info_ptr = read_partial_die (&pdi, abfd, info_ptr, &has_pc_info);
- switch (pdi.tag)
+ info_ptr = read_partial_die (&pdi, abfd, info_ptr,
+ &has_pc_info, cu_header);
+
+ if (pdi.name)
{
- case DW_TAG_subprogram:
- case DW_TAG_variable:
- case DW_TAG_typedef:
- case DW_TAG_class_type:
- case DW_TAG_structure_type:
- case DW_TAG_union_type:
- case DW_TAG_enumeration_type:
- if (pdi.is_external || nesting_level == 1)
+ switch (pdi.tag)
{
- if (pdi.name && !pdi.is_declaration)
+ case DW_TAG_subprogram:
+ if (has_pc_info)
+ {
+ if (pdi.lowpc < *lowpc)
+ {
+ *lowpc = pdi.lowpc;
+ }
+ if (pdi.highpc > *highpc)
+ {
+ *highpc = pdi.highpc;
+ }
+ if ((pdi.is_external || nesting_level == 1)
+ && !pdi.is_declaration)
+ {
+ add_partial_symbol (&pdi, objfile, cu_header);
+ }
+ }
+ break;
+ case DW_TAG_variable:
+ case DW_TAG_typedef:
+ case DW_TAG_class_type:
+ case DW_TAG_structure_type:
+ case DW_TAG_union_type:
+ case DW_TAG_enumeration_type:
+ if ((pdi.is_external || nesting_level == 1)
+ && !pdi.is_declaration)
{
- add_partial_symbol (&pdi, objfile);
+ add_partial_symbol (&pdi, objfile, cu_header);
}
+ break;
+ case DW_TAG_enumerator:
+ /* File scope enumerators are added to the partial symbol
+ table. */
+ if (nesting_level == 2)
+ add_partial_symbol (&pdi, objfile, cu_header);
+ break;
+ case DW_TAG_base_type:
+ /* File scope base type definitions are added to the partial
+ symbol table. */
+ if (nesting_level == 1)
+ add_partial_symbol (&pdi, objfile, cu_header);
+ break;
+ default:
+ break;
}
- if (has_pc_info)
- {
- if (pdi.lowpc < *lowpc)
- {
- *lowpc = pdi.lowpc;
- }
- if (pdi.highpc > *highpc)
- {
- *highpc = pdi.highpc;
- }
- }
- break;
- case DW_TAG_enumerator:
- /* File scope enumerators are added to the partial symbol table. */
- if (pdi.name && nesting_level == 2)
- add_partial_symbol (&pdi, objfile);
- break;
}
- if (pdi.has_children)
+
+ /* If the die has a sibling, skip to the sibling.
+ Do not skip enumeration types, we want to record their
+ enumerators. */
+ if (pdi.sibling && pdi.tag != DW_TAG_enumeration_type)
+ {
+ info_ptr = pdi.sibling;
+ }
+ else if (pdi.has_children)
{
+ /* Die has children, but the optional DW_AT_sibling attribute
+ is missing. */
nesting_level++;
}
+
if (pdi.tag == 0)
{
nesting_level--;
}
}
- while (nesting_level);
/* 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))
*lowpc = *highpc;
return info_ptr;
}
static void
-add_partial_symbol (pdi, objfile)
- struct partial_die_info *pdi;
- struct objfile *objfile;
+add_partial_symbol (struct partial_die_info *pdi, struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
{
+ CORE_ADDR addr = 0;
+
switch (pdi->tag)
{
case DW_TAG_subprogram:
if (pdi->is_external)
{
- prim_record_minimal_symbol (pdi->name, pdi->lowpc + baseaddr,
- mst_text, objfile);
+ /*prim_record_minimal_symbol (pdi->name, pdi->lowpc + baseaddr,
+ mst_text, objfile); */
add_psymbol_to_list (pdi->name, strlen (pdi->name),
VAR_NAMESPACE, LOC_BLOCK,
&objfile->global_psymbols,
- 0, pdi->lowpc + baseaddr, cu_language, objfile);
+ 0, pdi->lowpc + baseaddr, cu_language, objfile);
}
else
{
- prim_record_minimal_symbol (pdi->name, pdi->lowpc + baseaddr,
- mst_file_text, objfile);
+ /*prim_record_minimal_symbol (pdi->name, pdi->lowpc + baseaddr,
+ mst_file_text, objfile); */
add_psymbol_to_list (pdi->name, strlen (pdi->name),
VAR_NAMESPACE, LOC_BLOCK,
&objfile->static_psymbols,
- 0, pdi->lowpc + baseaddr, cu_language, objfile);
+ 0, pdi->lowpc + baseaddr, cu_language, objfile);
}
break;
case DW_TAG_variable:
- /* Skip symbols without location desciptors, these are external
- references. */
- if (pdi->locdesc == NULL)
- return;
if (pdi->is_external)
{
- prim_record_minimal_symbol (pdi->name,
- decode_locdesc (pdi->locdesc, objfile)
- + baseaddr,
- mst_data, objfile);
- add_psymbol_to_list (pdi->name, strlen (pdi->name),
- VAR_NAMESPACE, LOC_STATIC,
- &objfile->global_psymbols,
- 0, (CORE_ADDR) 0, cu_language, objfile);
+ /* Global Variable.
+ Don't enter into the minimal symbol tables as there is
+ a minimal symbol table entry from the ELF symbols already.
+ Enter into partial symbol table if it has a location
+ descriptor or a type.
+ If the location descriptor is missing, new_symbol will create
+ a LOC_UNRESOLVED symbol, the address of the variable will then
+ be determined from the minimal symbol table whenever the variable
+ is referenced.
+ The address for the partial symbol table entry is not
+ used by GDB, but it comes in handy for debugging partial symbol
+ table building. */
+
+ if (pdi->locdesc)
+ addr = decode_locdesc (pdi->locdesc, objfile, cu_header);
+ if (pdi->locdesc || pdi->has_type)
+ add_psymbol_to_list (pdi->name, strlen (pdi->name),
+ VAR_NAMESPACE, LOC_STATIC,
+ &objfile->global_psymbols,
+ 0, addr + baseaddr, cu_language, objfile);
}
else
{
- prim_record_minimal_symbol (pdi->name,
- decode_locdesc (pdi->locdesc, objfile)
- + baseaddr,
- mst_file_data, objfile);
+ /* Static Variable. Skip symbols without location descriptors. */
+ if (pdi->locdesc == NULL)
+ return;
+ addr = decode_locdesc (pdi->locdesc, objfile, cu_header);
+ /*prim_record_minimal_symbol (pdi->name, addr + baseaddr,
+ mst_file_data, objfile); */
add_psymbol_to_list (pdi->name, strlen (pdi->name),
VAR_NAMESPACE, LOC_STATIC,
&objfile->static_psymbols,
- 0, (CORE_ADDR) 0, cu_language, objfile);
+ 0, addr + baseaddr, cu_language, objfile);
}
break;
case DW_TAG_typedef:
+ case DW_TAG_base_type:
add_psymbol_to_list (pdi->name, strlen (pdi->name),
VAR_NAMESPACE, LOC_TYPEDEF,
&objfile->static_psymbols,
case DW_TAG_union_type:
case DW_TAG_enumeration_type:
/* Skip aggregate types without children, these are external
- references. */
+ references. */
if (pdi->has_children == 0)
return;
add_psymbol_to_list (pdi->name, strlen (pdi->name),
&objfile->static_psymbols,
0, (CORE_ADDR) 0, cu_language, objfile);
break;
+ default:
+ break;
}
}
/* Expand this partial symbol table into a full symbol table. */
static void
-dwarf2_psymtab_to_symtab (pst)
- struct partial_symtab *pst;
+dwarf2_psymtab_to_symtab (struct partial_symtab *pst)
{
/* FIXME: This is barely more than a stub. */
if (pst != NULL)
}
static void
-psymtab_to_symtab_1 (pst)
- struct partial_symtab *pst;
+psymtab_to_symtab_1 (struct partial_symtab *pst)
{
struct objfile *objfile = pst->objfile;
bfd *abfd = objfile->obfd;
struct comp_unit_head cu_header;
struct die_info *dies;
- struct attribute *attr;
unsigned long offset;
- CORE_ADDR highpc;
- struct attribute *high_pc_attr;
+ CORE_ADDR lowpc, highpc;
struct die_info *child_die;
char *info_ptr;
struct symtab *symtab;
struct cleanup *back_to;
/* Set local variables from the partial symbol table info. */
- offset = DWARF_INFO_OFFSET(pst);
- dwarf_info_buffer = DWARF_INFO_BUFFER(pst);
- dwarf_abbrev_buffer = DWARF_ABBREV_BUFFER(pst);
- dwarf_abbrev_size = DWARF_ABBREV_SIZE(pst);
- dwarf_line_buffer = DWARF_LINE_BUFFER(pst);
- baseaddr = ANOFFSET (pst->section_offsets, 0);
+ offset = DWARF_INFO_OFFSET (pst);
+ dwarf_info_buffer = DWARF_INFO_BUFFER (pst);
+ dwarf_abbrev_buffer = DWARF_ABBREV_BUFFER (pst);
+ dwarf_abbrev_size = DWARF_ABBREV_SIZE (pst);
+ dwarf_line_buffer = DWARF_LINE_BUFFER (pst);
+ baseaddr = ANOFFSET (pst->section_offsets, SECT_OFF_TEXT (objfile));
cu_header_offset = offset;
info_ptr = dwarf_info_buffer + offset;
make_cleanup (really_free_pendings, NULL);
/* read in the comp_unit header */
- cu_header.length = read_4_bytes (abfd, info_ptr);
- info_ptr += 4;
- cu_header.version = read_2_bytes (abfd, info_ptr);
- info_ptr += 2;
- cu_header.abbrev_offset = read_4_bytes (abfd, info_ptr);
- info_ptr += 4;
- cu_header.addr_size = read_1_byte (abfd, info_ptr);
- info_ptr += 1;
+ info_ptr = read_comp_unit_head (&cu_header, info_ptr, abfd);
/* Read the abbrevs for this compilation unit */
dwarf2_read_abbrevs (abfd, cu_header.abbrev_offset);
make_cleanup (dwarf2_empty_abbrev_table, NULL);
- dies = read_comp_unit (info_ptr, abfd);
+ dies = read_comp_unit (info_ptr, abfd, &cu_header);
- make_cleanup (free_die_list, dies);
+ make_cleanup_free_die_list (dies);
/* Do line number decoding in read_file_scope () */
- process_die (dies, objfile);
+ process_die (dies, objfile, &cu_header);
- attr = dwarf_attr (dies, DW_AT_high_pc);
- if (attr)
- {
- highpc = DW_ADDR (attr);
- }
- else
+ if (!dwarf2_get_pc_bounds (dies, &lowpc, &highpc, objfile))
{
/* Some compilers don't define a DW_AT_high_pc attribute for
- the compilation unit. If the DW_AT_high_pc is missing,
- synthesize it, by scanning the DIE's below the compilation unit. */
+ the compilation unit. If the DW_AT_high_pc is missing,
+ synthesize it, by scanning the DIE's below the compilation unit. */
highpc = 0;
if (dies->has_children)
{
{
if (child_die->tag == DW_TAG_subprogram)
{
- high_pc_attr = dwarf_attr (child_die, DW_AT_high_pc);
- if (high_pc_attr)
+ CORE_ADDR low, high;
+
+ if (dwarf2_get_pc_bounds (child_die, &low, &high, objfile))
{
- highpc = max (highpc, DW_ADDR (high_pc_attr));
+ highpc = max (highpc, high);
}
}
child_die = sibling_die (child_die);
}
}
}
- symtab = end_symtab (highpc + baseaddr, objfile, 0);
+ symtab = end_symtab (highpc + baseaddr, objfile, SECT_OFF_TEXT (objfile));
/* Set symtab language to language from DW_AT_language.
If the compilation is from a C file generated by language preprocessors,
/* Process a die and its children. */
static void
-process_die (die, objfile)
- struct die_info *die;
- struct objfile *objfile;
+process_die (struct die_info *die, struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
{
switch (die->tag)
{
case DW_TAG_padding:
break;
case DW_TAG_compile_unit:
- read_file_scope (die, objfile);
+ read_file_scope (die, objfile, cu_header);
break;
case DW_TAG_subprogram:
- read_subroutine_type (die, objfile);
- if (dwarf_attr (die, DW_AT_low_pc))
- {
- read_func_scope (die, objfile);
- }
+ read_subroutine_type (die, objfile, cu_header);
+ read_func_scope (die, objfile, cu_header);
+ break;
+ case DW_TAG_inlined_subroutine:
+ /* FIXME: These are ignored for now.
+ They could be used to set breakpoints on all inlined instances
+ of a function and make GDB `next' properly over inlined functions. */
break;
case DW_TAG_lexical_block:
- read_lexical_block_scope (die, objfile);
+ read_lexical_block_scope (die, objfile, cu_header);
break;
case DW_TAG_class_type:
case DW_TAG_structure_type:
case DW_TAG_union_type:
- read_structure_scope (die, objfile);
+ read_structure_scope (die, objfile, cu_header);
break;
case DW_TAG_enumeration_type:
- read_enumeration (die, objfile);
+ read_enumeration (die, objfile, cu_header);
break;
case DW_TAG_subroutine_type:
- read_subroutine_type (die, objfile);
+ read_subroutine_type (die, objfile, cu_header);
break;
case DW_TAG_array_type:
- dwarf_read_array_type (die, objfile);
+ read_array_type (die, objfile, cu_header);
break;
case DW_TAG_pointer_type:
- read_tag_pointer_type (die, objfile);
+ read_tag_pointer_type (die, objfile, cu_header);
break;
case DW_TAG_ptr_to_member_type:
- read_tag_ptr_to_member_type (die, objfile);
+ read_tag_ptr_to_member_type (die, objfile, cu_header);
break;
case DW_TAG_reference_type:
- read_tag_reference_type (die, objfile);
+ read_tag_reference_type (die, objfile, cu_header);
break;
case DW_TAG_string_type:
read_tag_string_type (die, objfile);
break;
case DW_TAG_base_type:
read_base_type (die, objfile);
+ if (dwarf_attr (die, DW_AT_name))
+ {
+ /* Add a typedef symbol for the base type definition. */
+ new_symbol (die, die->type, objfile, cu_header);
+ }
break;
case DW_TAG_common_block:
- read_common_block (die, objfile);
+ read_common_block (die, objfile, cu_header);
break;
case DW_TAG_common_inclusion:
break;
default:
- new_symbol (die, NULL, objfile);
+ new_symbol (die, NULL, objfile, cu_header);
break;
}
}
static void
-read_file_scope (die, objfile)
- struct die_info *die;
- struct objfile *objfile;
+read_file_scope (struct die_info *die, struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
{
unsigned int line_offset = 0;
- CORE_ADDR lowpc = ((CORE_ADDR) -1);
+ CORE_ADDR lowpc = ((CORE_ADDR) -1);
CORE_ADDR highpc = ((CORE_ADDR) 0);
- struct attribute *attr, *low_pc_attr, *high_pc_attr;
+ struct attribute *attr;
char *name = "<unknown>";
char *comp_dir = NULL;
struct die_info *child_die;
bfd *abfd = objfile->obfd;
- low_pc_attr = dwarf_attr (die, DW_AT_low_pc);
- if (low_pc_attr)
- {
- lowpc = DW_ADDR (low_pc_attr);
- }
- high_pc_attr = dwarf_attr (die, DW_AT_high_pc);
- if (high_pc_attr)
- {
- highpc = DW_ADDR (high_pc_attr);
- }
- if (!low_pc_attr || !high_pc_attr)
+ if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile))
{
if (die->has_children)
{
{
if (child_die->tag == DW_TAG_subprogram)
{
- low_pc_attr = dwarf_attr (child_die, DW_AT_low_pc);
- if (low_pc_attr)
- {
- lowpc = min (lowpc, DW_ADDR (low_pc_attr));
- }
- high_pc_attr = dwarf_attr (child_die, DW_AT_high_pc);
- if (high_pc_attr)
+ CORE_ADDR low, high;
+
+ if (dwarf2_get_pc_bounds (child_die, &low, &high, objfile))
{
- highpc = max (highpc, DW_ADDR (high_pc_attr));
+ lowpc = min (lowpc, low);
+ highpc = max (highpc, high);
}
}
child_die = sibling_die (child_die);
set_cu_language (DW_UNSND (attr));
}
+ /* We assume that we're processing GCC output. */
+ processing_gcc_compilation = 2;
#if 0
- /* FIXME:Do something here. */
- if (dip->at_producer != NULL)
+ /* FIXME:Do something here. */
+ if (dip->at_producer != NULL)
{
handle_producer (dip->at_producer);
}
memset (ftypes, 0, FT_NUM_MEMBERS * sizeof (struct type *));
start_symtab (name, comp_dir, lowpc);
+ record_debugformat ("DWARF 2");
/* Decode line number information if present. */
attr = dwarf_attr (die, DW_AT_stmt_list);
if (attr)
{
line_offset = DW_UNSND (attr);
- dwarf_decode_lines (line_offset, comp_dir, abfd);
+ dwarf_decode_lines (line_offset, comp_dir, abfd, cu_header);
}
/* Process all dies in compilation unit. */
child_die = die->next;
while (child_die && child_die->tag)
{
- process_die (child_die, objfile);
+ process_die (child_die, objfile, cu_header);
child_die = sibling_die (child_die);
}
}
}
static void
-read_func_scope (die, objfile)
- struct die_info *die;
- struct objfile *objfile;
+read_func_scope (struct die_info *die, struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
{
register struct context_stack *new;
- CORE_ADDR lowpc = 0;
- CORE_ADDR highpc = 0;
+ CORE_ADDR lowpc;
+ CORE_ADDR highpc;
struct die_info *child_die;
struct attribute *attr;
- char *name = "<unknown>";
+ char *name;
- attr = dwarf_attr (die, DW_AT_name);
- if (attr)
- {
- name = DW_STRING (attr);
- }
+ name = dwarf2_linkage_name (die);
- attr = dwarf_attr (die, DW_AT_low_pc);
- if (attr)
- {
- lowpc = DW_ADDR (attr);
- }
+ /* Ignore functions with missing or empty names and functions with
+ missing or invalid low and high pc attributes. */
+ if (name == NULL || !dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile))
+ return;
- attr = dwarf_attr (die, DW_AT_high_pc);
- if (attr)
- {
- highpc = DW_ADDR (attr);
- }
lowpc += baseaddr;
highpc += baseaddr;
objfile->ei.entry_func_highpc = highpc;
}
- if (STREQ (name, "main")) /* FIXME: hardwired name */
- {
- objfile->ei.main_func_lowpc = lowpc;
- objfile->ei.main_func_highpc = highpc;
- }
-
/* Decode DW_AT_frame_base location descriptor if present, keep result
for DW_OP_fbreg operands in decode_locdesc. */
frame_base_reg = -1;
attr = dwarf_attr (die, DW_AT_frame_base);
if (attr)
{
- CORE_ADDR addr = decode_locdesc (DW_BLOCK (attr), objfile);
- if (isreg)
+ CORE_ADDR addr = decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
+ if (isderef)
+ complain (&dwarf2_unsupported_at_frame_base, name);
+ else if (isreg)
frame_base_reg = addr;
else if (offreg)
{
}
new = push_context (0, lowpc);
- new->name = new_symbol (die, die->type, objfile);
+ new->name = new_symbol (die, die->type, objfile, cu_header);
list_in_scope = &local_symbols;
if (die->has_children)
child_die = die->next;
while (child_die && child_die->tag)
{
- process_die (child_die, objfile);
+ process_die (child_die, objfile, cu_header);
child_die = sibling_die (child_die);
}
}
a new scope, process the dies, and then close the scope. */
static void
-read_lexical_block_scope (die, objfile)
- struct die_info *die;
- struct objfile *objfile;
+read_lexical_block_scope (struct die_info *die, struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
{
register struct context_stack *new;
- CORE_ADDR lowpc = 0, highpc = 0;
- struct attribute *attr;
+ CORE_ADDR lowpc, highpc;
struct die_info *child_die;
- attr = dwarf_attr (die, DW_AT_low_pc);
- if (attr)
- {
- lowpc = DW_ADDR (attr);
- }
- attr = dwarf_attr (die, DW_AT_high_pc);
- if (attr)
- {
- highpc = DW_ADDR (attr);
- }
+ /* Ignore blocks with missing or invalid low and high pc attributes. */
+ if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile))
+ return;
lowpc += baseaddr;
highpc += baseaddr;
child_die = die->next;
while (child_die && child_die->tag)
{
- process_die (child_die, objfile);
+ process_die (child_die, objfile, cu_header);
child_die = sibling_die (child_die);
}
}
local_symbols = new->locals;
}
+/* Get low and high pc attributes from a die.
+ Return 1 if the attributes are present and valid, otherwise, return 0. */
+
+static int
+dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc, CORE_ADDR *highpc,
+ struct objfile *objfile)
+{
+ struct attribute *attr;
+ CORE_ADDR low;
+ CORE_ADDR high;
+
+ attr = dwarf_attr (die, DW_AT_low_pc);
+ if (attr)
+ low = DW_ADDR (attr);
+ else
+ return 0;
+ attr = dwarf_attr (die, DW_AT_high_pc);
+ if (attr)
+ high = DW_ADDR (attr);
+ else
+ return 0;
+
+ if (high < low)
+ return 0;
+
+ /* When using the GNU linker, .gnu.linkonce. sections are used to
+ eliminate duplicate copies of functions and vtables and such.
+ The linker will arbitrarily choose one and discard the others.
+ The AT_*_pc values for such functions refer to local labels in
+ 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.
+ If this is a discarded function, mark the pc bounds as invalid,
+ so that GDB will ignore it. */
+ if (low == 0 && (bfd_get_file_flags (objfile->obfd) & HAS_RELOC) == 0)
+ return 0;
+
+ *lowpc = low;
+ *highpc = high;
+ return 1;
+}
+
+/* Add an aggregate field to the field list. */
+
+static void
+dwarf2_add_field (struct field_info *fip, struct die_info *die,
+ struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
+{
+ struct nextfield *new_field;
+ struct attribute *attr;
+ struct field *fp;
+ char *fieldname = "";
+
+ /* Allocate a new field list entry and link it in. */
+ new_field = (struct nextfield *) xmalloc (sizeof (struct nextfield));
+ make_cleanup (xfree, new_field);
+ memset (new_field, 0, sizeof (struct nextfield));
+ new_field->next = fip->fields;
+ fip->fields = new_field;
+ fip->nfields++;
+
+ /* Handle accessibility and virtuality of field.
+ The default accessibility for members is public, the default
+ accessibility for inheritance is private. */
+ if (die->tag != DW_TAG_inheritance)
+ new_field->accessibility = DW_ACCESS_public;
+ else
+ new_field->accessibility = DW_ACCESS_private;
+ new_field->virtuality = DW_VIRTUALITY_none;
+
+ attr = dwarf_attr (die, DW_AT_accessibility);
+ if (attr)
+ new_field->accessibility = DW_UNSND (attr);
+ if (new_field->accessibility != DW_ACCESS_public)
+ fip->non_public_fields = 1;
+ attr = dwarf_attr (die, DW_AT_virtuality);
+ if (attr)
+ new_field->virtuality = DW_UNSND (attr);
+
+ fp = &new_field->field;
+ if (die->tag == DW_TAG_member)
+ {
+ /* Get type of field. */
+ fp->type = die_type (die, objfile, cu_header);
+
+ /* Get bit size of field (zero if none). */
+ attr = dwarf_attr (die, DW_AT_bit_size);
+ if (attr)
+ {
+ FIELD_BITSIZE (*fp) = DW_UNSND (attr);
+ }
+ else
+ {
+ FIELD_BITSIZE (*fp) = 0;
+ }
+
+ /* Get bit offset of field. */
+ attr = dwarf_attr (die, DW_AT_data_member_location);
+ if (attr)
+ {
+ FIELD_BITPOS (*fp) =
+ decode_locdesc (DW_BLOCK (attr), objfile, cu_header) * bits_per_byte;
+ }
+ else
+ FIELD_BITPOS (*fp) = 0;
+ attr = dwarf_attr (die, DW_AT_bit_offset);
+ if (attr)
+ {
+ if (BITS_BIG_ENDIAN)
+ {
+ /* For big endian bits, the DW_AT_bit_offset gives the
+ additional bit offset from the MSB of the containing
+ anonymous object to the MSB of the field. We don't
+ have to do anything special since we don't need to
+ know the size of the anonymous object. */
+ FIELD_BITPOS (*fp) += DW_UNSND (attr);
+ }
+ else
+ {
+ /* For little endian bits, compute the bit offset to the
+ MSB of the anonymous object, subtract off the number of
+ bits from the MSB of the field to the MSB of the
+ object, and then subtract off the number of bits of
+ the field itself. The result is the bit offset of
+ the LSB of the field. */
+ int anonymous_size;
+ int bit_offset = DW_UNSND (attr);
+
+ attr = dwarf_attr (die, DW_AT_byte_size);
+ if (attr)
+ {
+ /* The size of the anonymous object containing
+ the bit field is explicit, so use the
+ indicated size (in bytes). */
+ anonymous_size = DW_UNSND (attr);
+ }
+ else
+ {
+ /* The size of the anonymous object containing
+ the bit field must be inferred from the type
+ attribute of the data member containing the
+ bit field. */
+ anonymous_size = TYPE_LENGTH (fp->type);
+ }
+ FIELD_BITPOS (*fp) += anonymous_size * bits_per_byte
+ - bit_offset - FIELD_BITSIZE (*fp);
+ }
+ }
+
+ /* Get name of field. */
+ attr = dwarf_attr (die, DW_AT_name);
+ if (attr && DW_STRING (attr))
+ fieldname = DW_STRING (attr);
+ fp->name = obsavestring (fieldname, strlen (fieldname),
+ &objfile->type_obstack);
+
+ /* Change accessibility for artificial fields (e.g. virtual table
+ pointer or virtual base class pointer) to private. */
+ if (dwarf_attr (die, DW_AT_artificial))
+ {
+ new_field->accessibility = DW_ACCESS_private;
+ fip->non_public_fields = 1;
+ }
+ }
+ else if (die->tag == DW_TAG_variable)
+ {
+ char *physname;
+
+ /* C++ static member.
+ Get name of field. */
+ attr = dwarf_attr (die, DW_AT_name);
+ if (attr && DW_STRING (attr))
+ fieldname = DW_STRING (attr);
+ else
+ return;
+
+ /* Get physical name. */
+ physname = dwarf2_linkage_name (die);
+
+ SET_FIELD_PHYSNAME (*fp, obsavestring (physname, strlen (physname),
+ &objfile->type_obstack));
+ FIELD_TYPE (*fp) = die_type (die, objfile, cu_header);
+ FIELD_NAME (*fp) = obsavestring (fieldname, strlen (fieldname),
+ &objfile->type_obstack);
+ }
+ else if (die->tag == DW_TAG_inheritance)
+ {
+ /* C++ base class field. */
+ attr = dwarf_attr (die, DW_AT_data_member_location);
+ if (attr)
+ FIELD_BITPOS (*fp) = (decode_locdesc (DW_BLOCK (attr), objfile, cu_header)
+ * bits_per_byte);
+ FIELD_BITSIZE (*fp) = 0;
+ FIELD_TYPE (*fp) = die_type (die, objfile, cu_header);
+ FIELD_NAME (*fp) = type_name_no_tag (fp->type);
+ fip->nbaseclasses++;
+ }
+}
+
+/* Create the vector of fields, and attach it to the type. */
+
+static void
+dwarf2_attach_fields_to_type (struct field_info *fip, struct type *type,
+ struct objfile *objfile)
+{
+ int nfields = fip->nfields;
+
+ /* Record the field count, allocate space for the array of fields,
+ and create blank accessibility bitfields if necessary. */
+ TYPE_NFIELDS (type) = nfields;
+ TYPE_FIELDS (type) = (struct field *)
+ TYPE_ALLOC (type, sizeof (struct field) * nfields);
+ memset (TYPE_FIELDS (type), 0, sizeof (struct field) * nfields);
+
+ if (fip->non_public_fields)
+ {
+ ALLOCATE_CPLUS_STRUCT_TYPE (type);
+
+ TYPE_FIELD_PRIVATE_BITS (type) =
+ (B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields));
+ B_CLRALL (TYPE_FIELD_PRIVATE_BITS (type), nfields);
+
+ TYPE_FIELD_PROTECTED_BITS (type) =
+ (B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields));
+ B_CLRALL (TYPE_FIELD_PROTECTED_BITS (type), nfields);
+
+ TYPE_FIELD_IGNORE_BITS (type) =
+ (B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields));
+ B_CLRALL (TYPE_FIELD_IGNORE_BITS (type), nfields);
+ }
+
+ /* If the type has baseclasses, allocate and clear a bit vector for
+ TYPE_FIELD_VIRTUAL_BITS. */
+ if (fip->nbaseclasses)
+ {
+ int num_bytes = B_BYTES (fip->nbaseclasses);
+ char *pointer;
+
+ ALLOCATE_CPLUS_STRUCT_TYPE (type);
+ pointer = (char *) TYPE_ALLOC (type, num_bytes);
+ TYPE_FIELD_VIRTUAL_BITS (type) = (B_TYPE *) pointer;
+ B_CLRALL (TYPE_FIELD_VIRTUAL_BITS (type), fip->nbaseclasses);
+ TYPE_N_BASECLASSES (type) = fip->nbaseclasses;
+ }
+
+ /* 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
+ up in the same order in the array in which they were added to the list. */
+ while (nfields-- > 0)
+ {
+ TYPE_FIELD (type, nfields) = fip->fields->field;
+ switch (fip->fields->accessibility)
+ {
+ case DW_ACCESS_private:
+ SET_TYPE_FIELD_PRIVATE (type, nfields);
+ break;
+
+ case DW_ACCESS_protected:
+ SET_TYPE_FIELD_PROTECTED (type, nfields);
+ break;
+
+ case DW_ACCESS_public:
+ break;
+
+ default:
+ /* Unknown accessibility. Complain and treat it as public. */
+ {
+ complain (&dwarf2_unsupported_accessibility,
+ fip->fields->accessibility);
+ }
+ break;
+ }
+ if (nfields < fip->nbaseclasses)
+ {
+ switch (fip->fields->virtuality)
+ {
+ case DW_VIRTUALITY_virtual:
+ case DW_VIRTUALITY_pure_virtual:
+ SET_TYPE_FIELD_VIRTUAL (type, nfields);
+ break;
+ }
+ }
+ fip->fields = fip->fields->next;
+ }
+}
+
+/* Add a member function to the proper fieldlist. */
+
+static void
+dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
+ struct type *type, struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
+{
+ struct attribute *attr;
+ struct fnfieldlist *flp;
+ int i;
+ struct fn_field *fnp;
+ char *fieldname;
+ char *physname;
+ struct nextfnfield *new_fnfield;
+
+ /* Get name of member function. */
+ attr = dwarf_attr (die, DW_AT_name);
+ if (attr && DW_STRING (attr))
+ fieldname = DW_STRING (attr);
+ else
+ return;
+
+ /* Get the mangled name. */
+ physname = dwarf2_linkage_name (die);
+
+ /* Look up member function name in fieldlist. */
+ for (i = 0; i < fip->nfnfields; i++)
+ {
+ if (STREQ (fip->fnfieldlists[i].name, fieldname))
+ break;
+ }
+
+ /* Create new list element if necessary. */
+ if (i < fip->nfnfields)
+ flp = &fip->fnfieldlists[i];
+ else
+ {
+ if ((fip->nfnfields % DW_FIELD_ALLOC_CHUNK) == 0)
+ {
+ fip->fnfieldlists = (struct fnfieldlist *)
+ xrealloc (fip->fnfieldlists,
+ (fip->nfnfields + DW_FIELD_ALLOC_CHUNK)
+ * sizeof (struct fnfieldlist));
+ if (fip->nfnfields == 0)
+ make_cleanup (free_current_contents, &fip->fnfieldlists);
+ }
+ flp = &fip->fnfieldlists[fip->nfnfields];
+ flp->name = fieldname;
+ flp->length = 0;
+ flp->head = NULL;
+ fip->nfnfields++;
+ }
+
+ /* Create a new member function field and chain it to the field list
+ entry. */
+ new_fnfield = (struct nextfnfield *) xmalloc (sizeof (struct nextfnfield));
+ make_cleanup (xfree, new_fnfield);
+ memset (new_fnfield, 0, sizeof (struct nextfnfield));
+ new_fnfield->next = flp->head;
+ flp->head = new_fnfield;
+ flp->length++;
+
+ /* Fill in the member function field info. */
+ fnp = &new_fnfield->fnfield;
+ fnp->physname = obsavestring (physname, strlen (physname),
+ &objfile->type_obstack);
+ fnp->type = alloc_type (objfile);
+ if (die->type && TYPE_CODE (die->type) == TYPE_CODE_FUNC)
+ {
+ struct type *return_type = TYPE_TARGET_TYPE (die->type);
+ struct type **arg_types;
+ int nparams = TYPE_NFIELDS (die->type);
+ int iparams;
+
+ /* Copy argument types from the subroutine type. */
+ arg_types = (struct type **)
+ TYPE_ALLOC (fnp->type, (nparams + 1) * sizeof (struct type *));
+ for (iparams = 0; iparams < nparams; iparams++)
+ arg_types[iparams] = TYPE_FIELD_TYPE (die->type, iparams);
+
+ /* Set last entry in argument type vector. */
+ if (TYPE_FLAGS (die->type) & TYPE_FLAG_VARARGS)
+ arg_types[nparams] = NULL;
+ else
+ arg_types[nparams] = dwarf2_fundamental_type (objfile, FT_VOID);
+
+ smash_to_method_type (fnp->type, type, return_type, arg_types);
+
+ /* Handle static member functions.
+ 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 member functions (which is the
+ this pointer) as artificial. We obtain this information
+ from read_subroutine_type via TYPE_FIELD_ARTIFICIAL. */
+ if (nparams == 0 || TYPE_FIELD_ARTIFICIAL (die->type, 0) == 0)
+ fnp->voffset = VOFFSET_STATIC;
+ }
+ else
+ complain (&dwarf2_missing_member_fn_type_complaint, physname);
+
+ /* Get fcontext from DW_AT_containing_type if present. */
+ if (dwarf_attr (die, DW_AT_containing_type) != NULL)
+ fnp->fcontext = die_containing_type (die, objfile, cu_header);
+
+ /* 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. */
+
+ /* Get accessibility. */
+ attr = dwarf_attr (die, DW_AT_accessibility);
+ if (attr)
+ {
+ switch (DW_UNSND (attr))
+ {
+ case DW_ACCESS_private:
+ fnp->is_private = 1;
+ break;
+ case DW_ACCESS_protected:
+ fnp->is_protected = 1;
+ break;
+ }
+ }
+
+ /* Get index in virtual function table if it is a virtual member function. */
+ attr = dwarf_attr (die, DW_AT_vtable_elem_location);
+ if (attr)
+ fnp->voffset = decode_locdesc (DW_BLOCK (attr), objfile, cu_header) + 2;
+}
+
+/* Create the vector of member function fields, and attach it to the type. */
+
+static void
+dwarf2_attach_fn_fields_to_type (struct field_info *fip, struct type *type,
+ struct objfile *objfile)
+{
+ struct fnfieldlist *flp;
+ int total_length = 0;
+ int i;
+
+ ALLOCATE_CPLUS_STRUCT_TYPE (type);
+ TYPE_FN_FIELDLISTS (type) = (struct fn_fieldlist *)
+ TYPE_ALLOC (type, sizeof (struct fn_fieldlist) * fip->nfnfields);
+
+ for (i = 0, flp = fip->fnfieldlists; i < fip->nfnfields; i++, flp++)
+ {
+ struct nextfnfield *nfp = flp->head;
+ struct fn_fieldlist *fn_flp = &TYPE_FN_FIELDLIST (type, i);
+ int k;
+
+ TYPE_FN_FIELDLIST_NAME (type, i) = flp->name;
+ TYPE_FN_FIELDLIST_LENGTH (type, i) = flp->length;
+ fn_flp->fn_fields = (struct fn_field *)
+ TYPE_ALLOC (type, sizeof (struct fn_field) * flp->length);
+ for (k = flp->length; (k--, nfp); nfp = nfp->next)
+ fn_flp->fn_fields[k] = nfp->fnfield;
+
+ total_length += flp->length;
+ }
+
+ TYPE_NFN_FIELDS (type) = fip->nfnfields;
+ TYPE_NFN_FIELDS_TOTAL (type) = total_length;
+}
+
/* Called when we find the DIE that starts a structure or union scope
(definition) to process all dies that define the members of the
structure or union.
suppresses creating a symbol table entry itself). */
static void
-read_structure_scope (die, objfile)
- struct die_info *die;
- struct objfile *objfile;
+read_structure_scope (struct die_info *die, struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
{
struct type *type;
- struct field *fields;
- struct die_info *child_die;
struct attribute *attr;
- struct symbol *sym;
- int num_fields;
type = alloc_type (objfile);
INIT_CPLUS_SPECIFIC (type);
attr = dwarf_attr (die, DW_AT_name);
- if (attr)
+ if (attr && DW_STRING (attr))
{
TYPE_TAG_NAME (type) = obsavestring (DW_STRING (attr),
strlen (DW_STRING (attr)),
}
else
{
- /* FIXME: This should be changed to TYPE_CODE_CLASS when the rest
- of GDB knows how to handle it. */
- TYPE_CODE (type) = TYPE_CODE_STRUCT;
+ /* FIXME: TYPE_CODE_CLASS is currently defined to TYPE_CODE_STRUCT
+ in gdbtypes.h. */
+ TYPE_CODE (type) = TYPE_CODE_CLASS;
}
attr = dwarf_attr (die, DW_AT_byte_size);
type within the structure itself. */
die->type = type;
- num_fields = 0;
- fields = NULL;
- if (die->has_children)
+ if (die->has_children && ! die_is_declaration (die))
{
+ struct field_info fi;
+ struct die_info *child_die;
+ struct cleanup *back_to = make_cleanup (null_cleanup, NULL);
+
+ memset (&fi, 0, sizeof (struct field_info));
+
child_die = die->next;
+
while (child_die && child_die->tag)
{
if (child_die->tag == DW_TAG_member)
{
- if ((num_fields % DW_FIELD_ALLOC_CHUNK) == 0)
- {
- fields = (struct field *)
- xrealloc (fields,
- (num_fields + DW_FIELD_ALLOC_CHUNK)
- * sizeof (struct field));
- }
-
- /* Get bit offset of field */
- attr = dwarf_attr (child_die, DW_AT_bit_offset);
- if (attr)
- {
- fields[num_fields].bitpos = DW_UNSND (attr);
- }
- else
- {
- fields[num_fields].bitpos = 0;
- }
- attr = dwarf_attr (child_die, DW_AT_data_member_location);
- if (attr)
- {
- fields[num_fields].bitpos +=
- decode_locdesc (DW_BLOCK (attr), objfile) * bits_per_byte;
- }
-
- /* Get bit size of field (zero if none). */
- attr = dwarf_attr (child_die, DW_AT_bit_size);
- if (attr)
- {
- fields[num_fields].bitsize = DW_UNSND (attr);
- }
- else
- {
- fields[num_fields].bitsize = 0;
- }
-
- /* Get type of member. */
- fields[num_fields].type = die_type (child_die, objfile);
-
- /* Get name of member. */
- attr = dwarf_attr (child_die, DW_AT_name);
- if (attr)
- {
- fields[num_fields].name =
- obsavestring (DW_STRING (attr),
- strlen (DW_STRING (attr)),
- &objfile->type_obstack);
- }
- num_fields++;
+ dwarf2_add_field (&fi, child_die, objfile, cu_header);
}
else if (child_die->tag == DW_TAG_variable)
{
- char *physname = NULL;
- char *fieldname = NULL;
-
- /* C++ static member.
- Get physical name, extract field name from physical name. */
- attr = dwarf_attr (child_die, DW_AT_name);
- if (attr)
- {
- char *cp;
-
- physname = DW_STRING (attr);
-
- cp = physname;
- while (*cp && !is_cplus_marker (*cp))
- cp++;
- if (*cp)
- fieldname = cp + 1;
- }
-
- if (physname && fieldname)
- {
- if ((num_fields % DW_FIELD_ALLOC_CHUNK) == 0)
- {
- fields = (struct field *)
- xrealloc (fields,
- (num_fields + DW_FIELD_ALLOC_CHUNK)
- * sizeof (struct field));
- }
- fields[num_fields].bitpos = -1;
- fields[num_fields].bitsize = (long)
- obsavestring (physname, strlen (physname),
- &objfile->type_obstack);
- fields[num_fields].type = die_type (child_die, objfile);
- fields[num_fields].name =
- obsavestring (fieldname, strlen (fieldname),
- &objfile->type_obstack);
- num_fields++;
- }
- else
- {
- complain (&dwarf2_bad_static_member_name,
- physname ? physname : "<NULL>");
- }
+ /* C++ static member. */
+ dwarf2_add_field (&fi, child_die, objfile, cu_header);
}
else if (child_die->tag == DW_TAG_subprogram)
{
- /* FIXME: C++ member function. */
- process_die (child_die, objfile);
+ /* C++ member function. */
+ process_die (child_die, objfile, cu_header);
+ dwarf2_add_member_fn (&fi, child_die, type, objfile, cu_header);
}
else if (child_die->tag == DW_TAG_inheritance)
{
- /* FIXME: C++ inheritance information. */
+ /* C++ base class field. */
+ dwarf2_add_field (&fi, child_die, objfile, cu_header);
}
else
{
- process_die (child_die, objfile);
+ process_die (child_die, objfile, cu_header);
}
child_die = sibling_die (child_die);
}
- if (num_fields)
+
+ /* Attach fields and member functions to the type. */
+ if (fi.nfields)
+ dwarf2_attach_fields_to_type (&fi, type, objfile);
+ if (fi.nfnfields)
{
- TYPE_NFIELDS (type) = num_fields;
- TYPE_FIELDS (type) = (struct field *)
- TYPE_ALLOC (type, sizeof (struct field) * num_fields);
- memcpy (TYPE_FIELDS (type), fields,
- sizeof (struct field) * num_fields);
- free (fields);
+ dwarf2_attach_fn_fields_to_type (&fi, type, objfile);
+
+ /* Get the type which refers to the base class (possibly this
+ class itself) which contains the vtable pointer for the current
+ class from the DW_AT_containing_type attribute. */
+
+ if (dwarf_attr (die, DW_AT_containing_type) != NULL)
+ {
+ struct type *t = die_containing_type (die, objfile, cu_header);
+
+ TYPE_VPTR_BASETYPE (type) = t;
+ if (type == t)
+ {
+ static const char vptr_name[] =
+ {'_', 'v', 'p', 't', 'r', '\0'};
+ int i;
+
+ /* Our own class provides vtbl ptr. */
+ for (i = TYPE_NFIELDS (t) - 1;
+ i >= TYPE_N_BASECLASSES (t);
+ --i)
+ {
+ char *fieldname = TYPE_FIELD_NAME (t, i);
+
+ if (STREQN (fieldname, vptr_name, strlen (vptr_name) - 1)
+ && is_cplus_marker (fieldname[strlen (vptr_name)]))
+ {
+ TYPE_VPTR_FIELDNO (type) = i;
+ break;
+ }
+ }
+
+ /* Complain if virtual function table field not found. */
+ if (i < TYPE_N_BASECLASSES (t))
+ complain (&dwarf2_vtbl_not_found_complaint,
+ TYPE_TAG_NAME (type) ? TYPE_TAG_NAME (type) : "");
+ }
+ else
+ {
+ TYPE_VPTR_FIELDNO (type) = TYPE_VPTR_FIELDNO (t);
+ }
+ }
}
- sym = new_symbol (die, type, objfile);
+ new_symbol (die, type, objfile, cu_header);
+
+ do_cleanups (back_to);
}
else
{
NOTE: We reverse the order of the element list. */
static void
-read_enumeration (die, objfile)
- struct die_info *die;
- struct objfile *objfile;
+read_enumeration (struct die_info *die, struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
{
struct die_info *child_die;
struct type *type;
TYPE_CODE (type) = TYPE_CODE_ENUM;
attr = dwarf_attr (die, DW_AT_name);
- if (attr)
+ if (attr && DW_STRING (attr))
{
TYPE_TAG_NAME (type) = obsavestring (DW_STRING (attr),
strlen (DW_STRING (attr)),
{
if (child_die->tag != DW_TAG_enumerator)
{
- process_die (child_die, objfile);
+ process_die (child_die, objfile, cu_header);
}
else
{
attr = dwarf_attr (child_die, DW_AT_name);
if (attr)
{
- sym = new_symbol (child_die, type, objfile);
+ sym = new_symbol (child_die, type, objfile, cu_header);
if (SYMBOL_VALUE (sym) < 0)
unsigned_enum = 0;
fields = (struct field *)
xrealloc (fields,
(num_fields + DW_FIELD_ALLOC_CHUNK)
- * sizeof (struct field));
+ * sizeof (struct field));
}
- fields[num_fields].name = SYMBOL_NAME (sym);
- fields[num_fields].type = NULL;
- fields[num_fields].bitpos = SYMBOL_VALUE (sym);
- fields[num_fields].bitsize = 0;
+ FIELD_NAME (fields[num_fields]) = SYMBOL_NAME (sym);
+ FIELD_TYPE (fields[num_fields]) = NULL;
+ FIELD_BITPOS (fields[num_fields]) = SYMBOL_VALUE (sym);
+ FIELD_BITSIZE (fields[num_fields]) = 0;
num_fields++;
}
TYPE_ALLOC (type, sizeof (struct field) * num_fields);
memcpy (TYPE_FIELDS (type), fields,
sizeof (struct field) * num_fields);
- free (fields);
+ xfree (fields);
}
if (unsigned_enum)
TYPE_FLAGS (type) |= TYPE_FLAG_UNSIGNED;
}
die->type = type;
- sym = new_symbol (die, type, objfile);
+ new_symbol (die, type, objfile, cu_header);
}
/* Extract all information from a DW_TAG_array_type DIE and put it in
arrays. */
static void
-dwarf_read_array_type (die, objfile)
- struct die_info *die;
- struct objfile *objfile;
+read_array_type (struct die_info *die, struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
{
struct die_info *child_die;
struct type *type = NULL;
struct type *element_type, *range_type, *index_type;
+ struct type **range_types = NULL;
struct attribute *attr;
- unsigned int low, high;
+ int ndim = 0;
+ struct cleanup *back_to;
/* Return if we've already decoded this type. */
if (die->type)
return;
}
- element_type = die_type (die, objfile);
+ element_type = die_type (die, objfile, cu_header);
/* Irix 6.2 native cc creates array types without children for
- variable length arrays. */
+ arrays with unspecified length. */
if (die->has_children == 0)
{
index_type = dwarf2_fundamental_type (objfile, FT_INTEGER);
return;
}
- low = 0;
- high = 1;
- if (cu_language == DW_LANG_Fortran77 || cu_language == DW_LANG_Fortran90)
- {
- /* FORTRAN implies a lower bound of 1, if not given. */
- low = 1;
- }
-
+ back_to = make_cleanup (null_cleanup, NULL);
child_die = die->next;
while (child_die && child_die->tag)
{
if (child_die->tag == DW_TAG_subrange_type)
{
- index_type = die_type (child_die, objfile);
+ unsigned int low, high;
+
+ /* Default bounds to an array with unspecified length. */
+ low = 0;
+ high = -1;
+ if (cu_language == language_fortran)
+ {
+ /* FORTRAN implies a lower bound of 1, if not given. */
+ low = 1;
+ }
+
+ index_type = die_type (child_die, objfile, cu_header);
attr = dwarf_attr (child_die, DW_AT_lower_bound);
if (attr)
{
low = DW_SND (attr);
}
else if (attr->form == DW_FORM_udata
- || attr->form == DW_FORM_data1
- || attr->form == DW_FORM_data2
- || attr->form == DW_FORM_data4)
+ || attr->form == DW_FORM_data1
+ || attr->form == DW_FORM_data2
+ || attr->form == DW_FORM_data4)
{
low = DW_UNSND (attr);
}
high = DW_SND (attr);
}
else if (attr->form == DW_FORM_udata
- || attr->form == DW_FORM_data1
- || attr->form == DW_FORM_data2
- || attr->form == DW_FORM_data4)
+ || attr->form == DW_FORM_data1
+ || attr->form == DW_FORM_data2
+ || attr->form == DW_FORM_data4)
{
high = DW_UNSND (attr);
}
#endif
}
}
- range_type = create_range_type (NULL, index_type, low, high);
- type = create_array_type (NULL, element_type, range_type);
- element_type = type;
+
+ /* Create a range type and save it for array type creation. */
+ if ((ndim % DW_FIELD_ALLOC_CHUNK) == 0)
+ {
+ range_types = (struct type **)
+ xrealloc (range_types, (ndim + DW_FIELD_ALLOC_CHUNK)
+ * sizeof (struct type *));
+ if (ndim == 0)
+ make_cleanup (free_current_contents, &range_types);
+ }
+ range_types[ndim++] = create_range_type (NULL, index_type, low, high);
}
child_die = sibling_die (child_die);
}
+
+ /* Dwarf2 dimensions are output from left to right, create the
+ necessary array types in backwards order. */
+ type = element_type;
+ while (ndim-- > 0)
+ type = create_array_type (NULL, type, range_types[ndim]);
+
+ do_cleanups (back_to);
+
/* Install the type in the die. */
die->type = type;
}
/* First cut: install each common block member as a global variable. */
static void
-read_common_block (die, objfile)
- struct die_info *die;
- struct objfile *objfile;
+read_common_block (struct die_info *die, struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
{
struct die_info *child_die;
struct attribute *attr;
attr = dwarf_attr (die, DW_AT_location);
if (attr)
{
- base = decode_locdesc (DW_BLOCK (attr), objfile);
+ base = decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
}
if (die->has_children)
{
child_die = die->next;
while (child_die && child_die->tag)
{
- sym = new_symbol (child_die, NULL, objfile);
+ sym = new_symbol (child_die, NULL, objfile, cu_header);
attr = dwarf_attr (child_die, DW_AT_data_member_location);
if (attr)
{
SYMBOL_VALUE_ADDRESS (sym) =
- base + decode_locdesc (DW_BLOCK (attr), objfile);
+ base + decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
add_symbol_to_list (sym, &global_symbols);
}
child_die = sibling_die (child_die);
the user defined type vector. */
static void
-read_tag_pointer_type (die, objfile)
- struct die_info *die;
- struct objfile *objfile;
+read_tag_pointer_type (struct die_info *die, struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
{
struct type *type;
struct attribute *attr;
return;
}
- type = lookup_pointer_type (die_type (die, objfile));
+ type = lookup_pointer_type (die_type (die, objfile, cu_header));
attr = dwarf_attr (die, DW_AT_byte_size);
if (attr)
{
}
else
{
- TYPE_LENGTH (type) = address_size;
+ TYPE_LENGTH (type) = cu_header->addr_size;
}
die->type = type;
}
the user defined type vector. */
static void
-read_tag_ptr_to_member_type (die, objfile)
- struct die_info *die;
- struct objfile *objfile;
+read_tag_ptr_to_member_type (struct die_info *die, struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
{
struct type *type;
struct type *to_type;
}
type = alloc_type (objfile);
- to_type = die_type (die, objfile);
- domain = die_containing_type (die, objfile);
+ to_type = die_type (die, objfile, cu_header);
+ domain = die_containing_type (die, objfile, cu_header);
smash_to_member_type (type, domain, to_type);
die->type = type;
the user defined type vector. */
static void
-read_tag_reference_type (die, objfile)
- struct die_info *die;
- struct objfile *objfile;
+read_tag_reference_type (struct die_info *die, struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
{
struct type *type;
struct attribute *attr;
return;
}
- type = lookup_reference_type (die_type (die, objfile));
+ type = lookup_reference_type (die_type (die, objfile, cu_header));
attr = dwarf_attr (die, DW_AT_byte_size);
if (attr)
{
}
else
{
- TYPE_LENGTH (type) = address_size;
+ TYPE_LENGTH (type) = cu_header->addr_size;
}
die->type = type;
}
static void
-read_tag_const_type (die, objfile)
- struct die_info *die;
- struct objfile *objfile;
+read_tag_const_type (struct die_info *die, struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
{
if (die->type)
{
}
complain (&dwarf2_const_ignored);
- die->type = die_type (die, objfile);
+ die->type = die_type (die, objfile, cu_header);
}
static void
-read_tag_volatile_type (die, objfile)
- struct die_info *die;
- struct objfile *objfile;
+read_tag_volatile_type (struct die_info *die, struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
{
if (die->type)
{
}
complain (&dwarf2_volatile_ignored);
- die->type = die_type (die, objfile);
+ die->type = die_type (die, objfile, cu_header);
}
/* Extract all information from a DW_TAG_string_type DIE and add to
attribute to reference it. */
static void
-read_tag_string_type (die, objfile)
- struct die_info *die;
- struct objfile *objfile;
+read_tag_string_type (struct die_info *die, struct objfile *objfile)
{
struct type *type, *range_type, *index_type, *char_type;
struct attribute *attr;
/* Handle DIES due to C code like:
struct foo
- {
- int (*funcp)(int a, long l);
- int b;
- };
+ {
+ int (*funcp)(int a, long l);
+ int b;
+ };
('funcp' generates a DW_TAG_subroutine_type DIE)
-*/
+ */
static void
-read_subroutine_type (die, objfile)
- struct die_info *die;
- struct objfile *objfile;
+read_subroutine_type (struct die_info *die, struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
{
struct type *type; /* Type that this function returns */
struct type *ftype; /* Function that returns above type */
+ struct attribute *attr;
/* Decode the type that this subroutine returns */
if (die->type)
{
return;
}
- type = die_type (die, objfile);
+ type = die_type (die, objfile, cu_header);
ftype = lookup_function_type (type);
+ /* All functions in C++ have prototypes. */
+ attr = dwarf_attr (die, DW_AT_prototyped);
+ if ((attr && (DW_UNSND (attr) != 0))
+ || cu_language == language_cplus)
+ TYPE_FLAGS (ftype) |= TYPE_FLAG_PROTOTYPED;
+
if (die->has_children)
{
struct die_info *child_die;
int iparams = 0;
/* Count the number of parameters.
- FIXME: GDB currently has no way to deal with ellipsis,
- represented by DW_TAG_unspecified_parameters. */
+ FIXME: GDB currently ignores vararg functions, but knows about
+ vararg member functions. */
child_die = die->next;
while (child_die && child_die->tag)
{
if (child_die->tag == DW_TAG_formal_parameter)
nparams++;
+ else if (child_die->tag == DW_TAG_unspecified_parameters)
+ TYPE_FLAGS (ftype) |= TYPE_FLAG_VARARGS;
child_die = sibling_die (child_die);
}
{
if (child_die->tag == DW_TAG_formal_parameter)
{
- TYPE_FIELD_TYPE (ftype, iparams) = die_type (child_die, objfile);
+ /* 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 member functions (which is the
+ this pointer) as artificial. We pass this information
+ to dwarf2_add_member_fn via TYPE_FIELD_ARTIFICIAL. */
+ attr = dwarf_attr (child_die, DW_AT_artificial);
+ if (attr)
+ TYPE_FIELD_ARTIFICIAL (ftype, iparams) = DW_UNSND (attr);
+ else
+ TYPE_FIELD_ARTIFICIAL (ftype, iparams) = 0;
+ TYPE_FIELD_TYPE (ftype, iparams) = die_type (child_die, objfile,
+ cu_header);
iparams++;
}
child_die = sibling_die (child_die);
}
static void
-read_typedef (die, objfile)
- struct die_info *die;
- struct objfile *objfile;
+read_typedef (struct die_info *die, struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
{
struct type *type;
struct attribute *attr;
struct type *xtype;
- xtype = die_type (die, objfile);
+ xtype = die_type (die, objfile, cu_header);
type = alloc_type (objfile);
TYPE_CODE (type) = TYPE_CODE_TYPEDEF;
TYPE_FLAGS (type) |= TYPE_FLAG_TARGET_STUB;
TYPE_TARGET_TYPE (type) = xtype;
attr = dwarf_attr (die, DW_AT_name);
- if (attr)
+ if (attr && DW_STRING (attr))
TYPE_NAME (type) = obsavestring (DW_STRING (attr),
strlen (DW_STRING (attr)),
&objfile->type_obstack);
it in the TYPE field of the die. */
static void
-read_base_type (die, objfile)
- struct die_info *die;
- struct objfile *objfile;
+read_base_type (struct die_info *die, struct objfile *objfile)
{
struct type *type;
struct attribute *attr;
size = DW_UNSND (attr);
}
attr = dwarf_attr (die, DW_AT_name);
- if (attr)
+ if (attr && DW_STRING (attr))
{
enum type_code code = TYPE_CODE_INT;
int is_unsigned = 0;
break;
case DW_ATE_boolean:
code = TYPE_CODE_BOOL;
+ is_unsigned = 1;
break;
case DW_ATE_complex_float:
code = TYPE_CODE_COMPLEX;
}
else
{
- type = dwarf_base_type (encoding, size);
+ type = dwarf_base_type (encoding, size, objfile);
}
die->type = type;
}
/* Read a whole compilation unit into a linked list of dies. */
struct die_info *
-read_comp_unit (info_ptr, abfd)
- char *info_ptr;
- bfd *abfd;
+read_comp_unit (char *info_ptr, bfd *abfd,
+ const struct comp_unit_head *cu_header)
{
struct die_info *first_die, *last_die, *die;
char *cur_ptr;
int nesting_level;
- /* Reset die reference table, we are building a new one now. */
- dwarf2_empty_die_ref_table ();
+ /* Reset die reference table; we are
+ building new ones now. */
+ dwarf2_empty_hash_tables ();
cur_ptr = info_ptr;
nesting_level = 0;
first_die = last_die = NULL;
do
{
- cur_ptr = read_full_die (&die, abfd, cur_ptr);
+ cur_ptr = read_full_die (&die, abfd, cur_ptr, cu_header);
if (die->has_children)
{
nesting_level++;
/* Free a linked list of dies. */
static void
-free_die_list (dies)
- struct die_info *dies;
+free_die_list (struct die_info *dies)
{
struct die_info *die, *next;
while (die)
{
next = die->next;
- free (die->attrs);
- free (die);
+ xfree (die->attrs);
+ xfree (die);
die = next;
}
}
+static void
+do_free_die_list_cleanup (void *dies)
+{
+ free_die_list (dies);
+}
+
+static struct cleanup *
+make_cleanup_free_die_list (struct die_info *dies)
+{
+ return make_cleanup (do_free_die_list_cleanup, dies);
+}
+
+
/* 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. */
static char *
-dwarf2_read_section (objfile, offset, size)
- struct objfile *objfile;
- file_ptr offset;
- unsigned int size;
+dwarf2_read_section (struct objfile *objfile, file_ptr offset,
+ unsigned int size)
{
bfd *abfd = objfile->obfd;
char *buf;
{
buf = NULL;
error ("Dwarf Error: Can't read DWARF data from '%s'",
- bfd_get_filename (abfd));
+ bfd_get_filename (abfd));
}
return buf;
}
in a hash table. */
static void
-dwarf2_read_abbrevs (abfd, offset)
- bfd * abfd;
- unsigned int offset;
+dwarf2_read_abbrevs (bfd *abfd, unsigned int offset)
{
char *abbrev_ptr;
struct abbrev_info *cur_abbrev;
cur_abbrev->attrs = (struct attr_abbrev *)
xrealloc (cur_abbrev->attrs,
(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++].form = abbrev_form;
/* Get next abbreviation.
Under Irix6 the abbreviations for a compilation unit are not
- always properly terminated with an abbrev number of 0.
- Exit loop if we encounter an abbreviation which we have
- already read (which means we are about to read the abbreviations
- for the next compile unit) or if the end of the abbreviation
- table is reached. */
+ always properly terminated with an abbrev number of 0.
+ Exit loop if we encounter an abbreviation which we have
+ already read (which means we are about to read the abbreviations
+ for the next compile unit) or if the end of the abbreviation
+ table is reached. */
if ((unsigned int) (abbrev_ptr - dwarf_abbrev_buffer)
- >= dwarf_abbrev_size)
+ >= dwarf_abbrev_size)
break;
abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
abbrev_ptr += bytes_read;
/* ARGSUSED */
static void
-dwarf2_empty_abbrev_table (ignore)
- PTR ignore;
+dwarf2_empty_abbrev_table (PTR ignore)
{
int i;
struct abbrev_info *abbrev, *next;
while (abbrev)
{
next = abbrev->next;
- free (abbrev->attrs);
- free (abbrev);
+ xfree (abbrev->attrs);
+ xfree (abbrev);
abbrev = next;
}
dwarf2_abbrevs[i] = NULL;
/* Lookup an abbrev_info structure in the abbrev hash table. */
static struct abbrev_info *
-dwarf2_lookup_abbrev (number)
- unsigned int number;
+dwarf2_lookup_abbrev (unsigned int number)
{
unsigned int hash_number;
struct abbrev_info *abbrev;
/* Read a minimal amount of information into the minimal die structure. */
static char *
-read_partial_die (part_die, abfd, info_ptr, has_pc_info)
- struct partial_die_info *part_die;
- bfd * abfd;
- char *info_ptr;
- int *has_pc_info;
+read_partial_die (struct partial_die_info *part_die, bfd *abfd,
+ char *info_ptr, int *has_pc_info,
+ const struct comp_unit_head *cu_header)
{
unsigned int abbrev_number, bytes_read, i;
struct abbrev_info *abbrev;
- char ebuf[256];
- int has_low_pc_attr = 0;
+ struct attribute attr;
+ struct attribute spec_attr;
+ int found_spec_attr = 0;
+ int has_low_pc_attr = 0;
int has_high_pc_attr = 0;
*part_die = zeroed_partial_die;
part_die->has_children = abbrev->has_children;
part_die->abbrev = abbrev_number;
- {
- char *str = "";
- struct dwarf_block *blk = 0;
- CORE_ADDR addr = ((CORE_ADDR) -1);
- unsigned int unsnd = ((unsigned int) -1);
- int snd = -1;
+ for (i = 0; i < abbrev->num_attrs; ++i)
+ {
+ info_ptr = read_attribute (&attr, &abbrev->attrs[i], abfd,
+ info_ptr, cu_header);
- for (i = 0; i < abbrev->num_attrs; ++i)
- {
- /* read the correct type of data */
- switch (abbrev->attrs[i].form)
- {
- case DW_FORM_addr:
- addr = read_address (abfd, info_ptr);
- info_ptr += address_size;
- break;
- case DW_FORM_ref_addr:
- addr = read_address (abfd, info_ptr);
- info_ptr += address_size;
- break;
- case DW_FORM_block2:
- blk = dwarf_alloc_block ();
- blk->size = read_2_bytes (abfd, info_ptr);
- info_ptr += 2;
- blk->data = read_n_bytes (abfd, info_ptr, blk->size);
- info_ptr += blk->size;
- break;
- case DW_FORM_block4:
- blk = dwarf_alloc_block ();
- blk->size = read_4_bytes (abfd, info_ptr);
- info_ptr += 4;
- blk->data = read_n_bytes (abfd, info_ptr, blk->size);
- info_ptr += blk->size;
- break;
- case DW_FORM_data2:
- unsnd = read_2_bytes (abfd, info_ptr);
- info_ptr += 2;
- break;
- case DW_FORM_data4:
- unsnd = read_4_bytes (abfd, info_ptr);
- info_ptr += 4;
- break;
- case DW_FORM_data8:
- unsnd = read_8_bytes (abfd, info_ptr);
- info_ptr += 8;
- break;
- case DW_FORM_string:
- str = read_string (abfd, info_ptr, &bytes_read);
- info_ptr += bytes_read;
- break;
- case DW_FORM_block:
- blk = dwarf_alloc_block ();
- blk->size = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
- info_ptr += bytes_read;
- blk->data = read_n_bytes (abfd, info_ptr, blk->size);
- info_ptr += blk->size;
- break;
- case DW_FORM_block1:
- blk = dwarf_alloc_block ();
- blk->size = read_1_byte (abfd, info_ptr);
- info_ptr += 1;
- blk->data = read_n_bytes (abfd, info_ptr, blk->size);
- info_ptr += blk->size;
- break;
- case DW_FORM_data1:
- unsnd = read_1_byte (abfd, info_ptr);
- info_ptr += 1;
- break;
- case DW_FORM_ref1:
- unsnd = read_1_byte (abfd, info_ptr);
- info_ptr += 1;
- break;
- case DW_FORM_ref2:
- unsnd = read_2_bytes (abfd, info_ptr);
- info_ptr += 2;
- break;
- case DW_FORM_ref4:
- unsnd = read_4_bytes (abfd, info_ptr);
- info_ptr += 4;
- break;
- case DW_FORM_ref_udata:
- unsnd = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
- info_ptr += bytes_read;
- break;
- case DW_FORM_flag:
- unsnd = read_1_byte (abfd, info_ptr);
- info_ptr += 1;
- break;
- case DW_FORM_sdata:
- snd = read_signed_leb128 (abfd, info_ptr, &bytes_read);
- info_ptr += bytes_read;
- break;
- case DW_FORM_udata:
- unsnd = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
- info_ptr += bytes_read;
- break;
- case DW_FORM_indirect:
- default:
- sprintf (ebuf,
- "Dwarf Error: Cannot handle %s in DWARF reader.",
- dwarf_form_name (abbrev->attrs[i].form));
- error (ebuf);
- }
+ /* Store the data if it is of an attribute we want to keep in a
+ partial symbol table. */
+ switch (attr.name)
+ {
+ case DW_AT_name:
- /* store the data if it is of an attribute we want to keep in a
- partial symbol table */
- switch (abbrev->attrs[i].name)
- {
- case DW_AT_name:
- part_die->name = str;
- break;
- case DW_AT_low_pc:
- has_low_pc_attr = 1;
- part_die->lowpc = addr;
- break;
- case DW_AT_high_pc:
- has_high_pc_attr = 1;
- part_die->highpc = addr;
- break;
- case DW_AT_location:
- part_die->locdesc = blk;
- break;
- case DW_AT_language:
- part_die->language = unsnd;
- break;
- case DW_AT_external:
- part_die->is_external = unsnd;
- break;
- case DW_AT_declaration:
- part_die->is_declaration = unsnd;
- break;
- }
- }
- }
- *has_pc_info = has_low_pc_attr && has_high_pc_attr;
+ /* Prefer DW_AT_MIPS_linkage_name over DW_AT_name. */
+ if (part_die->name == NULL)
+ part_die->name = DW_STRING (&attr);
+ break;
+ case DW_AT_MIPS_linkage_name:
+ part_die->name = DW_STRING (&attr);
+ break;
+ case DW_AT_low_pc:
+ has_low_pc_attr = 1;
+ part_die->lowpc = DW_ADDR (&attr);
+ break;
+ case DW_AT_high_pc:
+ has_high_pc_attr = 1;
+ part_die->highpc = DW_ADDR (&attr);
+ break;
+ case DW_AT_location:
+ part_die->locdesc = DW_BLOCK (&attr);
+ break;
+ case DW_AT_language:
+ part_die->language = DW_UNSND (&attr);
+ break;
+ case DW_AT_external:
+ part_die->is_external = DW_UNSND (&attr);
+ break;
+ case DW_AT_declaration:
+ part_die->is_declaration = DW_UNSND (&attr);
+ break;
+ case DW_AT_type:
+ part_die->has_type = 1;
+ break;
+ case DW_AT_abstract_origin:
+ case DW_AT_specification:
+ found_spec_attr = 1;
+ spec_attr = attr;
+ break;
+ case DW_AT_sibling:
+ /* Ignore absolute siblings, they might point outside of
+ the current compile unit. */
+ if (attr.form == DW_FORM_ref_addr)
+ complain (&dwarf2_absolute_sibling_complaint);
+ else
+ part_die->sibling =
+ dwarf_info_buffer + dwarf2_get_ref_die_offset (&attr);
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* If we found a reference attribute and the die has no name, try
+ to find a name in the referred to die. */
+
+ if (found_spec_attr && part_die->name == NULL)
+ {
+ struct partial_die_info spec_die;
+ char *spec_ptr;
+ int dummy;
+
+ spec_ptr = dwarf_info_buffer + dwarf2_get_ref_die_offset (&spec_attr);
+ read_partial_die (&spec_die, abfd, spec_ptr, &dummy, cu_header);
+ if (spec_die.name)
+ {
+ part_die->name = spec_die.name;
+
+ /* Copy DW_AT_external attribute if it is set. */
+ if (spec_die.is_external)
+ part_die->is_external = spec_die.is_external;
+ }
+ }
+
+ /* When using the GNU linker, .gnu.linkonce. sections are used to
+ eliminate duplicate copies of functions and vtables and such.
+ The linker will arbitrarily choose one and discard the others.
+ The AT_*_pc values for such functions refer to local labels in
+ 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.
+ If this is a discarded function, mark the pc bounds as invalid,
+ so that GDB will ignore it. */
+ if (has_low_pc_attr && has_high_pc_attr
+ && part_die->lowpc < part_die->highpc
+ && (part_die->lowpc != 0
+ || (bfd_get_file_flags (abfd) & HAS_RELOC)))
+ *has_pc_info = 1;
return info_ptr;
}
point to a newly allocated die with its information. */
static char *
-read_full_die (diep, abfd, info_ptr)
- struct die_info **diep;
- bfd *abfd;
- char *info_ptr;
+read_full_die (struct die_info **diep, bfd *abfd, char *info_ptr,
+ const struct comp_unit_head *cu_header)
{
unsigned int abbrev_number, bytes_read, i, offset;
struct abbrev_info *abbrev;
struct die_info *die;
- char ebuf[256];
offset = info_ptr - dwarf_info_buffer;
abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
die->attrs = (struct attribute *)
xmalloc (die->num_attrs * sizeof (struct attribute));
- {
- struct dwarf_block *blk;
+ for (i = 0; i < abbrev->num_attrs; ++i)
+ {
+ info_ptr = read_attribute (&die->attrs[i], &abbrev->attrs[i],
+ abfd, info_ptr, cu_header);
+ }
- for (i = 0; i < abbrev->num_attrs; ++i)
- {
- /* read the correct type of data */
+ *diep = die;
+ return info_ptr;
+}
- die->attrs[i].name = abbrev->attrs[i].name;
- die->attrs[i].form = abbrev->attrs[i].form;
+/* Read an attribute described by an abbreviated attribute. */
- switch (abbrev->attrs[i].form)
- {
- case DW_FORM_addr:
- case DW_FORM_ref_addr:
- die->attrs[i].u.addr = read_address (abfd, info_ptr);
- info_ptr += address_size;
- break;
- case DW_FORM_block2:
- blk = dwarf_alloc_block ();
- blk->size = read_2_bytes (abfd, info_ptr);
- info_ptr += 2;
- blk->data = read_n_bytes (abfd, info_ptr, blk->size);
- info_ptr += blk->size;
- die->attrs[i].u.blk = blk;
- break;
- case DW_FORM_block4:
- blk = dwarf_alloc_block ();
- blk->size = read_4_bytes (abfd, info_ptr);
- info_ptr += 4;
- blk->data = read_n_bytes (abfd, info_ptr, blk->size);
- info_ptr += blk->size;
- die->attrs[i].u.blk = blk;
- break;
- case DW_FORM_data2:
- die->attrs[i].u.unsnd = read_2_bytes (abfd, info_ptr);
- info_ptr += 2;
- break;
- case DW_FORM_data4:
- die->attrs[i].u.unsnd = read_4_bytes (abfd, info_ptr);
- info_ptr += 4;
- break;
- case DW_FORM_data8:
- die->attrs[i].u.unsnd = read_8_bytes (abfd, info_ptr);
- info_ptr += 8;
- break;
- case DW_FORM_string:
- die->attrs[i].u.str = read_string (abfd, info_ptr, &bytes_read);
- info_ptr += bytes_read;
- break;
- case DW_FORM_block:
- blk = dwarf_alloc_block ();
- blk->size = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
- info_ptr += bytes_read;
- blk->data = read_n_bytes (abfd, info_ptr, blk->size);
- info_ptr += blk->size;
- die->attrs[i].u.blk = blk;
- break;
- case DW_FORM_block1:
- blk = dwarf_alloc_block ();
- blk->size = read_1_byte (abfd, info_ptr);
- info_ptr += 1;
- blk->data = read_n_bytes (abfd, info_ptr, blk->size);
- info_ptr += blk->size;
- die->attrs[i].u.blk = blk;
- break;
- case DW_FORM_data1:
- die->attrs[i].u.unsnd = read_1_byte (abfd, info_ptr);
- info_ptr += 1;
- break;
- case DW_FORM_ref1:
- die->attrs[i].u.unsnd = read_1_byte (abfd, info_ptr);
- info_ptr += 1;
- break;
- case DW_FORM_ref2:
- die->attrs[i].u.unsnd = read_2_bytes (abfd, info_ptr);
- info_ptr += 2;
- break;
- case DW_FORM_ref4:
- die->attrs[i].u.unsnd = read_4_bytes (abfd, info_ptr);
- info_ptr += 4;
- break;
- case DW_FORM_ref_udata:
- die->attrs[i].u.unsnd = read_unsigned_leb128 (abfd,
- info_ptr,
- &bytes_read);
- info_ptr += bytes_read;
- break;
- case DW_FORM_flag:
- die->attrs[i].u.unsnd = read_1_byte (abfd, info_ptr);
- info_ptr += 1;
- break;
- case DW_FORM_sdata:
- die->attrs[i].u.snd = read_signed_leb128 (abfd,
- info_ptr,
- &bytes_read);
- info_ptr += bytes_read;
- break;
- case DW_FORM_udata:
- die->attrs[i].u.unsnd = read_unsigned_leb128 (abfd,
- info_ptr,
- &bytes_read);
- info_ptr += bytes_read;
- break;
- case DW_FORM_indirect:
- default:
- sprintf (ebuf,
- "Dwarf Error: Cannot handle %s in DWARF reader.",
- dwarf_form_name (abbrev->attrs[i].form));
- error (ebuf);
- }
+static char *
+read_attribute (struct attribute *attr, struct attr_abbrev *abbrev,
+ bfd *abfd, char *info_ptr,
+ const struct comp_unit_head *cu_header)
+{
+ unsigned int bytes_read;
+ struct dwarf_block *blk;
- }
- }
- *diep = die;
+ attr->name = abbrev->name;
+ attr->form = abbrev->form;
+ switch (abbrev->form)
+ {
+ case DW_FORM_addr:
+ case DW_FORM_ref_addr:
+ DW_ADDR (attr) = read_address (abfd, info_ptr, cu_header, &bytes_read);
+ info_ptr += bytes_read;
+ break;
+ case DW_FORM_block2:
+ blk = dwarf_alloc_block ();
+ blk->size = read_2_bytes (abfd, info_ptr);
+ info_ptr += 2;
+ blk->data = read_n_bytes (abfd, info_ptr, blk->size);
+ info_ptr += blk->size;
+ DW_BLOCK (attr) = blk;
+ break;
+ case DW_FORM_block4:
+ blk = dwarf_alloc_block ();
+ blk->size = read_4_bytes (abfd, info_ptr);
+ info_ptr += 4;
+ blk->data = read_n_bytes (abfd, info_ptr, blk->size);
+ info_ptr += blk->size;
+ DW_BLOCK (attr) = blk;
+ break;
+ case DW_FORM_data2:
+ DW_UNSND (attr) = read_2_bytes (abfd, info_ptr);
+ info_ptr += 2;
+ break;
+ case DW_FORM_data4:
+ DW_UNSND (attr) = read_4_bytes (abfd, info_ptr);
+ info_ptr += 4;
+ break;
+ case DW_FORM_data8:
+ DW_UNSND (attr) = read_8_bytes (abfd, info_ptr);
+ info_ptr += 8;
+ break;
+ case DW_FORM_string:
+ DW_STRING (attr) = read_string (abfd, info_ptr, &bytes_read);
+ info_ptr += bytes_read;
+ break;
+ case DW_FORM_block:
+ blk = dwarf_alloc_block ();
+ blk->size = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
+ info_ptr += bytes_read;
+ blk->data = read_n_bytes (abfd, info_ptr, blk->size);
+ info_ptr += blk->size;
+ DW_BLOCK (attr) = blk;
+ break;
+ case DW_FORM_block1:
+ blk = dwarf_alloc_block ();
+ blk->size = read_1_byte (abfd, info_ptr);
+ info_ptr += 1;
+ blk->data = read_n_bytes (abfd, info_ptr, blk->size);
+ info_ptr += blk->size;
+ DW_BLOCK (attr) = blk;
+ break;
+ case DW_FORM_data1:
+ DW_UNSND (attr) = read_1_byte (abfd, info_ptr);
+ info_ptr += 1;
+ break;
+ case DW_FORM_flag:
+ DW_UNSND (attr) = read_1_byte (abfd, info_ptr);
+ info_ptr += 1;
+ break;
+ case DW_FORM_sdata:
+ DW_SND (attr) = read_signed_leb128 (abfd, info_ptr, &bytes_read);
+ info_ptr += bytes_read;
+ break;
+ case DW_FORM_udata:
+ DW_UNSND (attr) = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
+ info_ptr += bytes_read;
+ break;
+ case DW_FORM_ref1:
+ DW_UNSND (attr) = read_1_byte (abfd, info_ptr);
+ info_ptr += 1;
+ break;
+ case DW_FORM_ref2:
+ DW_UNSND (attr) = read_2_bytes (abfd, info_ptr);
+ info_ptr += 2;
+ break;
+ case DW_FORM_ref4:
+ DW_UNSND (attr) = read_4_bytes (abfd, info_ptr);
+ info_ptr += 4;
+ break;
+ case DW_FORM_ref8:
+ DW_UNSND (attr) = read_8_bytes (abfd, info_ptr);
+ info_ptr += 8;
+ break;
+ case DW_FORM_ref_udata:
+ DW_UNSND (attr) = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
+ info_ptr += bytes_read;
+ break;
+ case DW_FORM_strp:
+ case DW_FORM_indirect:
+ default:
+ error ("Dwarf Error: Cannot handle %s in DWARF reader.",
+ dwarf_form_name (abbrev->form));
+ }
return info_ptr;
}
/* read dwarf information from a buffer */
static unsigned int
-read_1_byte (abfd, buf)
- bfd *abfd;
- char *buf;
+read_1_byte (bfd *abfd, char *buf)
{
return bfd_get_8 (abfd, (bfd_byte *) buf);
}
static int
-read_1_signed_byte (abfd, buf)
- bfd *abfd;
- char *buf;
+read_1_signed_byte (bfd *abfd, char *buf)
{
return bfd_get_signed_8 (abfd, (bfd_byte *) buf);
}
static unsigned int
-read_2_bytes (abfd, buf)
- bfd *abfd;
- char *buf;
+read_2_bytes (bfd *abfd, char *buf)
{
return bfd_get_16 (abfd, (bfd_byte *) buf);
}
static int
-read_2_signed_bytes (abfd, buf)
- bfd *abfd;
- char *buf;
+read_2_signed_bytes (bfd *abfd, char *buf)
{
return bfd_get_signed_16 (abfd, (bfd_byte *) buf);
}
static unsigned int
-read_4_bytes (abfd, buf)
- bfd *abfd;
- char *buf;
+read_4_bytes (bfd *abfd, char *buf)
{
return bfd_get_32 (abfd, (bfd_byte *) buf);
}
static int
-read_4_signed_bytes (abfd, buf)
- bfd *abfd;
- char *buf;
+read_4_signed_bytes (bfd *abfd, char *buf)
{
return bfd_get_signed_32 (abfd, (bfd_byte *) buf);
}
-static unsigned int
-read_8_bytes (abfd, buf)
- bfd *abfd;
- char *buf;
+static unsigned long
+read_8_bytes (bfd *abfd, char *buf)
{
return bfd_get_64 (abfd, (bfd_byte *) buf);
}
static CORE_ADDR
-read_address (abfd, buf)
- bfd *abfd;
- char *buf;
+read_address (bfd *abfd, char *buf, const struct comp_unit_head *cu_header,
+ int *bytes_read)
{
CORE_ADDR retval = 0;
- if (address_size == 4)
+ if (cu_header->signed_addr_p)
+ {
+ switch (cu_header->addr_size)
+ {
+ case 2:
+ retval = bfd_get_signed_16 (abfd, (bfd_byte *) buf);
+ break;
+ case 4:
+ retval = bfd_get_signed_32 (abfd, (bfd_byte *) buf);
+ break;
+ case 8:
+ retval = bfd_get_signed_64 (abfd, (bfd_byte *) buf);
+ break;
+ default:
+ internal_error ("read_address: bad switch, signed");
+ }
+ }
+ else
+ {
+ switch (cu_header->addr_size)
+ {
+ case 2:
+ retval = bfd_get_16 (abfd, (bfd_byte *) buf);
+ break;
+ case 4:
+ retval = bfd_get_32 (abfd, (bfd_byte *) buf);
+ break;
+ case 8:
+ retval = bfd_get_64 (abfd, (bfd_byte *) buf);
+ break;
+ default:
+ internal_error ("read_address: bad switch, unsigned");
+ }
+ }
+
+ *bytes_read = cu_header->addr_size;
+ return retval;
+}
+
+/* Reads the initial length from a section. The (draft) DWARF 2.1
+ specification allows the initial length to take up either 4 bytes
+ or 12 bytes. If the first 4 bytes are 0xffffffff, then the next 8
+ bytes describe the length and all offsets will be 8 bytes in length
+ instead of 4.
+
+ The value returned via bytes_read should be used to increment
+ the relevant pointer after calling read_initial_length().
+
+ As a side effect, this function sets the fields initial_length_size
+ and offset_size in cu_header to the values appropriate for the
+ length field. (The format of the initial length field determines
+ the width of file offsets to be fetched later with fetch_offset().)
+
+ [ Note: read_initial_length() and read_offset() are based on the
+ document entitled "DWARF Debugging Information Format", revision
+ 2.1, draft 4, dated July 20, 2000. This document was obtained
+ from:
+
+ http://reality.sgi.com/dehnert_engr/dwarf/dwarf2p1-draft4-000720.pdf
+
+ This document is only a draft and is subject to change. (So beware.)
+
+ - Kevin, Aug 4, 2000
+ ] */
+
+static LONGEST
+read_initial_length (bfd *abfd, char *buf, struct comp_unit_head *cu_header,
+ int *bytes_read)
+{
+ LONGEST retval = 0;
+
+ retval = bfd_get_32 (abfd, (bfd_byte *) buf);
+
+ if (retval == 0xffffffff)
{
+ retval = bfd_get_64 (abfd, (bfd_byte *) buf + 4);
+ *bytes_read = 12;
+ if (cu_header != NULL)
+ {
+ cu_header->initial_length_size = 12;
+ cu_header->offset_size = 8;
+ }
+ }
+ else
+ {
+ *bytes_read = 4;
+ if (cu_header != NULL)
+ {
+ cu_header->initial_length_size = 4;
+ cu_header->offset_size = 4;
+ }
+ }
+
+ return retval;
+}
+
+/* Read an offset from the data stream. The size of the offset is
+ given by cu_header->offset_size. */
+
+static LONGEST
+read_offset (bfd *abfd, char *buf, const struct comp_unit_head *cu_header,
+ int *bytes_read)
+{
+ LONGEST retval = 0;
+
+ switch (cu_header->offset_size)
+ {
+ case 4:
retval = bfd_get_32 (abfd, (bfd_byte *) buf);
- } else { /* *THE* alternative is 8, right? */
+ *bytes_read = 4;
+ break;
+ case 8:
retval = bfd_get_64 (abfd, (bfd_byte *) buf);
+ *bytes_read = 8;
+ break;
+ default:
+ internal_error ("read_offset: bad switch");
}
- return retval;
+
+ return retval;
}
static char *
-read_n_bytes (abfd, buf, size)
- bfd * abfd;
- char *buf;
- unsigned int size;
+read_n_bytes (bfd *abfd, char *buf, unsigned int size)
{
/* 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
}
static char *
-read_string (abfd, buf, bytes_read_ptr)
- bfd *abfd;
- char *buf;
- unsigned int *bytes_read_ptr;
+read_string (bfd *abfd, char *buf, unsigned int *bytes_read_ptr)
{
/* 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
#endif
}
-static unsigned int
-read_unsigned_leb128 (abfd, buf, bytes_read_ptr)
- bfd *abfd;
- char *buf;
- unsigned int *bytes_read_ptr;
+static unsigned long
+read_unsigned_leb128 (bfd *abfd, char *buf, unsigned int *bytes_read_ptr)
{
- unsigned int result, num_read;
+ unsigned long result;
+ unsigned int num_read;
int i, shift;
unsigned char byte;
byte = bfd_get_8 (abfd, (bfd_byte *) buf);
buf++;
num_read++;
- result |= ((byte & 127) << shift);
+ result |= ((unsigned long)(byte & 127) << shift);
if ((byte & 128) == 0)
{
break;
return result;
}
-static int
-read_signed_leb128 (abfd, buf, bytes_read_ptr)
- bfd *abfd;
- char *buf;
- unsigned int *bytes_read_ptr;
+static long
+read_signed_leb128 (bfd *abfd, char *buf, unsigned int *bytes_read_ptr)
{
- int result;
+ long result;
int i, shift, size, num_read;
unsigned char byte;
byte = bfd_get_8 (abfd, (bfd_byte *) buf);
buf++;
num_read++;
- result |= ((byte & 127) << shift);
+ result |= ((long)(byte & 127) << shift);
shift += 7;
if ((byte & 128) == 0)
{
}
static void
-set_cu_language (lang)
- unsigned int lang;
+set_cu_language (unsigned int lang)
{
switch (lang)
{
case DW_LANG_C89:
case DW_LANG_C:
- case DW_LANG_Fortran77:
cu_language = language_c;
break;
case DW_LANG_C_plus_plus:
cu_language = language_cplus;
break;
+ case DW_LANG_Fortran77:
+ case DW_LANG_Fortran90:
+ cu_language = language_fortran;
+ break;
case DW_LANG_Mips_Assembler:
cu_language = language_asm;
break;
case DW_LANG_Ada83:
case DW_LANG_Cobol74:
case DW_LANG_Cobol85:
-#if 0
- case DW_LANG_Fortran77: /* moved up top for now */
-#endif
- case DW_LANG_Fortran90:
case DW_LANG_Pascal83:
case DW_LANG_Modula2:
default:
/* Return the named attribute or NULL if not there. */
static struct attribute *
-dwarf_attr (die, name)
- struct die_info *die;
- unsigned int name;
+dwarf_attr (struct die_info *die, unsigned int name)
{
unsigned int i;
struct attribute *spec = NULL;
if (spec)
{
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)
return dwarf_attr (ref_die, name);
}
-
+
return NULL;
}
+static int
+die_is_declaration (struct die_info *die)
+{
+ return (dwarf_attr (die, DW_AT_declaration)
+ && ! dwarf_attr (die, DW_AT_specification));
+}
+
/* Decode the line number information for the compilation unit whose
line number info is at OFFSET in the .debug_line section.
The compilation directory of the file is passed in COMP_DIR. */
{
unsigned int num_files;
struct fileinfo
- {
- char *name;
- unsigned int dir;
- unsigned int time;
- unsigned int size;
- }
- *files;
+ {
+ char *name;
+ unsigned int dir;
+ unsigned int time;
+ unsigned int size;
+ }
+ *files;
};
struct directories
-{
- unsigned int num_dirs;
- char **dirs;
-};
+ {
+ unsigned int num_dirs;
+ char **dirs;
+ };
static void
-dwarf_decode_lines (offset, comp_dir, abfd)
- unsigned int offset;
- char *comp_dir;
- bfd *abfd;
+dwarf_decode_lines (unsigned int offset, char *comp_dir, bfd *abfd,
+ const struct comp_unit_head *cu_header)
{
char *line_ptr;
char *line_end;
line_ptr = dwarf_line_buffer + offset;
/* read in the prologue */
- lh.total_length = read_4_bytes (abfd, line_ptr);
- line_ptr += 4;
+ lh.total_length = read_initial_length (abfd, line_ptr, NULL, &bytes_read);
+ line_ptr += bytes_read;
line_end = line_ptr + lh.total_length;
lh.version = read_2_bytes (abfd, line_ptr);
line_ptr += 2;
- lh.prologue_length = read_4_bytes (abfd, line_ptr);
- line_ptr += 4;
+ lh.prologue_length = read_offset (abfd, line_ptr, cu_header, &bytes_read);
+ line_ptr += bytes_read;
lh.minimum_instruction_length = read_1_byte (abfd, line_ptr);
line_ptr += 1;
lh.default_is_stmt = read_1_byte (abfd, line_ptr);
files.files = (struct fileinfo *)
xrealloc (files.files,
(files.num_files + FILE_ALLOC_CHUNK)
- * sizeof (struct fileinfo));
+ * sizeof (struct fileinfo));
if (files.num_files == 0)
make_cleanup (free_current_contents, &files.files);
}
while (line_ptr < line_end)
{
/* state machine registers */
- unsigned int address = 0;
+ CORE_ADDR address = 0;
unsigned int file = 1;
unsigned int line = 1;
unsigned int column = 0;
}
/* Decode the table. */
- while (! end_sequence)
+ while (!end_sequence)
{
op_code = read_1_byte (abfd, line_ptr);
line_ptr += 1;
{
case DW_LNE_end_sequence:
end_sequence = 1;
- record_line (current_subfile, line, address);
+ /* Don't call record_line here. The end_sequence
+ instruction provides the address of the first byte
+ *after* the last line in the sequence; it's not the
+ address of any real source line. However, the GDB
+ linetable structure only records the starts of lines,
+ not the ends. This is a weakness of GDB. */
break;
case DW_LNE_set_address:
- address = read_address (abfd, line_ptr) + baseaddr;
- line_ptr += address_size;
+ address = read_address (abfd, line_ptr, cu_header, &bytes_read);
+ line_ptr += bytes_read;
+ address += baseaddr;
break;
case DW_LNE_define_file:
cur_file = read_string (abfd, line_ptr, &bytes_read);
files.files = (struct fileinfo *)
xrealloc (files.files,
(files.num_files + FILE_ALLOC_CHUNK)
- * sizeof (struct fileinfo));
+ * sizeof (struct fileinfo));
if (files.num_files == 0)
make_cleanup (free_current_contents, &files.files);
}
break;
case DW_LNS_set_file:
/* 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);
line_ptr += bytes_read;
dwarf2_start_subfile
case DW_LNS_set_basic_block:
basic_block = 1;
break;
+ /* Add to the address register of the state machine the
+ address increment value corresponding to special opcode
+ 255. Ie, this value is scaled by the minimum instruction
+ length since special opcode 255 would have scaled the
+ the increment. */
case DW_LNS_const_add_pc:
- address += (255 - lh.opcode_base) / lh.line_range;
+ address += (lh.minimum_instruction_length
+ * ((255 - lh.opcode_base) / lh.line_range));
break;
case DW_LNS_fixed_advance_pc:
address += read_2_bytes (abfd, line_ptr);
/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:
- DW_AT_name: /srcdir/list0.c
- DW_AT_comp_dir: /compdir
- files.files[0].name: list0.h
- files.files[0].dir: /srcdir
- files.files[1].name: list0.c
- files.files[1].dir: /srcdir
+ DW_AT_name: /srcdir/list0.c
+ DW_AT_comp_dir: /compdir
+ files.files[0].name: list0.h
+ files.files[0].dir: /srcdir
+ files.files[1].name: list0.c
+ files.files[1].dir: /srcdir
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. */
static void
-dwarf2_start_subfile (filename, dirname)
- char *filename;
- char *dirname;
+dwarf2_start_subfile (char *filename, char *dirname)
{
/* If the filename isn't absolute, try to match an existing subfile
with the full pathname. */
if (STREQ (subfile->name, fullname))
{
current_subfile = subfile;
- free (fullname);
+ xfree (fullname);
return;
}
}
- free (fullname);
+ xfree (fullname);
}
start_subfile (filename, dirname);
}
to make a symbol table entry for it, and if so, create a new entry
and return a pointer to it.
If TYPE is NULL, determine symbol type from the die, otherwise
- used the passed type.
- */
+ used the passed type. */
static struct symbol *
-new_symbol (die, type, objfile)
- struct die_info *die;
- struct type *type;
- struct objfile *objfile;
+new_symbol (struct die_info *die, struct type *type, struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
{
struct symbol *sym = NULL;
+ char *name;
struct attribute *attr = NULL;
struct attribute *attr2 = NULL;
CORE_ADDR addr;
- attr = dwarf_attr (die, DW_AT_name);
- if (attr)
+ name = dwarf2_linkage_name (die);
+ if (name)
{
sym = (struct symbol *) obstack_alloc (&objfile->symbol_obstack,
sizeof (struct symbol));
OBJSTAT (objfile, n_syms++);
memset (sym, 0, sizeof (struct symbol));
- SYMBOL_NAME (sym) = obsavestring (DW_STRING (attr),
- strlen (DW_STRING (attr)),
+ SYMBOL_NAME (sym) = obsavestring (name, strlen (name),
&objfile->symbol_obstack);
/* 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_CLASS (sym) = LOC_STATIC;
if (type != NULL)
SYMBOL_TYPE (sym) = type;
else
- SYMBOL_TYPE (sym) = die_type (die, objfile);
+ SYMBOL_TYPE (sym) = die_type (die, objfile, cu_header);
attr = dwarf_attr (die, DW_AT_decl_line);
if (attr)
{
attr = dwarf_attr (die, DW_AT_low_pc);
if (attr)
{
- SYMBOL_VALUE_ADDRESS (sym) = DW_ADDR (attr);
+ SYMBOL_VALUE_ADDRESS (sym) = DW_ADDR (attr) + baseaddr;
}
SYMBOL_CLASS (sym) = LOC_LABEL;
break;
case DW_TAG_subprogram:
- attr = dwarf_attr (die, DW_AT_low_pc);
- if (attr)
- {
- SYMBOL_VALUE_ADDRESS (sym) = DW_ADDR (attr);
- }
+ /* SYMBOL_BLOCK_VALUE (sym) will be filled in later by
+ finish_block. */
SYMBOL_CLASS (sym) = LOC_BLOCK;
attr2 = dwarf_attr (die, DW_AT_external);
if (attr2 && (DW_UNSND (attr2) != 0))
TARGET_INT_BIT / HOST_CHAR_BIT, 0,
"<variable, no debug info>",
objfile);
+ attr = dwarf_attr (die, DW_AT_const_value);
+ if (attr)
+ {
+ dwarf2_const_value (attr, sym, objfile, cu_header);
+ attr2 = dwarf_attr (die, DW_AT_external);
+ if (attr2 && (DW_UNSND (attr2) != 0))
+ add_symbol_to_list (sym, &global_symbols);
+ else
+ add_symbol_to_list (sym, list_in_scope);
+ break;
+ }
attr = dwarf_attr (die, DW_AT_location);
if (attr)
{
if (attr2 && (DW_UNSND (attr2) != 0))
{
SYMBOL_VALUE_ADDRESS (sym) =
- decode_locdesc (DW_BLOCK (attr), objfile);
+ decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
add_symbol_to_list (sym, &global_symbols);
- SYMBOL_CLASS (sym) = LOC_STATIC;
- SYMBOL_VALUE_ADDRESS (sym) += baseaddr;
+
+ /* In shared libraries the address of the variable
+ in the location descriptor might still be relocatable,
+ so its value could be zero.
+ Enter the symbol as a LOC_UNRESOLVED symbol, if its
+ value is zero, the address of the variable will then
+ be determined from the minimal symbol table whenever
+ the variable is referenced. */
+ if (SYMBOL_VALUE_ADDRESS (sym))
+ {
+ fixup_symbol_section (sym, objfile);
+ SYMBOL_VALUE_ADDRESS (sym) +=
+ ANOFFSET (objfile->section_offsets,
+ SYMBOL_SECTION (sym));
+ SYMBOL_CLASS (sym) = LOC_STATIC;
+ }
+ else
+ SYMBOL_CLASS (sym) = LOC_UNRESOLVED;
}
else
{
SYMBOL_VALUE (sym) = addr =
- decode_locdesc (DW_BLOCK (attr), objfile);
+ decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
add_symbol_to_list (sym, list_in_scope);
if (optimized_out)
{
else if (isreg)
{
SYMBOL_CLASS (sym) = LOC_REGISTER;
+ SYMBOL_VALUE (sym) =
+ DWARF2_REG_TO_REGNUM (SYMBOL_VALUE (sym));
}
else if (offreg)
{
SYMBOL_CLASS (sym) = LOC_BASEREG;
- SYMBOL_BASEREG (sym) = basereg;
+ SYMBOL_BASEREG (sym) = DWARF2_REG_TO_REGNUM (basereg);
}
else if (islocal)
{
}
else
{
+ fixup_symbol_section (sym, objfile);
+ SYMBOL_VALUE_ADDRESS (sym) =
+ addr + ANOFFSET (objfile->section_offsets,
+ SYMBOL_SECTION (sym));
SYMBOL_CLASS (sym) = LOC_STATIC;
- SYMBOL_VALUE_ADDRESS (sym) = addr + baseaddr;
}
}
}
else
{
/* We do not know the address of this symbol.
- If it is an external symbol and we have type information
- it, enter the symbol as a LOC_UNRESOLVED symbol.
- The address of the variable will then be determined from
- the minimal symbol table whenever the variable is
- referenced. */
+ If it is an external symbol and we have type information
+ for it, enter the symbol as a LOC_UNRESOLVED symbol.
+ The address of the variable will then be determined from
+ the minimal symbol table whenever the variable is
+ referenced. */
attr2 = dwarf_attr (die, DW_AT_external);
if (attr2 && (DW_UNSND (attr2) != 0)
&& dwarf_attr (die, DW_AT_type) != NULL)
break;
case DW_TAG_formal_parameter:
attr = dwarf_attr (die, DW_AT_location);
- if (attr != NULL)
- {
- SYMBOL_VALUE (sym) = decode_locdesc (DW_BLOCK (attr), objfile);
- }
- add_symbol_to_list (sym, list_in_scope);
- if (isreg)
- {
- SYMBOL_CLASS (sym) = LOC_REGPARM;
- }
- else if (offreg)
+ if (attr)
{
- SYMBOL_CLASS (sym) = LOC_BASEREG_ARG;
- SYMBOL_BASEREG (sym) = basereg;
+ SYMBOL_VALUE (sym) =
+ decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
+ if (isreg)
+ {
+ SYMBOL_CLASS (sym) = LOC_REGPARM;
+ SYMBOL_VALUE (sym) =
+ DWARF2_REG_TO_REGNUM (SYMBOL_VALUE (sym));
+ }
+ else if (offreg)
+ {
+ if (isderef)
+ {
+ if (basereg != frame_base_reg)
+ complain (&dwarf2_complex_location_expr);
+ SYMBOL_CLASS (sym) = LOC_REF_ARG;
+ }
+ else
+ {
+ SYMBOL_CLASS (sym) = LOC_BASEREG_ARG;
+ SYMBOL_BASEREG (sym) = DWARF2_REG_TO_REGNUM (basereg);
+ }
+ }
+ else
+ {
+ SYMBOL_CLASS (sym) = LOC_ARG;
+ }
}
- else
+ attr = dwarf_attr (die, DW_AT_const_value);
+ if (attr)
{
- SYMBOL_CLASS (sym) = LOC_ARG;
+ dwarf2_const_value (attr, sym, objfile, cu_header);
}
+ add_symbol_to_list (sym, list_in_scope);
break;
case DW_TAG_unspecified_parameters:
/* From varargs functions; gdb doesn't seem to have any
if (cu_language == language_cplus)
{
struct symbol *typedef_sym = (struct symbol *)
- obstack_alloc (&objfile->symbol_obstack,
- sizeof (struct symbol));
+ obstack_alloc (&objfile->symbol_obstack,
+ sizeof (struct symbol));
*typedef_sym = *sym;
SYMBOL_NAMESPACE (typedef_sym) = VAR_NAMESPACE;
if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0)
}
break;
case DW_TAG_typedef:
+ case DW_TAG_base_type:
SYMBOL_CLASS (sym) = LOC_TYPEDEF;
SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
add_symbol_to_list (sym, list_in_scope);
break;
case DW_TAG_enumerator:
- SYMBOL_CLASS (sym) = LOC_CONST;
attr = dwarf_attr (die, DW_AT_const_value);
if (attr)
{
- SYMBOL_VALUE (sym) = DW_UNSND (attr);
+ dwarf2_const_value (attr, sym, objfile, cu_header);
}
add_symbol_to_list (sym, list_in_scope);
break;
return (sym);
}
+/* Copy constant value from an attribute to a symbol. */
+
+static void
+dwarf2_const_value (struct attribute *attr, struct symbol *sym,
+ struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
+{
+ struct dwarf_block *blk;
+
+ switch (attr->form)
+ {
+ case DW_FORM_addr:
+ if (TYPE_LENGTH (SYMBOL_TYPE (sym)) != cu_header->addr_size)
+ complain (&dwarf2_const_value_length_mismatch, SYMBOL_NAME (sym),
+ cu_header->addr_size, TYPE_LENGTH (SYMBOL_TYPE (sym)));
+ SYMBOL_VALUE_BYTES (sym) = (char *)
+ obstack_alloc (&objfile->symbol_obstack, cu_header->addr_size);
+ store_address (SYMBOL_VALUE_BYTES (sym), cu_header->addr_size,
+ DW_ADDR (attr));
+ SYMBOL_CLASS (sym) = LOC_CONST_BYTES;
+ break;
+ case DW_FORM_block1:
+ case DW_FORM_block2:
+ case DW_FORM_block4:
+ case DW_FORM_block:
+ blk = DW_BLOCK (attr);
+ if (TYPE_LENGTH (SYMBOL_TYPE (sym)) != blk->size)
+ complain (&dwarf2_const_value_length_mismatch, SYMBOL_NAME (sym),
+ blk->size, TYPE_LENGTH (SYMBOL_TYPE (sym)));
+ SYMBOL_VALUE_BYTES (sym) = (char *)
+ obstack_alloc (&objfile->symbol_obstack, blk->size);
+ memcpy (SYMBOL_VALUE_BYTES (sym), blk->data, blk->size);
+ SYMBOL_CLASS (sym) = LOC_CONST_BYTES;
+ break;
+
+ /* The DW_AT_const_value attributes are supposed to carry the
+ symbol's value "represented as it would be on the target
+ architecture." By the time we get here, it's already been
+ converted to host endianness, so we just need to sign- or
+ zero-extend it as appropriate. */
+ case DW_FORM_data1:
+ dwarf2_const_value_data (attr, sym, 8);
+ break;
+ case DW_FORM_data2:
+ dwarf2_const_value_data (attr, sym, 16);
+ break;
+ case DW_FORM_data4:
+ dwarf2_const_value_data (attr, sym, 32);
+ break;
+ case DW_FORM_data8:
+ dwarf2_const_value_data (attr, sym, 64);
+ break;
+
+ case DW_FORM_sdata:
+ SYMBOL_VALUE (sym) = DW_SND (attr);
+ SYMBOL_CLASS (sym) = LOC_CONST;
+ break;
+
+ case DW_FORM_udata:
+ SYMBOL_VALUE (sym) = DW_UNSND (attr);
+ SYMBOL_CLASS (sym) = LOC_CONST;
+ break;
+
+ default:
+ complain (&dwarf2_unsupported_const_value_attr,
+ dwarf_form_name (attr->form));
+ SYMBOL_VALUE (sym) = 0;
+ SYMBOL_CLASS (sym) = LOC_CONST;
+ break;
+ }
+}
+
+
+/* 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. */
+static void
+dwarf2_const_value_data (struct attribute *attr,
+ struct symbol *sym,
+ int bits)
+{
+ LONGEST l = DW_UNSND (attr);
+
+ if (bits < sizeof (l) * 8)
+ {
+ if (TYPE_UNSIGNED (SYMBOL_TYPE (sym)))
+ l &= ((LONGEST) 1 << bits) - 1;
+ else
+ l = (l << (sizeof (l) * 8 - bits)) >> (sizeof (l) * 8 - bits);
+ }
+
+ SYMBOL_VALUE (sym) = l;
+ SYMBOL_CLASS (sym) = LOC_CONST;
+}
+
+
/* Return the type of the die in question using its DW_AT_type attribute. */
static struct type *
-die_type (die, objfile)
- struct die_info *die;
- struct objfile *objfile;
+die_type (struct die_info *die, struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
{
struct type *type;
struct attribute *type_attr;
return NULL;
}
}
- type = tag_type_to_type (type_die, objfile);
+ type = tag_type_to_type (type_die, objfile, cu_header);
if (!type)
{
dump_die (type_die);
DW_AT_containing_type attribute. */
static struct type *
-die_containing_type (die, objfile)
- struct die_info *die;
- struct objfile *objfile;
+die_containing_type (struct die_info *die, struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
{
struct type *type = NULL;
struct attribute *type_attr;
error ("Dwarf Error: Cannot find referent at offset %d.", ref);
return NULL;
}
- type = tag_type_to_type (type_die, objfile);
+ type = tag_type_to_type (type_die, objfile, cu_header);
}
if (!type)
{
#if 0
static struct type *
-type_at_offset (offset, objfile)
- unsigned int offset;
- struct objfile *objfile;
+type_at_offset (unsigned int offset, struct objfile *objfile)
{
struct die_info *die;
struct type *type;
#endif
static struct type *
-tag_type_to_type (die, objfile)
- struct die_info *die;
- struct objfile *objfile;
+tag_type_to_type (struct die_info *die, struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
{
if (die->type)
{
}
else
{
- read_type_die (die, objfile);
+ read_type_die (die, objfile, cu_header);
if (!die->type)
{
dump_die (die);
}
static void
-read_type_die (die, objfile)
- struct die_info *die;
- struct objfile *objfile;
+read_type_die (struct die_info *die, struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
{
switch (die->tag)
{
case DW_TAG_class_type:
case DW_TAG_structure_type:
case DW_TAG_union_type:
- read_structure_scope (die, objfile);
+ read_structure_scope (die, objfile, cu_header);
break;
case DW_TAG_enumeration_type:
- read_enumeration (die, objfile);
+ read_enumeration (die, objfile, cu_header);
break;
case DW_TAG_subprogram:
case DW_TAG_subroutine_type:
- read_subroutine_type (die, objfile);
+ read_subroutine_type (die, objfile, cu_header);
break;
case DW_TAG_array_type:
- dwarf_read_array_type (die, objfile);
+ read_array_type (die, objfile, cu_header);
break;
case DW_TAG_pointer_type:
- read_tag_pointer_type (die, objfile);
+ read_tag_pointer_type (die, objfile, cu_header);
break;
case DW_TAG_ptr_to_member_type:
- read_tag_ptr_to_member_type (die, objfile);
+ read_tag_ptr_to_member_type (die, objfile, cu_header);
break;
case DW_TAG_reference_type:
- read_tag_reference_type (die, objfile);
+ read_tag_reference_type (die, objfile, cu_header);
break;
case DW_TAG_const_type:
- read_tag_const_type (die, objfile);
+ read_tag_const_type (die, objfile, cu_header);
break;
case DW_TAG_volatile_type:
- read_tag_volatile_type (die, objfile);
+ read_tag_volatile_type (die, objfile, cu_header);
break;
case DW_TAG_string_type:
read_tag_string_type (die, objfile);
break;
case DW_TAG_typedef:
- read_typedef (die, objfile);
+ read_typedef (die, objfile, cu_header);
break;
case DW_TAG_base_type:
read_base_type (die, objfile);
break;
- case DW_TAG_padding:
- case DW_TAG_compile_unit:
- case DW_TAG_lexical_block:
default:
+ complain (&dwarf2_unexpected_tag, dwarf_tag_name (die->tag));
break;
}
}
static struct type *
-dwarf_base_type (encoding, size)
- int encoding;
- int size;
+dwarf_base_type (int encoding, int size, struct objfile *objfile)
{
/* FIXME - this should not produce a new (struct type *)
every time. It should cache base types. */
switch (encoding)
{
case DW_ATE_address:
- type = dwarf2_fundamental_type (current_objfile, FT_VOID);
+ type = dwarf2_fundamental_type (objfile, FT_VOID);
return type;
case DW_ATE_boolean:
- type = dwarf2_fundamental_type (current_objfile, FT_BOOLEAN);
+ type = dwarf2_fundamental_type (objfile, FT_BOOLEAN);
return type;
case DW_ATE_complex_float:
if (size == 16)
{
- type = dwarf2_fundamental_type (current_objfile, FT_DBL_PREC_COMPLEX);
+ type = dwarf2_fundamental_type (objfile, FT_DBL_PREC_COMPLEX);
}
else
{
- type = dwarf2_fundamental_type (current_objfile, FT_COMPLEX);
+ type = dwarf2_fundamental_type (objfile, FT_COMPLEX);
}
return type;
case DW_ATE_float:
if (size == 8)
{
- type = dwarf2_fundamental_type (current_objfile, FT_DBL_PREC_FLOAT);
+ type = dwarf2_fundamental_type (objfile, FT_DBL_PREC_FLOAT);
}
else
{
- type = dwarf2_fundamental_type (current_objfile, FT_FLOAT);
+ type = dwarf2_fundamental_type (objfile, FT_FLOAT);
}
return type;
case DW_ATE_signed:
switch (size)
{
case 1:
- type = dwarf2_fundamental_type (current_objfile, FT_SIGNED_CHAR);
+ type = dwarf2_fundamental_type (objfile, FT_SIGNED_CHAR);
break;
case 2:
- type = dwarf2_fundamental_type (current_objfile, FT_SIGNED_SHORT);
+ type = dwarf2_fundamental_type (objfile, FT_SIGNED_SHORT);
break;
default:
case 4:
- type = dwarf2_fundamental_type (current_objfile, FT_SIGNED_INTEGER);
+ type = dwarf2_fundamental_type (objfile, FT_SIGNED_INTEGER);
break;
}
return type;
case DW_ATE_signed_char:
- type = dwarf2_fundamental_type (current_objfile, FT_SIGNED_CHAR);
+ type = dwarf2_fundamental_type (objfile, FT_SIGNED_CHAR);
return type;
case DW_ATE_unsigned:
switch (size)
{
case 1:
- type = dwarf2_fundamental_type (current_objfile, FT_UNSIGNED_CHAR);
+ type = dwarf2_fundamental_type (objfile, FT_UNSIGNED_CHAR);
break;
case 2:
- type = dwarf2_fundamental_type (current_objfile, FT_UNSIGNED_SHORT);
+ type = dwarf2_fundamental_type (objfile, FT_UNSIGNED_SHORT);
break;
default:
case 4:
- type = dwarf2_fundamental_type (current_objfile, FT_UNSIGNED_INTEGER);
+ type = dwarf2_fundamental_type (objfile, FT_UNSIGNED_INTEGER);
break;
}
return type;
case DW_ATE_unsigned_char:
- type = dwarf2_fundamental_type (current_objfile, FT_UNSIGNED_CHAR);
+ type = dwarf2_fundamental_type (objfile, FT_UNSIGNED_CHAR);
return type;
default:
- type = dwarf2_fundamental_type (current_objfile, FT_SIGNED_INTEGER);
+ type = dwarf2_fundamental_type (objfile, FT_SIGNED_INTEGER);
return type;
}
}
#if 0
struct die_info *
-copy_die (old_die)
- struct die_info *old_die;
+copy_die (struct die_info *old_die)
{
struct die_info *new_die;
int i, num_attrs;
/* Return sibling of die, NULL if no sibling. */
struct die_info *
-sibling_die (die)
- struct die_info *die;
+sibling_die (struct die_info *die)
{
int nesting_level = 0;
}
}
+/* Get linkage name of a die, return NULL if not found. */
+
+static char *
+dwarf2_linkage_name (struct die_info *die)
+{
+ struct attribute *attr;
+
+ attr = dwarf_attr (die, DW_AT_MIPS_linkage_name);
+ if (attr && DW_STRING (attr))
+ return DW_STRING (attr);
+ attr = dwarf_attr (die, DW_AT_name);
+ if (attr && DW_STRING (attr))
+ return DW_STRING (attr);
+ return NULL;
+}
+
/* Convert a DIE tag into its string name. */
static char *
-dwarf_tag_name (tag)
- register unsigned tag;
+dwarf_tag_name (register unsigned tag)
{
switch (tag)
{
/* Convert a DWARF attribute code into its string name. */
static char *
-dwarf_attr_name (attr)
- register unsigned attr;
+dwarf_attr_name (register unsigned attr)
{
switch (attr)
{
/* Convert a DWARF value form code into its string name. */
static char *
-dwarf_form_name (form)
- register unsigned form;
+dwarf_form_name (register unsigned form)
{
switch (form)
{
/* Convert a DWARF stack opcode into its string name. */
static char *
-dwarf_stack_op_name (op)
- register unsigned op;
+dwarf_stack_op_name (register unsigned op)
{
switch (op)
{
}
static char *
-dwarf_bool_name (bool)
- unsigned bool;
+dwarf_bool_name (unsigned mybool)
{
- if (bool)
+ if (mybool)
return "TRUE";
else
return "FALSE";
/* Convert a DWARF type code into its string name. */
static char *
-dwarf_type_encoding_name (enc)
- register unsigned enc;
+dwarf_type_encoding_name (register unsigned enc)
{
switch (enc)
{
#if 0
static char *
-dwarf_cfi_name (cfi_opc)
- register unsigned cfi_opc;
+dwarf_cfi_name (register unsigned cfi_opc)
{
switch (cfi_opc)
{
#endif
void
-dump_die (die)
- struct die_info *die;
+dump_die (struct die_info *die)
{
unsigned int i;
case DW_FORM_ref_addr:
case DW_FORM_addr:
fprintf (stderr, "address: ");
- print_address_numeric (die->attrs[i].u.addr, 1, stderr);
+ print_address_numeric (DW_ADDR (&die->attrs[i]), 1, gdb_stderr);
break;
case DW_FORM_block2:
case DW_FORM_block4:
case DW_FORM_block:
case DW_FORM_block1:
- fprintf (stderr, "block: size %d",
- die->attrs[i].u.blk->size);
+ fprintf (stderr, "block: size %d", DW_BLOCK (&die->attrs[i])->size);
break;
case DW_FORM_data1:
case DW_FORM_data2:
case DW_FORM_data4:
+ case DW_FORM_data8:
case DW_FORM_ref1:
case DW_FORM_ref2:
case DW_FORM_ref4:
case DW_FORM_udata:
case DW_FORM_sdata:
- fprintf (stderr, "constant: %d", die->attrs[i].u.unsnd);
+ fprintf (stderr, "constant: %ld", DW_UNSND (&die->attrs[i]));
break;
case DW_FORM_string:
- fprintf (stderr, "string: \"%s\"", die->attrs[i].u.str);
+ fprintf (stderr, "string: \"%s\"",
+ DW_STRING (&die->attrs[i])
+ ? DW_STRING (&die->attrs[i]) : "");
break;
case DW_FORM_flag:
- if (die->attrs[i].u.unsnd)
+ if (DW_UNSND (&die->attrs[i]))
fprintf (stderr, "flag: TRUE");
else
fprintf (stderr, "flag: FALSE");
case DW_FORM_strp: /* we do not support separate string
section yet */
case DW_FORM_indirect: /* we do not handle indirect yet */
- case DW_FORM_data8: /* we do not have 64 bit quantities */
default:
fprintf (stderr, "unsupported attribute form: %d.",
- die->attrs[i].form);
+ die->attrs[i].form);
}
fprintf (stderr, "\n");
}
}
void
-dump_die_list (die)
- struct die_info *die;
+dump_die_list (struct die_info *die)
{
while (die)
{
}
void
-store_in_ref_table (offset, die)
- unsigned int offset;
- struct die_info *die;
+store_in_ref_table (unsigned int offset, struct die_info *die)
{
int h;
struct die_info *old;
static void
-dwarf2_empty_die_ref_table ()
+dwarf2_empty_hash_tables (void)
{
memset (die_ref_table, 0, sizeof (die_ref_table));
}
static unsigned int
-dwarf2_get_ref_die_offset (attr)
- struct attribute *attr;
+dwarf2_get_ref_die_offset (struct attribute *attr)
{
unsigned int result = 0;
case DW_FORM_ref1:
case DW_FORM_ref2:
case DW_FORM_ref4:
+ case DW_FORM_ref8:
case DW_FORM_ref_udata:
result = cu_header_offset + DW_UNSND (attr);
break;
}
struct die_info *
-follow_die_ref (offset)
- unsigned int offset;
+follow_die_ref (unsigned int offset)
{
struct die_info *die;
int h;
}
static struct type *
-dwarf2_fundamental_type (objfile, typeid)
- struct objfile *objfile;
- int typeid;
+dwarf2_fundamental_type (struct objfile *objfile, int typeid)
{
if (typeid < 0 || typeid >= FT_NUM_MEMBERS)
{
DW_AT_frame_base attribute, the global islocal flag is set.
Hopefully the machine dependent code knows how to set up a virtual
frame pointer for the local references.
-
+
Note that stack[0] is unused except as a default error return.
Note that stack overflow is not yet handled. */
static CORE_ADDR
-decode_locdesc (blk, objfile)
- struct dwarf_block *blk;
- struct objfile *objfile;
+decode_locdesc (struct dwarf_block *blk, struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
{
int i;
int size = blk->size;
stack[stacki] = 0;
isreg = 0;
offreg = 0;
+ isderef = 0;
islocal = 0;
optimized_out = 1;
i += bytes_read;
break;
+ case DW_OP_bregx:
+ offreg = 1;
+ basereg = read_unsigned_leb128 (NULL, (data + i), &bytes_read);
+ i += bytes_read;
+ stack[++stacki] = read_signed_leb128 (NULL, (data + i), &bytes_read);
+ i += bytes_read;
+ break;
+
case DW_OP_fbreg:
stack[++stacki] = read_signed_leb128 (NULL, (data + i), &bytes_read);
i += bytes_read;
break;
case DW_OP_addr:
- stack[++stacki] = read_address (objfile->obfd, &data[i]);
- i += address_size;
+ stack[++stacki] = read_address (objfile->obfd, &data[i],
+ cu_header, &bytes_read);
+ i += bytes_read;
break;
case DW_OP_const1u:
case DW_OP_constu:
stack[++stacki] = read_unsigned_leb128 (NULL, (data + i),
- &bytes_read);
+ &bytes_read);
i += bytes_read;
break;
stacki--;
break;
+ case DW_OP_plus_uconst:
+ stack[stacki] += read_unsigned_leb128 (NULL, (data + i), &bytes_read);
+ i += bytes_read;
+ break;
+
case DW_OP_minus:
stack[stacki - 1] = stack[stacki] - stack[stacki - 1];
stacki--;
break;
+ case DW_OP_deref:
+ isderef = 1;
+ /* If we're not the last op, then we definitely can't encode
+ this using GDB's address_class enum. */
+ if (i < size)
+ complain (&dwarf2_complex_location_expr);
+ break;
+
default:
- complain (&dwarf2_unsupported_stack_op, dwarf_stack_op_name(op));
+ complain (&dwarf2_unsupported_stack_op, dwarf_stack_op_name (op));
return (stack[stacki]);
}
}
/* ARGSUSED */
static void
-dwarf2_free_tmp_obstack (ignore)
- PTR ignore;
+dwarf2_free_tmp_obstack (PTR ignore)
{
obstack_free (&dwarf2_tmp_obstack, NULL);
}
static struct dwarf_block *
-dwarf_alloc_block ()
+dwarf_alloc_block (void)
{
struct dwarf_block *blk;
}
static struct abbrev_info *
-dwarf_alloc_abbrev ()
+dwarf_alloc_abbrev (void)
{
struct abbrev_info *abbrev;
}
static struct die_info *
-dwarf_alloc_die ()
+dwarf_alloc_die (void)
{
struct die_info *die;