/* DWARF 2 debugging format support for GDB.
- Copyright 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+ Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+ Free Software Foundation, Inc.
Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology,
Inc. with support from Florida State University (under contract
#include "defs.h"
#include "bfd.h"
-#include "elf-bfd.h"
#include "symtab.h"
#include "gdbtypes.h"
#include "symfile.h"
#include "buildsym.h"
#include "demangle.h"
#include "expression.h"
+#include "filenames.h" /* for DOSish file names */
+#include "macrotab.h"
+
#include "language.h"
#include "complaints.h"
-
+#include "bcache.h"
#include <fcntl.h>
#include "gdb_string.h"
+#include "gdb_assert.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
static file_ptr dwarf_loc_offset;
static file_ptr dwarf_macinfo_offset;
static file_ptr dwarf_str_offset;
+static file_ptr dwarf_ranges_offset;
+file_ptr dwarf_frame_offset;
+file_ptr dwarf_eh_frame_offset;
static unsigned int dwarf_info_size;
static unsigned int dwarf_abbrev_size;
static unsigned int dwarf_loc_size;
static unsigned int dwarf_macinfo_size;
static unsigned int dwarf_str_size;
+static unsigned int dwarf_ranges_size;
+unsigned int dwarf_frame_size;
+unsigned int dwarf_eh_frame_size;
+
+static asection *dwarf_info_section;
+static asection *dwarf_abbrev_section;
+static asection *dwarf_line_section;
+static asection *dwarf_pubnames_section;
+static asection *dwarf_aranges_section;
+static asection *dwarf_loc_section;
+static asection *dwarf_macinfo_section;
+static asection *dwarf_str_section;
+static asection *dwarf_ranges_section;
+asection *dwarf_frame_section;
+asection *dwarf_eh_frame_section;
/* names of the debugging sections */
#define LOC_SECTION ".debug_loc"
#define MACINFO_SECTION ".debug_macinfo"
#define STR_SECTION ".debug_str"
+#define RANGES_SECTION ".debug_ranges"
+#define FRAME_SECTION ".debug_frame"
+#define EH_FRAME_SECTION ".eh_frame"
/* local data types */
-/* The data in a compilation unit header looks like this. */
+/* We hold several abbreviation tables in memory at the same time. */
+#ifndef ABBREV_HASH_SIZE
+#define ABBREV_HASH_SIZE 121
+#endif
+
+/* The data in a compilation unit header, after target2host
+ translation, looks like this. */
struct comp_unit_head
{
- unsigned int length;
+ unsigned long length;
short version;
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 */
+
+ /* Offset to the first byte of this compilation unit header in the
+ * .debug_info section, for resolving relative reference dies. */
+
+ unsigned int offset;
+
+ /* Pointer to this compilation unit header in the .debug_info
+ * section */
+
+ char *cu_head_ptr;
+
+ /* Pointer to the first die of this compilatio unit. This will
+ * be the first byte following the compilation unit header. */
+
+ char *first_die_ptr;
+
+ /* Pointer to the next compilation unit header in the program. */
+
+ struct comp_unit_head *next;
+
+ /* DWARF abbreviation table associated with this compilation unit */
+
+ struct abbrev_info *dwarf2_abbrevs[ABBREV_HASH_SIZE];
+
+ /* Pointer to the DIE associated with the compilation unit. */
+
+ struct die_info *die;
};
-/* The data in the .debug_line statement prologue looks like this. */
-struct line_head
+/* The line number information for a compilation unit (found in the
+ .debug_line section) begins with a "statement program header",
+ which contains the following information. */
+struct line_header
+{
+ unsigned int total_length;
+ unsigned short version;
+ unsigned int header_length;
+ unsigned char minimum_instruction_length;
+ unsigned char default_is_stmt;
+ int line_base;
+ unsigned char line_range;
+ unsigned char opcode_base;
+
+ /* standard_opcode_lengths[i] is the number of operands for the
+ standard opcode whose value is i. This means that
+ standard_opcode_lengths[0] is unused, and the last meaningful
+ element is standard_opcode_lengths[opcode_base - 1]. */
+ unsigned char *standard_opcode_lengths;
+
+ /* The include_directories table. NOTE! These strings are not
+ allocated with xmalloc; instead, they are pointers into
+ debug_line_buffer. If you try to free them, `free' will get
+ indigestion. */
+ unsigned int num_include_dirs, include_dirs_size;
+ char **include_dirs;
+
+ /* The file_names table. NOTE! These strings are not allocated
+ with xmalloc; instead, they are pointers into debug_line_buffer.
+ Don't try to free them directly. */
+ unsigned int num_file_names, file_names_size;
+ struct file_entry
{
- unsigned int total_length;
- unsigned short version;
- unsigned int prologue_length;
- unsigned char minimum_instruction_length;
- unsigned char default_is_stmt;
- int line_base;
- unsigned char line_range;
- unsigned char opcode_base;
- unsigned char *standard_opcode_lengths;
- };
+ char *name;
+ unsigned int dir_index;
+ unsigned int mod_time;
+ unsigned int length;
+ } *file_names;
+
+ /* The start and end of the statement program following this
+ header. These point into dwarf_line_buffer. */
+ char *statement_program_start, *statement_program_end;
+};
/* When we construct a partial symbol table entry we only
need this much information. */
unsigned int offset;
unsigned int abbrev;
char *name;
+ int has_pc_info;
CORE_ADDR lowpc;
CORE_ADDR highpc;
struct dwarf_block *locdesc;
{
char *str;
struct dwarf_block *blk;
- unsigned int unsnd;
- int snd;
+ unsigned long unsnd;
+ long int snd;
CORE_ADDR addr;
}
u;
};
+struct function_range
+{
+ const char *name;
+ CORE_ADDR lowpc, highpc;
+ int seen_line;
+ struct function_range *next;
+};
+
+static struct function_range *cu_first_fn, *cu_last_fn, *cu_cached_fn;
+
/* Get at parts of an attribute structure */
#define DW_STRING(attr) ((attr)->u.str)
char *data;
};
-/* We only hold one compilation unit's abbrevs in
- memory at any one time. */
-#ifndef ABBREV_HASH_SIZE
-#define ABBREV_HASH_SIZE 121
-#endif
#ifndef ATTR_ALLOC_CHUNK
#define ATTR_ALLOC_CHUNK 4
#endif
-static struct abbrev_info *dwarf2_abbrevs[ABBREV_HASH_SIZE];
-
/* A hash table of die offsets for following references. */
#ifndef REF_HASH_SIZE
#define REF_HASH_SIZE 1021
static char *dwarf_info_buffer;
static char *dwarf_abbrev_buffer;
static char *dwarf_line_buffer;
+static char *dwarf_str_buffer;
+static char *dwarf_macinfo_buffer;
+static char *dwarf_ranges_buffer;
/* A zeroed version of a partial die for initialization purposes. */
static struct partial_die_info zeroed_partial_die;
this function, so we can't say
which register it's relative to;
use LOC_LOCAL. */
+static int is_thread_local; /* Variable is at a constant offset in the
+ thread-local storage block for the
+ current thread and the dynamic linker
+ module containing this expression.
+ decode_locdesc returns the offset from
+ that base. */
/* 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 */
/* Pointer to start of dwarf line buffer for the objfile. */
char *dwarf_line_buffer;
+
+ /* Size of dwarf_line_buffer, in bytes. */
+
+ unsigned int dwarf_line_size;
+
+ /* Pointer to start of dwarf string buffer for the objfile. */
+
+ char *dwarf_str_buffer;
+
+ /* Size of dwarf string section for the objfile. */
+
+ unsigned int dwarf_str_size;
+
+ /* Pointer to start of dwarf macro buffer for the objfile. */
+
+ char *dwarf_macinfo_buffer;
+
+ /* Size of dwarf macinfo section for the objfile. */
+
+ unsigned int dwarf_macinfo_size;
+
+ /* Pointer to start of dwarf ranges buffer for the objfile. */
+
+ char *dwarf_ranges_buffer;
+
+ /* Size of dwarf ranges buffer for the objfile. */
+
+ unsigned int dwarf_ranges_size;
+
};
#define PST_PRIVATE(p) ((struct dwarf2_pinfo *)(p)->read_symtab_private)
#define DWARF_ABBREV_BUFFER(p) (PST_PRIVATE(p)->dwarf_abbrev_buffer)
#define DWARF_ABBREV_SIZE(p) (PST_PRIVATE(p)->dwarf_abbrev_size)
#define DWARF_LINE_BUFFER(p) (PST_PRIVATE(p)->dwarf_line_buffer)
+#define DWARF_LINE_SIZE(p) (PST_PRIVATE(p)->dwarf_line_size)
+#define DWARF_STR_BUFFER(p) (PST_PRIVATE(p)->dwarf_str_buffer)
+#define DWARF_STR_SIZE(p) (PST_PRIVATE(p)->dwarf_str_size)
+#define DWARF_MACINFO_BUFFER(p) (PST_PRIVATE(p)->dwarf_macinfo_buffer)
+#define DWARF_MACINFO_SIZE(p) (PST_PRIVATE(p)->dwarf_macinfo_size)
+#define DWARF_RANGES_BUFFER(p) (PST_PRIVATE(p)->dwarf_ranges_buffer)
+#define DWARF_RANGES_SIZE(p) (PST_PRIVATE(p)->dwarf_ranges_size)
/* Maintain an array of referenced fundamental types for the current
compilation unit being read. For DWARF version 1, we have to construct
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 =
-{
- "type qualifier 'const' ignored", 0, 0
-};
-static struct complaint dwarf2_volatile_ignored =
-{
- "type qualifier 'volatile' ignored", 0, 0
-};
-static struct complaint dwarf2_non_const_array_bound_ignored =
-{
- "non-constant array bounds form '%s' ignored", 0, 0
-};
-static struct complaint dwarf2_missing_line_number_section =
-{
- "missing .debug_line section", 0, 0
-};
-static struct complaint dwarf2_mangled_line_number_section =
-{
- "mangled .debug_line section", 0, 0
-};
-static struct complaint dwarf2_unsupported_die_ref_attr =
-{
- "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
-};
-static struct complaint dwarf2_unsupported_at_encoding =
-{
- "unsupported DW_AT_encoding: '%s'", 0, 0
-};
-static struct complaint dwarf2_unsupported_at_frame_base =
-{
- "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
-};
-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 =
+static void
+dwarf2_non_const_array_bound_ignored_complaint (const char *arg1)
{
- "member function type missing for '%s'", 0, 0
-};
-static struct complaint dwarf2_vtbl_not_found_complaint =
+ complaint (&symfile_complaints, "non-constant array bounds form '%s' ignored",
+ arg1);
+}
+
+static void
+dwarf2_statement_list_fits_in_line_number_section_complaint (void)
{
- "virtual function table pointer not found when defining class '%s'", 0, 0
-};
-static struct complaint dwarf2_absolute_sibling_complaint =
+ complaint (&symfile_complaints,
+ "statement list doesn't fit in .debug_line section");
+}
+
+static void
+dwarf2_complex_location_expr_complaint (void)
{
- "ignoring absolute DW_AT_sibling", 0, 0
-};
-static struct complaint dwarf2_const_value_length_mismatch =
+ complaint (&symfile_complaints, "location expression too complex");
+}
+
+static void
+dwarf2_unsupported_at_frame_base_complaint (const char *arg1)
{
- "const value length mismatch for '%s', got %d, expected %d", 0, 0
-};
-static struct complaint dwarf2_unsupported_const_value_attr =
+ complaint (&symfile_complaints,
+ "unsupported DW_AT_frame_base for function '%s'", arg1);
+}
+
+static void
+dwarf2_const_value_length_mismatch_complaint (const char *arg1, int arg2,
+ int arg3)
{
- "unsupported const value attribute form: '%s'", 0, 0
-};
+ complaint (&symfile_complaints,
+ "const value length mismatch for '%s', got %d, expected %d", arg1,
+ arg2, arg3);
+}
-/* 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;
+static void
+dwarf2_macros_too_long_complaint (void)
+{
+ complaint (&symfile_complaints,
+ "macro info runs off end of `.debug_macinfo' section");
+}
-/* Some elf32 object file formats while linked for a 32 bit address
- space contain debug information that has assumed 64 bit
- addresses. Eg 64 bit MIPS target produced by GCC/GAS/LD where the
- symbol table contains 32bit address values while its .debug_info
- section contains 64 bit address values.
- ADDRESS_SIGNIFICANT_SIZE specifies the number significant bits in
- the ADDRESS_SIZE bytes read from the file */
-static int address_significant_size;
+static void
+dwarf2_macro_malformed_definition_complaint (const char *arg1)
+{
+ complaint (&symfile_complaints,
+ "macro debug info contains a malformed macro definition:\n`%s'",
+ arg1);
+}
-/* Externals references. */
-extern int info_verbose; /* From main.c; nonzero => verbose */
+static void
+dwarf2_invalid_attrib_class_complaint (const char *arg1, const char *arg2)
+{
+ complaint (&symfile_complaints,
+ "invalid attribute class or form for '%s' in '%s'", arg1, arg2);
+}
/* local function prototypes */
-static void dwarf2_locate_sections PARAMS ((bfd *, asection *, PTR));
+static void dwarf2_locate_sections (bfd *, asection *, void *);
#if 0
-static void dwarf2_build_psymtabs_easy PARAMS ((struct objfile *, int));
+static void dwarf2_build_psymtabs_easy (struct objfile *, int);
#endif
-static void dwarf2_build_psymtabs_hard PARAMS ((struct objfile *, 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 void add_partial_symbol (struct partial_die_info *, struct objfile *,
+ const struct comp_unit_head *);
+
+static void dwarf2_psymtab_to_symtab (struct partial_symtab *);
-static char *scan_partial_symbols PARAMS ((char *, struct objfile *,
- CORE_ADDR *, CORE_ADDR *));
+static void psymtab_to_symtab_1 (struct partial_symtab *);
-static void add_partial_symbol PARAMS ((struct partial_die_info *,
- struct objfile *));
+char *dwarf2_read_section (struct objfile *, file_ptr, unsigned int,
+ asection *);
-static void dwarf2_psymtab_to_symtab PARAMS ((struct partial_symtab *));
+static void dwarf2_read_abbrevs (bfd *abfd, struct comp_unit_head *cu_header);
-static void psymtab_to_symtab_1 PARAMS ((struct partial_symtab *));
+static void dwarf2_empty_abbrev_table (void *);
-static char *dwarf2_read_section PARAMS ((struct objfile *, file_ptr,
- unsigned int));
+static struct abbrev_info *dwarf2_lookup_abbrev (unsigned int,
+ const struct comp_unit_head *cu_header);
-static void dwarf2_read_abbrevs PARAMS ((bfd *, unsigned int));
+static char *read_partial_die (struct partial_die_info *,
+ bfd *, char *,
+ const struct comp_unit_head *);
-static void dwarf2_empty_abbrev_table PARAMS ((PTR));
+static char *read_full_die (struct die_info **, bfd *, char *,
+ const struct comp_unit_head *);
-static struct abbrev_info *dwarf2_lookup_abbrev PARAMS ((unsigned int));
+static char *read_attribute (struct attribute *, struct attr_abbrev *,
+ bfd *, char *, const struct comp_unit_head *);
-static char *read_partial_die PARAMS ((struct partial_die_info *,
- bfd *, char *, int *));
+static char *read_attribute_value (struct attribute *, unsigned,
+ bfd *, char *, const struct comp_unit_head *);
-static char *read_full_die PARAMS ((struct die_info **, bfd *, char *));
+static unsigned int read_1_byte (bfd *, char *);
-static char *read_attribute PARAMS ((struct attribute *, struct attr_abbrev *,
- bfd *, char *));
+static int read_1_signed_byte (bfd *, char *);
-static unsigned int read_1_byte PARAMS ((bfd *, char *));
+static unsigned int read_2_bytes (bfd *, char *);
-static int read_1_signed_byte PARAMS ((bfd *, char *));
+static unsigned int read_4_bytes (bfd *, char *);
-static unsigned int read_2_bytes PARAMS ((bfd *, char *));
+static unsigned long read_8_bytes (bfd *, char *);
-static unsigned int read_4_bytes PARAMS ((bfd *, char *));
+static CORE_ADDR read_address (bfd *, char *ptr, const struct comp_unit_head *,
+ int *bytes_read);
-static unsigned int read_8_bytes PARAMS ((bfd *, char *));
+static LONGEST read_initial_length (bfd *, char *,
+ struct comp_unit_head *, int *bytes_read);
-static CORE_ADDR read_address PARAMS ((bfd *, char *));
+static LONGEST read_offset (bfd *, char *, const struct comp_unit_head *,
+ int *bytes_read);
-static char *read_n_bytes PARAMS ((bfd *, char *, unsigned int));
+static char *read_n_bytes (bfd *, char *, unsigned int);
-static char *read_string PARAMS ((bfd *, char *, unsigned int *));
+static char *read_string (bfd *, char *, unsigned int *);
-static unsigned int read_unsigned_leb128 PARAMS ((bfd *, char *,
- unsigned int *));
+static char *read_indirect_string (bfd *, char *, const struct comp_unit_head *,
+ unsigned int *);
-static int read_signed_leb128 PARAMS ((bfd *, char *, unsigned int *));
+static unsigned long read_unsigned_leb128 (bfd *, char *, unsigned int *);
-static void set_cu_language PARAMS ((unsigned int));
+static long read_signed_leb128 (bfd *, char *, unsigned int *);
-static struct attribute *dwarf_attr PARAMS ((struct die_info *,
- unsigned int));
+static void set_cu_language (unsigned int);
+
+static struct attribute *dwarf_attr (struct die_info *, unsigned int);
static int die_is_declaration (struct die_info *);
-static void dwarf_decode_lines PARAMS ((unsigned int, char *, bfd *));
+static void free_line_header (struct line_header *lh);
+
+static struct line_header *(dwarf_decode_line_header
+ (unsigned int offset,
+ bfd *abfd,
+ const struct comp_unit_head *cu_header));
+
+static void dwarf_decode_lines (struct line_header *, char *, bfd *,
+ const struct comp_unit_head *);
-static void dwarf2_start_subfile PARAMS ((char *, char *));
+static void dwarf2_start_subfile (char *, char *);
-static struct symbol *new_symbol PARAMS ((struct die_info *, struct type *,
- struct objfile *));
+static struct symbol *new_symbol (struct die_info *, struct type *,
+ struct objfile *, const struct comp_unit_head *);
-static void dwarf2_const_value PARAMS ((struct attribute *, struct symbol *,
- struct objfile *));
+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 PARAMS ((struct die_info *, struct objfile *));
+static struct type *die_type (struct die_info *, struct objfile *,
+ const struct comp_unit_head *);
-static struct type *die_containing_type PARAMS ((struct die_info *,
- struct objfile *));
+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 PARAMS ((struct die_info *, struct objfile *));
+static void read_type_die (struct die_info *, struct objfile *,
+ const struct comp_unit_head *);
-static void read_typedef PARAMS ((struct die_info *, struct objfile *));
+static void read_typedef (struct die_info *, struct objfile *,
+ const struct comp_unit_head *);
-static void read_base_type PARAMS ((struct die_info *, struct objfile *));
+static void read_base_type (struct die_info *, struct objfile *);
-static void read_file_scope PARAMS ((struct die_info *, struct objfile *));
+static void read_file_scope (struct die_info *, struct objfile *,
+ const struct comp_unit_head *);
-static void read_func_scope PARAMS ((struct die_info *, struct objfile *));
+static void read_func_scope (struct die_info *, struct objfile *,
+ const struct comp_unit_head *);
-static void read_lexical_block_scope PARAMS ((struct die_info *,
- struct objfile *));
+static void read_lexical_block_scope (struct die_info *, struct objfile *,
+ const struct comp_unit_head *);
-static int dwarf2_get_pc_bounds PARAMS ((struct die_info *,
- CORE_ADDR *, CORE_ADDR *,
- struct objfile *));
+static int dwarf2_get_pc_bounds (struct die_info *,
+ CORE_ADDR *, CORE_ADDR *, struct objfile *,
+ const struct comp_unit_head *);
-static void dwarf2_add_field PARAMS ((struct field_info *, 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 dwarf2_attach_fields_to_type PARAMS ((struct field_info *,
- struct type *,
- struct objfile *));
+static void dwarf2_attach_fields_to_type (struct field_info *,
+ struct type *, struct objfile *);
-static void dwarf2_add_member_fn PARAMS ((struct field_info *,
- struct die_info *, struct type *,
- struct objfile * 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 dwarf2_attach_fn_fields_to_type PARAMS ((struct field_info *,
- struct type *,
- struct objfile *));
+static void dwarf2_attach_fn_fields_to_type (struct field_info *,
+ struct type *, struct objfile *);
-static void read_structure_scope PARAMS ((struct die_info *, struct objfile *));
+static void read_structure_scope (struct die_info *, struct objfile *,
+ const struct comp_unit_head *);
-static void read_common_block PARAMS ((struct die_info *, struct objfile *));
+static void read_common_block (struct die_info *, struct objfile *,
+ const struct comp_unit_head *);
-static void read_enumeration PARAMS ((struct die_info *, struct objfile *));
+static void read_namespace (struct die_info *die, struct objfile *objfile,
+ const struct comp_unit_head *cu_header);
-static struct type *dwarf_base_type PARAMS ((int, int, struct objfile *));
+static void read_enumeration (struct die_info *, struct objfile *,
+ const struct comp_unit_head *);
-static CORE_ADDR decode_locdesc PARAMS ((struct dwarf_block *,
- struct objfile *));
+static struct type *dwarf_base_type (int, int, struct objfile *);
-static void read_array_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_pointer_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_ptr_to_member_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_reference_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_const_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_volatile_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_tag_string_type PARAMS ((struct die_info *,
- struct objfile *));
+static void read_tag_volatile_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_string_type (struct die_info *, struct objfile *);
-struct die_info *read_comp_unit PARAMS ((char *, bfd *));
+static void read_subroutine_type (struct die_info *, struct objfile *,
+ const struct comp_unit_head *);
-static void free_die_list PARAMS ((struct die_info *));
+static struct die_info *read_comp_unit (char *, bfd *,
+ const struct comp_unit_head *);
-static void process_die PARAMS ((struct die_info *, struct objfile *));
+static void free_die_list (struct die_info *);
-static char *dwarf2_linkage_name PARAMS ((struct die_info *));
+static struct cleanup *make_cleanup_free_die_list (struct die_info *);
-static char *dwarf_tag_name PARAMS ((unsigned int));
+static void process_die (struct die_info *, struct objfile *,
+ const struct comp_unit_head *);
-static char *dwarf_attr_name PARAMS ((unsigned int));
+static char *dwarf2_linkage_name (struct die_info *);
-static char *dwarf_form_name PARAMS ((unsigned int));
+static char *dwarf_tag_name (unsigned int);
-static char *dwarf_stack_op_name PARAMS ((unsigned int));
+static char *dwarf_attr_name (unsigned int);
-static char *dwarf_bool_name PARAMS ((unsigned int));
+static char *dwarf_form_name (unsigned int);
-static char *dwarf_type_encoding_name PARAMS ((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 *));
+static struct die_info *sibling_die (struct die_info *);
-void dump_die PARAMS ((struct die_info *));
+static void dump_die (struct die_info *);
-void dump_die_list PARAMS ((struct die_info *));
+static void dump_die_list (struct die_info *);
-void store_in_ref_table PARAMS ((unsigned int, struct die_info *));
+static 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));
+static 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 (void *);
+
+static struct dwarf_block *dwarf_alloc_block (void);
+
+static struct abbrev_info *dwarf_alloc_abbrev (void);
+
+static struct die_info *dwarf_alloc_die (void);
+
+static void initialize_cu_func_list (void);
-static struct dwarf_block *dwarf_alloc_block PARAMS ((void));
+static void add_to_cu_func_list (const char *, CORE_ADDR, CORE_ADDR);
-static struct abbrev_info *dwarf_alloc_abbrev PARAMS ((void));
+static void dwarf_decode_macros (struct line_header *, unsigned int,
+ char *, bfd *, const struct comp_unit_head *,
+ struct objfile *);
-static struct die_info *dwarf_alloc_die PARAMS ((void));
+static int attr_form_is_block (struct attribute *);
/* 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;
+ dwarf_info_offset = 0;
+ dwarf_abbrev_offset = 0;
+ dwarf_line_offset = 0;
+ dwarf_str_offset = 0;
+ dwarf_macinfo_offset = 0;
+ dwarf_frame_offset = 0;
+ dwarf_eh_frame_offset = 0;
+ dwarf_ranges_offset = 0;
+
bfd_map_over_sections (abfd, dwarf2_locate_sections, NULL);
if (dwarf_info_offset && dwarf_abbrev_offset)
{
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, void *ignore_ptr)
{
if (STREQ (sectp->name, INFO_SECTION))
{
dwarf_info_offset = sectp->filepos;
dwarf_info_size = bfd_get_section_size_before_reloc (sectp);
+ dwarf_info_section = sectp;
}
else if (STREQ (sectp->name, ABBREV_SECTION))
{
dwarf_abbrev_offset = sectp->filepos;
dwarf_abbrev_size = bfd_get_section_size_before_reloc (sectp);
+ dwarf_abbrev_section = sectp;
}
else if (STREQ (sectp->name, LINE_SECTION))
{
dwarf_line_offset = sectp->filepos;
dwarf_line_size = bfd_get_section_size_before_reloc (sectp);
+ dwarf_line_section = sectp;
}
else if (STREQ (sectp->name, PUBNAMES_SECTION))
{
dwarf_pubnames_offset = sectp->filepos;
dwarf_pubnames_size = bfd_get_section_size_before_reloc (sectp);
+ dwarf_pubnames_section = sectp;
}
else if (STREQ (sectp->name, ARANGES_SECTION))
{
dwarf_aranges_offset = sectp->filepos;
dwarf_aranges_size = bfd_get_section_size_before_reloc (sectp);
+ dwarf_aranges_section = sectp;
}
else if (STREQ (sectp->name, LOC_SECTION))
{
dwarf_loc_offset = sectp->filepos;
dwarf_loc_size = bfd_get_section_size_before_reloc (sectp);
+ dwarf_loc_section = sectp;
}
else if (STREQ (sectp->name, MACINFO_SECTION))
{
dwarf_macinfo_offset = sectp->filepos;
dwarf_macinfo_size = bfd_get_section_size_before_reloc (sectp);
+ dwarf_macinfo_section = sectp;
}
else if (STREQ (sectp->name, STR_SECTION))
{
dwarf_str_offset = sectp->filepos;
dwarf_str_size = bfd_get_section_size_before_reloc (sectp);
+ dwarf_str_section = sectp;
+ }
+ else if (STREQ (sectp->name, FRAME_SECTION))
+ {
+ dwarf_frame_offset = sectp->filepos;
+ dwarf_frame_size = bfd_get_section_size_before_reloc (sectp);
+ dwarf_frame_section = sectp;
+ }
+ else if (STREQ (sectp->name, EH_FRAME_SECTION))
+ {
+ dwarf_eh_frame_offset = sectp->filepos;
+ dwarf_eh_frame_size = bfd_get_section_size_before_reloc (sectp);
+ dwarf_eh_frame_section = sectp;
+ }
+ else if (STREQ (sectp->name, RANGES_SECTION))
+ {
+ dwarf_ranges_offset = sectp->filepos;
+ dwarf_ranges_size = bfd_get_section_size_before_reloc (sectp);
+ dwarf_ranges_section = sectp;
}
}
/* Build a partial symbol table. */
void
-dwarf2_build_psymtabs (objfile, mainline)
- struct objfile *objfile;
- int mainline;
+dwarf2_build_psymtabs (struct objfile *objfile, int mainline)
{
/* We definitely need the .debug_info and .debug_abbrev sections */
dwarf_info_buffer = dwarf2_read_section (objfile,
dwarf_info_offset,
- dwarf_info_size);
+ dwarf_info_size,
+ dwarf_info_section);
dwarf_abbrev_buffer = dwarf2_read_section (objfile,
dwarf_abbrev_offset,
- dwarf_abbrev_size);
- dwarf_line_buffer = dwarf2_read_section (objfile,
- dwarf_line_offset,
- dwarf_line_size);
+ dwarf_abbrev_size,
+ dwarf_abbrev_section);
+
+ if (dwarf_line_offset)
+ dwarf_line_buffer = dwarf2_read_section (objfile,
+ dwarf_line_offset,
+ dwarf_line_size,
+ dwarf_line_section);
+ else
+ dwarf_line_buffer = NULL;
+
+ if (dwarf_str_offset)
+ dwarf_str_buffer = dwarf2_read_section (objfile,
+ dwarf_str_offset,
+ dwarf_str_size,
+ dwarf_str_section);
+ else
+ dwarf_str_buffer = NULL;
+
+ if (dwarf_macinfo_offset)
+ dwarf_macinfo_buffer = dwarf2_read_section (objfile,
+ dwarf_macinfo_offset,
+ dwarf_macinfo_size,
+ dwarf_macinfo_section);
+ else
+ dwarf_macinfo_buffer = NULL;
+
+ if (dwarf_ranges_offset)
+ dwarf_ranges_buffer = dwarf2_read_section (objfile,
+ dwarf_ranges_offset,
+ dwarf_ranges_size,
+ dwarf_ranges_section);
+ else
+ dwarf_ranges_buffer = NULL;
- if (mainline || objfile->global_psymbols.size == 0 ||
- objfile->static_psymbols.size == 0)
+ if (mainline
+ || (objfile->global_psymbols.size == 0
+ && objfile->static_psymbols.size == 0))
{
init_psymbol_list (objfile, 1024);
}
.debug_pubnames and .debug_aranges sections. */
static void
-dwarf2_build_psymtabs_easy (objfile, mainline)
- struct objfile *objfile;
- int mainline;
+dwarf2_build_psymtabs_easy (struct objfile *objfile, int mainline)
{
bfd *abfd = objfile->obfd;
char *aranges_buffer, *pubnames_buffer;
pubnames_buffer = dwarf2_read_section (objfile,
dwarf_pubnames_offset,
- dwarf_pubnames_size);
+ dwarf_pubnames_size,
+ dwarf_pubnames_section);
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);
aranges_buffer = dwarf2_read_section (objfile,
dwarf_aranges_offset,
- dwarf_aranges_size);
+ dwarf_aranges_size,
+ dwarf_aranges_section);
}
#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 (__FILE__, __LINE__,
+ "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, mainline)
- struct objfile *objfile;
- 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;
- int comp_unit_has_pc_info;
CORE_ADDR lowpc, highpc;
- /* Number of bytes of any addresses that are signficant */
- address_significant_size = get_elf_backend_data (abfd)->s->arch_size / 8;
-
info_ptr = dwarf_info_buffer;
abbrev_ptr = dwarf_abbrev_buffer;
+ /* We use dwarf2_tmp_obstack for objects that don't need to survive
+ the partial symbol scan, like attribute values.
+
+ We could reduce our peak memory consumption during partial symbol
+ table construction by freeing stuff from this obstack more often
+ --- say, after processing each compilation unit, or each die ---
+ but it turns out that this saves almost nothing. For an
+ executable with 11Mb of Dwarf 2 data, I found about 64k allocated
+ on dwarf2_tmp_obstack. Some investigation showed:
+
+ 1) 69% of the attributes used forms DW_FORM_addr, DW_FORM_data*,
+ DW_FORM_flag, DW_FORM_[su]data, and DW_FORM_ref*. These are
+ all fixed-length values not requiring dynamic allocation.
+
+ 2) 30% of the attributes used the form DW_FORM_string. For
+ DW_FORM_string, read_attribute simply hands back a pointer to
+ the null-terminated string in dwarf_info_buffer, so no dynamic
+ allocation is needed there either.
+
+ 3) The remaining 1% of the attributes all used DW_FORM_block1.
+ 75% of those were DW_AT_frame_base location lists for
+ functions; the rest were DW_AT_location attributes, probably
+ for the global variables.
+
+ Anyway, what this all means is that the memory the dwarf2
+ reader uses as temporary space reading partial symbols is about
+ 0.5% as much as we use for dwarf_*_buffer. That's noise. */
+
obstack_init (&dwarf2_tmp_obstack);
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)
+ /* Since the objects we're extracting from dwarf_info_buffer vary in
+ length, only the individual functions to extract them (like
+ read_comp_unit_head and read_partial_die) can really know whether
+ the buffer is large enough to hold another complete object.
+
+ At the moment, they don't actually check that. If
+ dwarf_info_buffer holds just one extra byte after the last
+ compilation unit's dies, then read_comp_unit_head will happily
+ read off the end of the buffer. read_partial_die is similarly
+ casual. Those functions should be fixed.
+
+ For this loop condition, simply checking whether there's any data
+ left at all should be sufficient. */
+ while (info_ptr < dwarf_info_buffer + 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.");
+ error ("Dwarf Error: wrong version in compilation unit header (is %d, should be %d) [in module %s]", cu_header.version, 2, bfd_get_filename (abfd));
return;
}
if (cu_header.abbrev_offset >= dwarf_abbrev_size)
{
- error ("Dwarf Error: bad offset (0x%lx) in compilation unit header (offset 0x%lx + 6).",
+ error ("Dwarf Error: bad offset (0x%lx) in compilation unit header (offset 0x%lx + 6) [in module %s]",
(long) cu_header.abbrev_offset,
- (long) (beg_of_comp_unit - dwarf_info_buffer));
+ (long) (beg_of_comp_unit - dwarf_info_buffer),
+ bfd_get_filename (abfd));
return;
}
- if (beg_of_comp_unit + cu_header.length + 4
+ 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).",
+ error ("Dwarf Error: bad length (0x%lx) in compilation unit header (offset 0x%lx + 0) [in module %s]",
(long) cu_header.length,
- (long) (beg_of_comp_unit - dwarf_info_buffer));
+ (long) (beg_of_comp_unit - dwarf_info_buffer),
+ bfd_get_filename (abfd));
return;
}
- if (address_size < address_significant_size)
- {
- error ("Dwarf Error: bad address size (%ld) in compilation unit header (offset 0x%lx + 11).",
- (long) cu_header.addr_size,
- (long) (beg_of_comp_unit - dwarf_info_buffer));
- }
+ /* Complete the cu_header */
+ cu_header.offset = beg_of_comp_unit - dwarf_info_buffer;
+ cu_header.first_die_ptr = info_ptr;
+ cu_header.cu_head_ptr = beg_of_comp_unit;
/* 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);
+ dwarf2_read_abbrevs (abfd, &cu_header);
+ make_cleanup (dwarf2_empty_abbrev_table, cu_header.dwarf2_abbrevs);
/* 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,
+ &cu_header);
/* Set the language we're debugging */
set_cu_language (comp_unit_die.language);
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, 0);
+ DWARF_LINE_SIZE (pst) = dwarf_line_size;
+ DWARF_STR_BUFFER (pst) = dwarf_str_buffer;
+ DWARF_STR_SIZE (pst) = dwarf_str_size;
+ DWARF_MACINFO_BUFFER (pst) = dwarf_macinfo_buffer;
+ DWARF_MACINFO_SIZE (pst) = dwarf_macinfo_size;
+ DWARF_RANGES_BUFFER (pst) = dwarf_ranges_buffer;
+ DWARF_RANGES_SIZE (pst) = dwarf_ranges_size;
+ 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;
If not, there's no more debug_info for this comp unit. */
if (comp_unit_die.has_children)
{
- info_ptr = scan_partial_symbols (info_ptr, objfile, &lowpc, &highpc);
+ info_ptr = scan_partial_symbols (info_ptr, objfile, &lowpc, &highpc,
+ &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)
+ if (! comp_unit_die.has_pc_info)
{
comp_unit_die.lowpc = lowpc;
comp_unit_die.highpc = highpc;
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;
back to that level. */
int nesting_level = 1;
- int has_pc_info;
+
+ /* We only want to read in symbols corresponding to variables or
+ other similar objects that are global or static. Normally, these
+ are all children of the DW_TAG_compile_unit die, so are all at
+ level 1. But C++ namespaces give ries to DW_TAG_namespace dies
+ whose children are global objects. So we keep track of what
+ level we currently think of as referring to file scope; this
+ should always equal 1 plus the number of namespaces that we are
+ currently nested within. */
+
+ int file_scope_level = 1;
*lowpc = ((CORE_ADDR) -1);
*highpc = ((CORE_ADDR) 0);
while (nesting_level)
{
- info_ptr = read_partial_die (&pdi, abfd, info_ptr, &has_pc_info);
+ info_ptr = read_partial_die (&pdi, abfd, info_ptr, cu_header);
- if (pdi.name)
+ /* Anonymous namespaces have no name but are interesting. */
+
+ if (pdi.name != NULL || pdi.tag == DW_TAG_namespace)
{
switch (pdi.tag)
{
case DW_TAG_subprogram:
- if (has_pc_info)
+ if (pdi.has_pc_info)
{
if (pdi.lowpc < *lowpc)
{
{
*highpc = pdi.highpc;
}
- if ((pdi.is_external || nesting_level == 1)
+ if ((pdi.is_external || nesting_level == file_scope_level)
&& !pdi.is_declaration)
{
- add_partial_symbol (&pdi, objfile);
+ add_partial_symbol (&pdi, objfile, cu_header);
}
}
break;
case DW_TAG_structure_type:
case DW_TAG_union_type:
case DW_TAG_enumeration_type:
- if ((pdi.is_external || nesting_level == 1)
+ if ((pdi.is_external || nesting_level == file_scope_level)
&& !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);
+ /* File scope enumerators are added to the partial
+ symbol table. They're children of the enumeration
+ type die, so they occur at a level one higher than we
+ normally look for. */
+ if (nesting_level == file_scope_level + 1)
+ 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);
+ if (nesting_level == file_scope_level)
+ add_partial_symbol (&pdi, objfile, cu_header);
break;
+ case DW_TAG_namespace:
+ /* FIXME: carlton/2002-10-16: we're not yet doing
+ anything useful with this, but for now make sure that
+ these tags at least don't cause us to miss any
+ important symbols. */
+ if (pdi.has_children)
+ file_scope_level++;
default:
break;
}
}
- /* 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)
+ /* If the die has a sibling, skip to the sibling. Do not skip
+ enumeration types, we want to record their enumerators. Do
+ not skip namespaces, we want to record symbols inside
+ them. */
+ if (pdi.sibling
+ && pdi.tag != DW_TAG_enumeration_type
+ && pdi.tag != DW_TAG_namespace)
{
info_ptr = pdi.sibling;
}
else if (pdi.has_children)
{
- /* Die has children, but the optional DW_AT_sibling attribute
- is missing. */
+ /* Die has children, but either the optional DW_AT_sibling
+ attribute is missing or we want to look at them. */
nesting_level++;
}
if (pdi.tag == 0)
{
nesting_level--;
+ /* If this is the end of a DW_TAG_namespace entry, then
+ decrease the file_scope_level, too. */
+ if (nesting_level < file_scope_level)
+ {
+ file_scope_level--;
+ gdb_assert (nesting_level == file_scope_level);
+ }
}
}
}
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;
table building. */
if (pdi->locdesc)
- addr = decode_locdesc (pdi->locdesc, objfile);
+ 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,
/* Static Variable. Skip symbols without location descriptors. */
if (pdi->locdesc == NULL)
return;
- addr = decode_locdesc (pdi->locdesc, objfile);
+ 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),
/* 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;
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);
+ dwarf_line_size = DWARF_LINE_SIZE (pst);
+ dwarf_str_buffer = DWARF_STR_BUFFER (pst);
+ dwarf_str_size = DWARF_STR_SIZE (pst);
+ dwarf_macinfo_buffer = DWARF_MACINFO_BUFFER (pst);
+ dwarf_macinfo_size = DWARF_MACINFO_SIZE (pst);
+ dwarf_ranges_buffer = DWARF_RANGES_BUFFER (pst);
+ dwarf_ranges_size = DWARF_RANGES_SIZE (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);
+ dwarf2_read_abbrevs (abfd, &cu_header);
+ make_cleanup (dwarf2_empty_abbrev_table, cu_header.dwarf2_abbrevs);
- dies = read_comp_unit (info_ptr, abfd);
+ dies = read_comp_unit (info_ptr, abfd, &cu_header);
- make_cleanup ((make_cleanup_func) free_die_list, dies);
+ make_cleanup_free_die_list (dies);
/* Do line number decoding in read_file_scope () */
- process_die (dies, objfile);
+ cu_header.die = dies;
+ process_die (dies, objfile, &cu_header);
- if (!dwarf2_get_pc_bounds (dies, &lowpc, &highpc, objfile))
+ if (!dwarf2_get_pc_bounds (dies, &lowpc, &highpc, objfile, &cu_header))
{
/* Some compilers don't define a DW_AT_high_pc attribute for
the compilation unit. If the DW_AT_high_pc is missing,
{
CORE_ADDR low, high;
- if (dwarf2_get_pc_bounds (child_die, &low, &high, objfile))
+ if (dwarf2_get_pc_bounds (child_die, &low, &high,
+ objfile, &cu_header))
{
highpc = max (highpc, high);
}
}
}
}
- 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);
- 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.
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:
- 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);
if (dwarf_attr (die, DW_AT_name))
{
/* Add a typedef symbol for the base type definition. */
- new_symbol (die, die->type, objfile);
+ 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;
+ case DW_TAG_namespace:
+ read_namespace (die, objfile, cu_header);
+ break;
+ case DW_TAG_imported_declaration:
+ case DW_TAG_imported_module:
+ /* FIXME: carlton/2002-10-16: Eventually, we should use the
+ information contained in these. DW_TAG_imported_declaration
+ dies shouldn't have children; DW_TAG_imported_module dies
+ shouldn't in the C++ case, but conceivably could in the
+ Fortran case, so we'll have to replace this gdb_assert if
+ Fortran compilers start generating that info. */
+ gdb_assert (!die->has_children);
+ 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;
+initialize_cu_func_list (void)
{
- unsigned int line_offset = 0;
+ cu_first_fn = cu_last_fn = cu_cached_fn = NULL;
+}
+
+static void
+read_file_scope (struct die_info *die, struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
+{
+ struct cleanup *back_to = make_cleanup (null_cleanup, 0);
CORE_ADDR lowpc = ((CORE_ADDR) -1);
CORE_ADDR highpc = ((CORE_ADDR) 0);
struct attribute *attr;
char *comp_dir = NULL;
struct die_info *child_die;
bfd *abfd = objfile->obfd;
+ struct line_header *line_header = 0;
- if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile))
+ if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile, cu_header))
{
if (die->has_children)
{
{
CORE_ADDR low, high;
- if (dwarf2_get_pc_bounds (child_die, &low, &high, objfile))
+ if (dwarf2_get_pc_bounds (child_die, &low, &high,
+ objfile, cu_header))
{
lowpc = min (lowpc, low);
highpc = max (highpc, high);
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);
- }
+ initialize_cu_func_list ();
/* Process all dies in compilation unit. */
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);
}
}
+
+ /* Decode line number information if present. */
+ attr = dwarf_attr (die, DW_AT_stmt_list);
+ if (attr)
+ {
+ unsigned int line_offset = DW_UNSND (attr);
+ line_header = dwarf_decode_line_header (line_offset,
+ abfd, cu_header);
+ if (line_header)
+ {
+ make_cleanup ((make_cleanup_ftype *) free_line_header,
+ (void *) line_header);
+ dwarf_decode_lines (line_header, comp_dir, abfd, cu_header);
+ }
+ }
+
+ /* Decode macro information, if present. Dwarf 2 macro information
+ refers to information in the line number info statement program
+ header, so we can only read it if we've read the header
+ successfully. */
+ attr = dwarf_attr (die, DW_AT_macro_info);
+ if (attr && line_header)
+ {
+ unsigned int macro_offset = DW_UNSND (attr);
+ dwarf_decode_macros (line_header, macro_offset,
+ comp_dir, abfd, cu_header, objfile);
+ }
+ do_cleanups (back_to);
+}
+
+static void
+add_to_cu_func_list (const char *name, CORE_ADDR lowpc, CORE_ADDR highpc)
+{
+ struct function_range *thisfn;
+
+ thisfn = (struct function_range *)
+ obstack_alloc (&dwarf2_tmp_obstack, sizeof (struct function_range));
+ thisfn->name = name;
+ thisfn->lowpc = lowpc;
+ thisfn->highpc = highpc;
+ thisfn->seen_line = 0;
+ thisfn->next = NULL;
+
+ if (cu_last_fn == NULL)
+ cu_first_fn = thisfn;
+ else
+ cu_last_fn->next = thisfn;
+
+ cu_last_fn = thisfn;
}
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;
/* 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))
+ if (name == NULL || !dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile, cu_header))
return;
lowpc += baseaddr;
highpc += baseaddr;
+ /* Record the function range for dwarf_decode_lines. */
+ add_to_cu_func_list (name, lowpc, highpc);
+
if (objfile->ei.entry_point >= lowpc &&
objfile->ei.entry_point < highpc)
{
attr = dwarf_attr (die, DW_AT_frame_base);
if (attr)
{
- CORE_ADDR addr = decode_locdesc (DW_BLOCK (attr), objfile);
+ CORE_ADDR addr;
+
+ /* Support the .debug_loc offsets */
+ if (attr_form_is_block (attr))
+ {
+ addr = decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
+ }
+ else if (attr->form == DW_FORM_data4 || attr->form == DW_FORM_data8)
+ {
+ dwarf2_complex_location_expr_complaint ();
+ addr = 0;
+ }
+ else
+ {
+ dwarf2_invalid_attrib_class_complaint ("DW_AT_frame_base", name);
+ addr = 0;
+ }
+
if (isderef)
- complain (&dwarf2_unsupported_at_frame_base, name);
+ dwarf2_unsupported_at_frame_base_complaint (name);
else if (isreg)
frame_base_reg = addr;
else if (offreg)
frame_base_offset = addr;
}
else
- complain (&dwarf2_unsupported_at_frame_base, name);
+ dwarf2_unsupported_at_frame_base_complaint (name);
}
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);
}
}
/* Make a block for the local symbols within. */
finish_block (new->name, &local_symbols, new->old_blocks,
lowpc, highpc, objfile);
- list_in_scope = &file_symbols;
+
+ /* In C++, we can have functions nested inside functions (e.g., when
+ a function declares a class that has methods). This means that
+ when we finish processing a function scope, we may need to go
+ back to building a containing block's symbol lists. */
+ local_symbols = new->locals;
+ param_symbols = new->params;
+
+ /* If we've finished processing a top-level function, subsequent
+ symbols go in the file symbol list. */
+ if (outermost_context_p ())
+ list_in_scope = &file_symbols;
}
/* Process all the DIES contained within a lexical block scope. Start
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, highpc;
struct die_info *child_die;
/* Ignore blocks with missing or invalid low and high pc attributes. */
- if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile))
+ /* ??? Perhaps consider discontiguous blocks defined by DW_AT_ranges
+ as multiple lexical blocks? Handling children in a sane way would
+ be nasty. Might be easier to properly extend generic blocks to
+ describe ranges. */
+ if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile, cu_header))
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. */
-
+/* Get low and high pc attributes from a die. Return 1 if the attributes
+ are present and valid, otherwise, return 0. Return -1 if the range is
+ discontinuous, i.e. derived from DW_AT_ranges information. */
static int
-dwarf2_get_pc_bounds (die, lowpc, highpc, objfile)
- struct die_info *die;
- CORE_ADDR *lowpc;
- CORE_ADDR *highpc;
- struct objfile *objfile;
+dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc,
+ CORE_ADDR *highpc, struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
{
struct attribute *attr;
- CORE_ADDR low;
- CORE_ADDR high;
+ bfd *obfd = objfile->obfd;
+ CORE_ADDR low = 0;
+ CORE_ADDR high = 0;
+ int ret = 0;
- 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);
+ {
+ high = DW_ADDR (attr);
+ attr = dwarf_attr (die, DW_AT_low_pc);
+ if (attr)
+ low = DW_ADDR (attr);
+ else
+ /* Found high w/o low attribute. */
+ return 0;
+
+ /* Found consecutive range of addresses. */
+ ret = 1;
+ }
else
- return 0;
+ {
+ attr = dwarf_attr (die, DW_AT_ranges);
+ if (attr != NULL)
+ {
+ unsigned int addr_size = cu_header->addr_size;
+ CORE_ADDR mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1));
+ /* Value of the DW_AT_ranges attribute is the offset in the
+ .debug_renges section. */
+ unsigned int offset = DW_UNSND (attr);
+ /* Base address selection entry. */
+ CORE_ADDR base = 0;
+ int found_base = 0;
+ int dummy;
+ unsigned int i;
+ char *buffer;
+ CORE_ADDR marker;
+ int low_set;
+
+ /* The applicable base address is determined by (1) the closest
+ preceding base address selection entry in the range list or
+ (2) the DW_AT_low_pc of the compilation unit. */
+
+ /* ??? Was in dwarf3 draft4, and has since been removed.
+ GCC still uses it though. */
+ attr = dwarf_attr (cu_header->die, DW_AT_entry_pc);
+ if (attr)
+ {
+ base = DW_ADDR (attr);
+ found_base = 1;
+ }
+
+ if (!found_base)
+ {
+ attr = dwarf_attr (cu_header->die, DW_AT_low_pc);
+ if (attr)
+ {
+ base = DW_ADDR (attr);
+ found_base = 1;
+ }
+ }
+
+ buffer = dwarf_ranges_buffer + offset;
+
+
+ /* Read in the largest possible address. */
+ marker = read_address (obfd, buffer, cu_header, &dummy);
+ if ((marker & mask) == mask)
+ {
+ /* If we found the largest possible address, then
+ read the base address. */
+ base = read_address (obfd, buffer + addr_size,
+ cu_header, &dummy);
+ buffer += 2 * addr_size;
+ offset += 2 * addr_size;
+ found_base = 1;
+ }
+
+ low_set = 0;
+
+ while (1)
+ {
+ CORE_ADDR range_beginning, range_end;
+
+ range_beginning = read_address (obfd, buffer,
+ cu_header, &dummy);
+ buffer += addr_size;
+ range_end = read_address (obfd, buffer, cu_header, &dummy);
+ buffer += addr_size;
+ offset += 2 * addr_size;
+
+ /* An end of list marker is a pair of zero addresses. */
+ if (range_beginning == 0 && range_end == 0)
+ /* Found the end of list entry. */
+ break;
+
+ /* Each base address selection entry is a pair of 2 values.
+ The first is the largest possible address, the second is
+ the base address. Check for a base address here. */
+ if ((range_beginning & mask) == mask)
+ {
+ /* If we found the largest possible address, then
+ read the base address. */
+ base = read_address (obfd, buffer + addr_size,
+ cu_header, &dummy);
+ found_base = 1;
+ continue;
+ }
+
+ if (!found_base)
+ {
+ /* We have no valid base address for the ranges
+ data. */
+ complaint (&symfile_complaints,
+ "Invalid .debug_ranges data (no base address)");
+ return 0;
+ }
+
+ range_beginning += base;
+ range_end += base;
+
+ /* FIXME: This is recording everything as a low-high
+ segment of consecutive addresses. We should have a
+ data structure for discontiguous block ranges
+ instead. */
+ if (! low_set)
+ {
+ low = range_beginning;
+ high = range_end;
+ low_set = 1;
+ }
+ else
+ {
+ if (range_beginning < low)
+ low = range_beginning;
+ if (range_end > high)
+ high = range_end;
+ }
+ }
+
+ if (! low_set)
+ /* If the first entry is an end-of-list marker, the range
+ describes an empty scope, i.e. no instructions. */
+ return 0;
+
+ ret = -1;
+ }
+ }
if (high < low)
return 0;
labels are not in the output, so the relocs get a value of 0.
If this is a discarded function, mark the pc bounds as invalid,
so that GDB will ignore it. */
- if (low == 0 && (bfd_get_file_flags (objfile->obfd) & HAS_RELOC) == 0)
+ if (low == 0 && (bfd_get_file_flags (obfd) & HAS_RELOC) == 0)
return 0;
*lowpc = low;
*highpc = high;
- return 1;
+ return ret;
}
/* Add an aggregate field to the field list. */
static void
-dwarf2_add_field (fip, die, objfile)
- struct field_info *fip;
- struct die_info *die;
- struct objfile *objfile;
+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;
/* Allocate a new field list entry and link it in. */
new_field = (struct nextfield *) xmalloc (sizeof (struct nextfield));
- make_cleanup (free, new_field);
+ make_cleanup (xfree, new_field);
memset (new_field, 0, sizeof (struct nextfield));
new_field->next = fip->fields;
fip->fields = new_field;
new_field->virtuality = DW_UNSND (attr);
fp = &new_field->field;
- if (die->tag == DW_TAG_member)
+
+ if (die->tag == DW_TAG_member && ! die_is_declaration (die))
{
+ /* Data member other than a C++ static data member. */
+
/* Get type of field. */
- fp->type = die_type (die, objfile);
+ fp->type = die_type (die, objfile, cu_header);
+
+ FIELD_STATIC_KIND (*fp) = 0;
/* Get bit size of field (zero if none). */
attr = dwarf_attr (die, DW_AT_bit_size);
if (attr)
{
FIELD_BITPOS (*fp) =
- decode_locdesc (DW_BLOCK (attr), objfile) * bits_per_byte;
+ decode_locdesc (DW_BLOCK (attr), objfile, cu_header) * bits_per_byte;
}
else
FIELD_BITPOS (*fp) = 0;
fip->non_public_fields = 1;
}
}
- else if (die->tag == DW_TAG_variable)
+ else if (die->tag == DW_TAG_member || die->tag == DW_TAG_variable)
{
+ /* C++ static member. */
+
+ /* NOTE: carlton/2002-11-05: It should be a DW_TAG_member that
+ is a declaration, but all versions of G++ as of this writing
+ (so through at least 3.2.1) incorrectly generate
+ DW_TAG_variable tags. */
+
char *physname;
- /* C++ static member.
- Get name of field. */
+ /* Get name of field. */
attr = dwarf_attr (die, DW_AT_name);
if (attr && DW_STRING (attr))
fieldname = DW_STRING (attr);
SET_FIELD_PHYSNAME (*fp, obsavestring (physname, strlen (physname),
&objfile->type_obstack));
- FIELD_TYPE (*fp) = die_type (die, objfile);
+ FIELD_TYPE (*fp) = die_type (die, objfile, cu_header);
FIELD_NAME (*fp) = obsavestring (fieldname, strlen (fieldname),
&objfile->type_obstack);
}
/* C++ base class field. */
attr = dwarf_attr (die, DW_AT_data_member_location);
if (attr)
- FIELD_BITPOS (*fp) = decode_locdesc (DW_BLOCK (attr), objfile) * bits_per_byte;
+ 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);
+ FIELD_STATIC_KIND (*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 (fip, type, objfile)
- struct field_info *fip;
- struct type *type;
- struct objfile *objfile;
+dwarf2_attach_fields_to_type (struct field_info *fip, struct type *type,
+ struct objfile *objfile)
{
int nfields = fip->nfields;
default:
/* Unknown accessibility. Complain and treat it as public. */
{
- complain (&dwarf2_unsupported_accessibility,
- fip->fields->accessibility);
+ complaint (&symfile_complaints, "unsupported accessibility %d",
+ fip->fields->accessibility);
}
break;
}
/* Add a member function to the proper fieldlist. */
static void
-dwarf2_add_member_fn (fip, die, type, objfile)
- struct field_info *fip;
- struct die_info *die;
- struct type *type;
- struct objfile *objfile;
+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;
(fip->nfnfields + DW_FIELD_ALLOC_CHUNK)
* sizeof (struct fnfieldlist));
if (fip->nfnfields == 0)
- make_cleanup ((make_cleanup_func) free_current_contents,
- &fip->fnfieldlists);
+ make_cleanup (free_current_contents, &fip->fnfieldlists);
}
flp = &fip->fnfieldlists[fip->nfnfields];
flp->name = fieldname;
/* Create a new member function field and chain it to the field list
entry. */
new_fnfield = (struct nextfnfield *) xmalloc (sizeof (struct nextfnfield));
- make_cleanup (free, new_fnfield);
+ make_cleanup (xfree, new_fnfield);
memset (new_fnfield, 0, sizeof (struct nextfnfield));
new_fnfield->next = flp->head;
flp->head = new_fnfield;
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);
+ /* TYPE is the domain of this method, and DIE->TYPE is the type
+ of the method itself (TYPE_CODE_METHOD). */
+ smash_to_method_type (fnp->type, type,
+ TYPE_TARGET_TYPE (die->type),
+ TYPE_FIELDS (die->type),
+ TYPE_NFIELDS (die->type),
+ TYPE_VARARGS (die->type));
/* Handle static member functions.
Dwarf2 has no clean way to discern C++ static and non-static
fnp->voffset = VOFFSET_STATIC;
}
else
- complain (&dwarf2_missing_member_fn_type_complaint, physname);
+ complaint (&symfile_complaints, "member function type missing for '%s'",
+ 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);
+ 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. */
}
}
+ /* Check for artificial methods. */
+ attr = dwarf_attr (die, DW_AT_artificial);
+ if (attr && DW_UNSND (attr) != 0)
+ fnp->is_artificial = 1;
+
/* 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) + 2;
+ {
+ /* Support the .debug_loc offsets */
+ if (attr_form_is_block (attr))
+ {
+ fnp->voffset = decode_locdesc (DW_BLOCK (attr), objfile, cu_header) + 2;
+ }
+ else if (attr->form == DW_FORM_data4 || attr->form == DW_FORM_data8)
+ {
+ dwarf2_complex_location_expr_complaint ();
+ }
+ else
+ {
+ dwarf2_invalid_attrib_class_complaint ("DW_AT_vtable_elem_location",
+ fieldname);
+ }
+ }
}
/* Create the vector of member function fields, and attach it to the type. */
static void
-dwarf2_attach_fn_fields_to_type (fip, type, objfile)
- struct field_info *fip;
- struct type *type;
- struct objfile *objfile;
+dwarf2_attach_fn_fields_to_type (struct field_info *fip, struct type *type,
+ struct objfile *objfile)
{
struct fnfieldlist *flp;
int total_length = 0;
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 attribute *attr;
while (child_die && child_die->tag)
{
- if (child_die->tag == DW_TAG_member)
- {
- dwarf2_add_field (&fi, child_die, objfile);
- }
- else if (child_die->tag == DW_TAG_variable)
+ if (child_die->tag == DW_TAG_member
+ || child_die->tag == DW_TAG_variable)
{
- /* C++ static member. */
- dwarf2_add_field (&fi, child_die, objfile);
+ /* NOTE: carlton/2002-11-05: A C++ static data member
+ should be a DW_TAG_member that is a declaration, but
+ all versions of G++ as of this writing (so through at
+ least 3.2.1) incorrectly generate DW_TAG_variable
+ tags for them instead. */
+ dwarf2_add_field (&fi, child_die, objfile, cu_header);
}
else if (child_die->tag == DW_TAG_subprogram)
{
/* C++ member function. */
- process_die (child_die, objfile);
- dwarf2_add_member_fn (&fi, child_die, type, objfile);
+ 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)
{
/* C++ base class field. */
- dwarf2_add_field (&fi, child_die, objfile);
+ 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 (dwarf_attr (die, DW_AT_containing_type) != NULL)
{
- struct type *t = die_containing_type (die, objfile);
+ struct type *t = die_containing_type (die, objfile, cu_header);
TYPE_VPTR_BASETYPE (type) = t;
if (type == t)
/* 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) : "");
+ complaint (&symfile_complaints,
+ "virtual function table pointer not found when defining class '%s'",
+ TYPE_TAG_NAME (type) ? TYPE_TAG_NAME (type) :
+ "");
}
else
{
}
}
- new_symbol (die, type, objfile);
+ new_symbol (die, type, objfile, cu_header);
do_cleanups (back_to);
}
/* No children, must be stub. */
TYPE_FLAGS (type) |= TYPE_FLAG_STUB;
}
-
- die->type = type;
}
/* Given a pointer to a die which begins an enumeration, process all
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;
{
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;
FIELD_TYPE (fields[num_fields]) = NULL;
FIELD_BITPOS (fields[num_fields]) = SYMBOL_VALUE (sym);
FIELD_BITSIZE (fields[num_fields]) = 0;
+ FIELD_STATIC_KIND (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;
- 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
-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;
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
arrays with unspecified length. */
low = 1;
}
- index_type = die_type (child_die, objfile);
+ index_type = die_type (child_die, objfile, cu_header);
attr = dwarf_attr (child_die, DW_AT_lower_bound);
if (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_data4
+ || attr->form == DW_FORM_data8)
{
low = DW_UNSND (attr);
}
else
{
- complain (&dwarf2_non_const_array_bound_ignored,
- dwarf_form_name (attr->form));
+ dwarf2_non_const_array_bound_ignored_complaint
+ (dwarf_form_name (attr->form));
#ifdef FORTRAN_HACK
die->type = lookup_pointer_type (element_type);
return;
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_data4
+ || attr->form == DW_FORM_data8)
{
high = DW_UNSND (attr);
}
}
else
{
- complain (&dwarf2_non_const_array_bound_ignored,
- dwarf_form_name (attr->form));
+ dwarf2_non_const_array_bound_ignored_complaint
+ (dwarf_form_name (attr->form));
#ifdef FORTRAN_HACK
die->type = lookup_pointer_type (element_type);
return;
xrealloc (range_types, (ndim + DW_FIELD_ALLOC_CHUNK)
* sizeof (struct type *));
if (ndim == 0)
- make_cleanup ((make_cleanup_func) free_current_contents,
- &range_types);
+ make_cleanup (free_current_contents, &range_types);
}
range_types[ndim++] = create_range_type (NULL, index_type, low, high);
}
while (ndim-- > 0)
type = create_array_type (NULL, type, range_types[ndim]);
+ /* Understand Dwarf2 support for vector types (like they occur on
+ the PowerPC w/ AltiVec). Gcc just adds another attribute to the
+ array type. This is not part of the Dwarf2/3 standard yet, but a
+ custom vendor extension. The main difference between a regular
+ array and the vector variant is that vectors are passed by value
+ to functions. */
+ attr = dwarf_attr (die, DW_AT_GNU_vector);
+ if (attr)
+ TYPE_FLAGS (type) |= TYPE_FLAG_VECTOR;
+
do_cleanups (back_to);
/* Install the type in the die. */
/* 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);
+ /* Support the .debug_loc offsets */
+ if (attr_form_is_block (attr))
+ {
+ base = decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
+ }
+ else if (attr->form == DW_FORM_data4 || attr->form == DW_FORM_data8)
+ {
+ dwarf2_complex_location_expr_complaint ();
+ }
+ else
+ {
+ dwarf2_invalid_attrib_class_complaint ("DW_AT_location",
+ "common block member");
+ }
}
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);
}
}
+/* Read a C++ namespace. */
+
+/* FIXME: carlton/2002-10-16: For now, we don't actually do anything
+ useful with the namespace data: we just process its children. */
+
+static void
+read_namespace (struct die_info *die, struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
+{
+ if (die->has_children)
+ {
+ struct die_info *child_die = die->next;
+
+ while (child_die && child_die->tag)
+ {
+ process_die (child_die, objfile, cu_header);
+ child_die = sibling_die (child_die);
+ }
+ }
+}
+
/* Extract all information from a DW_TAG_pointer_type DIE and add to
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;
+ struct attribute *attr_byte_size;
+ struct attribute *attr_address_class;
+ int byte_size, addr_class;
if (die->type)
{
return;
}
- type = lookup_pointer_type (die_type (die, objfile));
- attr = dwarf_attr (die, DW_AT_byte_size);
- if (attr)
- {
- TYPE_LENGTH (type) = DW_UNSND (attr);
- }
+ type = lookup_pointer_type (die_type (die, objfile, cu_header));
+
+ attr_byte_size = dwarf_attr (die, DW_AT_byte_size);
+ if (attr_byte_size)
+ byte_size = DW_UNSND (attr_byte_size);
else
+ byte_size = cu_header->addr_size;
+
+ attr_address_class = dwarf_attr (die, DW_AT_address_class);
+ if (attr_address_class)
+ addr_class = DW_UNSND (attr_address_class);
+ else
+ addr_class = DW_ADDR_none;
+
+ /* If the pointer size or address class is different than the
+ default, create a type variant marked as such and set the
+ length accordingly. */
+ if (TYPE_LENGTH (type) != byte_size || addr_class != DW_ADDR_none)
{
- TYPE_LENGTH (type) = address_size;
+ if (ADDRESS_CLASS_TYPE_FLAGS_P ())
+ {
+ int type_flags;
+
+ type_flags = ADDRESS_CLASS_TYPE_FLAGS (byte_size, addr_class);
+ gdb_assert ((type_flags & ~TYPE_FLAG_ADDRESS_CLASS_ALL) == 0);
+ type = make_type_with_address_space (type, type_flags);
+ }
+ else if (TYPE_LENGTH (type) != byte_size)
+ {
+ complaint (&symfile_complaints, "invalid pointer size %d", byte_size);
+ }
+ else {
+ /* Should we also complain about unhandled address classes? */
+ }
}
+
+ TYPE_LENGTH (type) = byte_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)
{
+ struct type *base_type;
+
if (die->type)
{
return;
}
- complain (&dwarf2_const_ignored);
- die->type = die_type (die, objfile);
+ base_type = die_type (die, objfile, cu_header);
+ die->type = make_cv_type (1, TYPE_VOLATILE (base_type), base_type, 0);
}
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)
{
+ struct type *base_type;
+
if (die->type)
{
return;
}
- complain (&dwarf2_volatile_ignored);
- die->type = die_type (die, objfile);
+ base_type = die_type (die, objfile, cu_header);
+ die->type = make_cv_type (TYPE_CONST (base_type), 1, base_type, 0);
}
/* 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;
}
else
{
- length = 1;
+ /* check for the DW_AT_byte_size attribute */
+ attr = dwarf_attr (die, DW_AT_byte_size);
+ if (attr)
+ {
+ length = DW_UNSND (attr);
+ }
+ else
+ {
+ length = 1;
+ }
}
index_type = dwarf2_fundamental_type (objfile, FT_INTEGER);
range_type = create_range_type (NULL, index_type, 1, length);
- char_type = dwarf2_fundamental_type (objfile, FT_CHAR);
- type = create_string_type (char_type, range_type);
+ if (cu_language == language_fortran)
+ {
+ /* Need to create a unique string type for bounds
+ information */
+ type = create_string_type (0, range_type);
+ }
+ else
+ {
+ char_type = dwarf2_fundamental_type (objfile, FT_CHAR);
+ type = create_string_type (char_type, range_type);
+ }
die->type = type;
}
*/
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 */
{
return;
}
- type = die_type (die, objfile);
+ type = die_type (die, objfile, cu_header);
ftype = lookup_function_type (type);
/* All functions in C++ have prototypes. */
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);
+ 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;
+ char *name = NULL;
if (!die->type)
{
- struct attribute *attr;
- struct type *xtype;
-
- xtype = die_type (die, objfile);
-
- 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 && DW_STRING (attr))
- TYPE_NAME (type) = obsavestring (DW_STRING (attr),
- strlen (DW_STRING (attr)),
- &objfile->type_obstack);
-
- die->type = type;
+ {
+ name = DW_STRING (attr);
+ }
+ die->type = init_type (TYPE_CODE_TYPEDEF, 0, TYPE_FLAG_TARGET_STUB, name, objfile);
+ TYPE_TARGET_TYPE (die->type) = die_type (die, objfile, cu_header);
}
}
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;
if (attr && DW_STRING (attr))
{
enum type_code code = TYPE_CODE_INT;
- int is_unsigned = 0;
+ int type_flags = 0;
switch (encoding)
{
case DW_ATE_address:
/* Turn DW_ATE_address into a void * pointer. */
code = TYPE_CODE_PTR;
- is_unsigned = 1;
+ type_flags |= TYPE_FLAG_UNSIGNED;
break;
case DW_ATE_boolean:
code = TYPE_CODE_BOOL;
- is_unsigned = 1;
+ type_flags |= TYPE_FLAG_UNSIGNED;
break;
case DW_ATE_complex_float:
code = TYPE_CODE_COMPLEX;
break;
case DW_ATE_unsigned:
case DW_ATE_unsigned_char:
- is_unsigned = 1;
+ type_flags |= TYPE_FLAG_UNSIGNED;
break;
default:
- complain (&dwarf2_unsupported_at_encoding,
- dwarf_type_encoding_name (encoding));
+ complaint (&symfile_complaints, "unsupported DW_AT_encoding: '%s'",
+ dwarf_type_encoding_name (encoding));
break;
}
- type = init_type (code, size, is_unsigned, DW_STRING (attr), objfile);
+ type = init_type (code, size, type_flags, DW_STRING (attr), objfile);
if (encoding == DW_ATE_address)
TYPE_TARGET_TYPE (type) = dwarf2_fundamental_type (objfile, FT_VOID);
+ else if (encoding == DW_ATE_complex_float)
+ {
+ if (size == 32)
+ TYPE_TARGET_TYPE (type)
+ = dwarf2_fundamental_type (objfile, FT_EXT_PREC_FLOAT);
+ else if (size == 16)
+ TYPE_TARGET_TYPE (type)
+ = dwarf2_fundamental_type (objfile, FT_DBL_PREC_FLOAT);
+ else if (size == 8)
+ TYPE_TARGET_TYPE (type)
+ = dwarf2_fundamental_type (objfile, FT_FLOAT);
+ }
}
else
{
/* 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;
+static struct die_info *
+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;
+char *
+dwarf2_read_section (struct objfile *objfile, file_ptr offset,
+ unsigned int size, asection *sectp)
{
bfd *abfd = objfile->obfd;
- char *buf;
+ char *buf, *retbuf;
if (size == 0)
return NULL;
buf = (char *) obstack_alloc (&objfile->psymbol_obstack, size);
+ retbuf
+ = (char *) symfile_relocate_debug_section (abfd, sectp, (bfd_byte *) buf);
+ if (retbuf != NULL)
+ return retbuf;
+
if ((bfd_seek (abfd, offset, SEEK_SET) != 0) ||
- (bfd_read (buf, size, 1, abfd) != size))
+ (bfd_bread (buf, size, abfd) != size))
{
buf = NULL;
error ("Dwarf Error: Can't read DWARF data from '%s'",
in a hash table. */
static void
-dwarf2_read_abbrevs (abfd, offset)
- bfd *abfd;
- unsigned int offset;
+dwarf2_read_abbrevs (bfd *abfd, struct comp_unit_head *cu_header)
{
char *abbrev_ptr;
struct abbrev_info *cur_abbrev;
unsigned int abbrev_number, bytes_read, abbrev_name;
unsigned int abbrev_form, hash_number;
- /* empty the table */
- dwarf2_empty_abbrev_table (NULL);
+ /* Initialize dwarf2 abbrevs */
+ memset (cu_header->dwarf2_abbrevs, 0,
+ ABBREV_HASH_SIZE*sizeof (struct abbrev_info *));
- abbrev_ptr = dwarf_abbrev_buffer + offset;
+ abbrev_ptr = dwarf_abbrev_buffer + cu_header->abbrev_offset;
abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
abbrev_ptr += bytes_read;
}
hash_number = abbrev_number % ABBREV_HASH_SIZE;
- cur_abbrev->next = dwarf2_abbrevs[hash_number];
- dwarf2_abbrevs[hash_number] = cur_abbrev;
+ cur_abbrev->next = cu_header->dwarf2_abbrevs[hash_number];
+ cu_header->dwarf2_abbrevs[hash_number] = cur_abbrev;
/* Get next abbreviation.
Under Irix6 the abbreviations for a compilation unit are not
break;
abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
abbrev_ptr += bytes_read;
- if (dwarf2_lookup_abbrev (abbrev_number) != NULL)
+ if (dwarf2_lookup_abbrev (abbrev_number, cu_header) != NULL)
break;
}
}
/* ARGSUSED */
static void
-dwarf2_empty_abbrev_table (ignore)
- PTR ignore;
+dwarf2_empty_abbrev_table (void *ptr_to_abbrevs_table)
{
int i;
struct abbrev_info *abbrev, *next;
+ struct abbrev_info **abbrevs;
+
+ abbrevs = (struct abbrev_info **)ptr_to_abbrevs_table;
for (i = 0; i < ABBREV_HASH_SIZE; ++i)
{
next = NULL;
- abbrev = dwarf2_abbrevs[i];
+ abbrev = abbrevs[i];
while (abbrev)
{
next = abbrev->next;
- free (abbrev->attrs);
- free (abbrev);
+ xfree (abbrev->attrs);
+ xfree (abbrev);
abbrev = next;
}
- dwarf2_abbrevs[i] = NULL;
+ 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, const struct comp_unit_head *cu_header)
{
unsigned int hash_number;
struct abbrev_info *abbrev;
hash_number = number % ABBREV_HASH_SIZE;
- abbrev = dwarf2_abbrevs[hash_number];
+ abbrev = cu_header->dwarf2_abbrevs[hash_number];
while (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, const struct comp_unit_head *cu_header)
{
unsigned int abbrev_number, bytes_read, i;
struct abbrev_info *abbrev;
int has_high_pc_attr = 0;
*part_die = zeroed_partial_die;
- *has_pc_info = 0;
abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
info_ptr += bytes_read;
if (!abbrev_number)
return info_ptr;
- abbrev = dwarf2_lookup_abbrev (abbrev_number);
+ abbrev = dwarf2_lookup_abbrev (abbrev_number, cu_header);
if (!abbrev)
{
- error ("Dwarf Error: Could not find abbrev number %d.", abbrev_number);
+ error ("Dwarf Error: Could not find abbrev number %d [in module %s]", abbrev_number,
+ bfd_get_filename (abfd));
}
part_die->offset = info_ptr - dwarf_info_buffer;
part_die->tag = abbrev->tag;
for (i = 0; i < abbrev->num_attrs; ++i)
{
- info_ptr = read_attribute (&attr, &abbrev->attrs[i], abfd, info_ptr);
+ info_ptr = read_attribute (&attr, &abbrev->attrs[i], abfd,
+ info_ptr, cu_header);
/* Store the data if it is of an attribute we want to keep in a
partial symbol table. */
part_die->highpc = DW_ADDR (&attr);
break;
case DW_AT_location:
- part_die->locdesc = DW_BLOCK (&attr);
+ /* Support the .debug_loc offsets */
+ if (attr_form_is_block (&attr))
+ {
+ part_die->locdesc = DW_BLOCK (&attr);
+ }
+ else if (attr.form == DW_FORM_data4 || attr.form == DW_FORM_data8)
+ {
+ dwarf2_complex_location_expr_complaint ();
+ }
+ else
+ {
+ dwarf2_invalid_attrib_class_complaint ("DW_AT_location",
+ "partial symbol information");
+ }
break;
case DW_AT_language:
part_die->language = DW_UNSND (&attr);
/* Ignore absolute siblings, they might point outside of
the current compile unit. */
if (attr.form == DW_FORM_ref_addr)
- complain (&dwarf2_absolute_sibling_complaint);
+ complaint (&symfile_complaints, "ignoring absolute DW_AT_sibling");
else
part_die->sibling =
dwarf_info_buffer + dwarf2_get_ref_die_offset (&attr);
int dummy;
spec_ptr = dwarf_info_buffer + dwarf2_get_ref_die_offset (&spec_attr);
- read_partial_die (&spec_die, abfd, spec_ptr, &dummy);
+ read_partial_die (&spec_die, abfd, spec_ptr, cu_header);
if (spec_die.name)
{
part_die->name = spec_die.name;
&& part_die->lowpc < part_die->highpc
&& (part_die->lowpc != 0
|| (bfd_get_file_flags (abfd) & HAS_RELOC)))
- *has_pc_info = 1;
+ part_die->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;
return info_ptr;
}
- abbrev = dwarf2_lookup_abbrev (abbrev_number);
+ abbrev = dwarf2_lookup_abbrev (abbrev_number, cu_header);
if (!abbrev)
{
- error ("Dwarf Error: could not find abbrev number %d.", abbrev_number);
+ error ("Dwarf Error: could not find abbrev number %d [in module %s]", abbrev_number,
+ bfd_get_filename (abfd));
}
die = dwarf_alloc_die ();
die->offset = offset;
for (i = 0; i < abbrev->num_attrs; ++i)
{
info_ptr = read_attribute (&die->attrs[i], &abbrev->attrs[i],
- abfd, info_ptr);
+ abfd, info_ptr, cu_header);
}
*diep = die;
return info_ptr;
}
-/* Read an attribute described by an abbreviated attribute. */
+/* Read an attribute value described by an attribute form. */
static char *
-read_attribute (attr, abbrev, abfd, info_ptr)
- struct attribute *attr;
- struct attr_abbrev *abbrev;
- bfd *abfd;
- char *info_ptr;
+read_attribute_value (struct attribute *attr, unsigned form,
+ bfd *abfd, char *info_ptr,
+ const struct comp_unit_head *cu_header)
{
unsigned int bytes_read;
struct dwarf_block *blk;
- attr->name = abbrev->name;
- attr->form = abbrev->form;
- switch (abbrev->form)
+ attr->form = form;
+ switch (form)
{
case DW_FORM_addr:
case DW_FORM_ref_addr:
- DW_ADDR (attr) = read_address (abfd, info_ptr);
- info_ptr += address_size;
+ 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 ();
DW_STRING (attr) = read_string (abfd, info_ptr, &bytes_read);
info_ptr += bytes_read;
break;
+ case DW_FORM_strp:
+ DW_STRING (attr) = read_indirect_string (abfd, info_ptr, cu_header,
+ &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);
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:
+ form = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
+ info_ptr += bytes_read;
+ info_ptr = read_attribute_value (attr, form, abfd, info_ptr, cu_header);
+ break;
default:
- error ("Dwarf Error: Cannot handle %s in DWARF reader.",
- dwarf_form_name (abbrev->form));
+ error ("Dwarf Error: Cannot handle %s in DWARF reader [in module %s]",
+ dwarf_form_name (form),
+ bfd_get_filename (abfd));
}
return info_ptr;
}
+/* Read an attribute described by an abbreviated attribute. */
+
+static char *
+read_attribute (struct attribute *attr, struct attr_abbrev *abbrev,
+ bfd *abfd, char *info_ptr,
+ const struct comp_unit_head *cu_header)
+{
+ attr->name = abbrev->name;
+ return read_attribute_value (attr, abbrev->form, abfd, info_ptr, cu_header);
+}
+
/* 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;
-{
- return bfd_get_signed_8 (abfd, (bfd_byte *) buf);
+static int
+read_1_signed_byte (bfd *abfd, char *buf)
+{
+ return bfd_get_signed_8 (abfd, (bfd_byte *) buf);
+}
+
+static unsigned int
+read_2_bytes (bfd *abfd, char *buf)
+{
+ return bfd_get_16 (abfd, (bfd_byte *) buf);
+}
+
+static int
+read_2_signed_bytes (bfd *abfd, char *buf)
+{
+ return bfd_get_signed_16 (abfd, (bfd_byte *) buf);
+}
+
+static unsigned int
+read_4_bytes (bfd *abfd, char *buf)
+{
+ return bfd_get_32 (abfd, (bfd_byte *) buf);
+}
+
+static int
+read_4_signed_bytes (bfd *abfd, char *buf)
+{
+ return bfd_get_signed_32 (abfd, (bfd_byte *) buf);
+}
+
+static unsigned long
+read_8_bytes (bfd *abfd, char *buf)
+{
+ return bfd_get_64 (abfd, (bfd_byte *) buf);
+}
+
+static CORE_ADDR
+read_address (bfd *abfd, char *buf, const struct comp_unit_head *cu_header,
+ int *bytes_read)
+{
+ CORE_ADDR retval = 0;
+
+ 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 (__FILE__, __LINE__,
+ "read_address: bad switch, signed [in module %s]",
+ bfd_get_filename (abfd));
+ }
+ }
+ 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 (__FILE__, __LINE__,
+ "read_address: bad switch, unsigned [in module %s]",
+ bfd_get_filename (abfd));
+ }
+ }
+
+ *bytes_read = cu_header->addr_size;
+ return retval;
}
-static unsigned int
-read_2_bytes (abfd, buf)
- bfd *abfd;
- char *buf;
+/* Read the initial length from a section. The (draft) DWARF 3
+ 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.
+
+ An older, non-standard 64-bit format is also handled by this
+ function. The older format in question stores the initial length
+ as an 8-byte quantity without an escape value. Lengths greater
+ than 2^32 aren't very common which means that the initial 4 bytes
+ is almost always zero. Since a length value of zero doesn't make
+ sense for the 32-bit format, this initial zero can be considered to
+ be an escape value which indicates the presence of the older 64-bit
+ format. As written, the code can't detect (old format) lengths
+ greater than 4GB. If it becomes necessary to handle lengths somewhat
+ larger than 4GB, we could allow other small values (such as the
+ non-sensical values of 1, 2, and 3) to also be used as escape values
+ indicating the presence of the old format.
+
+ 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
+ 3, draft 8, dated November 19, 2001. This document was obtained
+ from:
+
+ http://reality.sgiweb.org/davea/dwarf3-draft8-011125.pdf
+
+ This document is only a draft and is subject to change. (So beware.)
+
+ Details regarding the older, non-standard 64-bit format were
+ determined empirically by examining 64-bit ELF files produced
+ by the SGI toolchain on an IRIX 6.5 machine.
+
+ - Kevin, July 16, 2002
+ ] */
+
+static LONGEST
+read_initial_length (bfd *abfd, char *buf, struct comp_unit_head *cu_header,
+ int *bytes_read)
{
- return bfd_get_16 (abfd, (bfd_byte *) buf);
-}
+ LONGEST retval = 0;
-static int
-read_2_signed_bytes (abfd, buf)
- bfd *abfd;
- char *buf;
-{
- return bfd_get_signed_16 (abfd, (bfd_byte *) buf);
-}
+ retval = bfd_get_32 (abfd, (bfd_byte *) buf);
-static unsigned int
-read_4_bytes (abfd, buf)
- bfd *abfd;
- char *buf;
-{
- return 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 if (retval == 0)
+ {
+ /* Handle (non-standard) 64-bit DWARF2 formats such as that used
+ by IRIX. */
+ retval = bfd_get_64 (abfd, (bfd_byte *) buf);
+ *bytes_read = 8;
+ if (cu_header != NULL)
+ {
+ cu_header->initial_length_size = 8;
+ cu_header->offset_size = 8;
+ }
+ }
+ else
+ {
+ *bytes_read = 4;
+ if (cu_header != NULL)
+ {
+ cu_header->initial_length_size = 4;
+ cu_header->offset_size = 4;
+ }
+ }
-static int
-read_4_signed_bytes (abfd, buf)
- bfd *abfd;
- char *buf;
-{
- return bfd_get_signed_32 (abfd, (bfd_byte *) buf);
+ return retval;
}
-static unsigned int
-read_8_bytes (abfd, buf)
- bfd *abfd;
- char *buf;
-{
- return bfd_get_64 (abfd, (bfd_byte *) buf);
-}
+/* Read an offset from the data stream. The size of the offset is
+ given by cu_header->offset_size. */
-static CORE_ADDR
-read_address (abfd, buf)
- bfd *abfd;
- char *buf;
+static LONGEST
+read_offset (bfd *abfd, char *buf, const struct comp_unit_head *cu_header,
+ int *bytes_read)
{
- CORE_ADDR retval = 0;
+ LONGEST retval = 0;
- switch (address_size)
+ switch (cu_header->offset_size)
{
- case 2:
- retval = bfd_get_16 (abfd, (bfd_byte *) buf);
- break;
case 4:
retval = bfd_get_32 (abfd, (bfd_byte *) buf);
+ *bytes_read = 4;
break;
case 8:
retval = bfd_get_64 (abfd, (bfd_byte *) buf);
+ *bytes_read = 8;
break;
default:
- /* *THE* alternative is 8, right? */
- abort ();
+ internal_error (__FILE__, __LINE__,
+ "read_offset: bad switch [in module %s]",
+ bfd_get_filename (abfd));
}
- /* If the address being read is larger than the address that is
- applicable for the object file format then mask it down to the
- correct size. Take care to avoid unnecessary shift or shift
- overflow */
- if (address_size > address_significant_size
- && address_significant_size < sizeof (CORE_ADDR))
- {
- CORE_ADDR mask = ((CORE_ADDR) 0) - 1;
- retval &= ~(mask << (address_significant_size * 8));
- }
- 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
allocated on the temporary obstack. */
-#if HOST_CHAR_BIT == 8
+ gdb_assert (HOST_CHAR_BIT == 8);
return buf;
-#else
- char *ret;
- unsigned int i;
-
- ret = obstack_alloc (&dwarf2_tmp_obstack, size);
- for (i = 0; i < size; ++i)
- {
- ret[i] = bfd_get_8 (abfd, (bfd_byte *) buf);
- buf++;
- }
- return ret;
-#endif
}
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
allocated on the temporary obstack. */
-#if HOST_CHAR_BIT == 8
+ gdb_assert (HOST_CHAR_BIT == 8);
if (*buf == '\0')
{
*bytes_read_ptr = 1;
}
*bytes_read_ptr = strlen (buf) + 1;
return buf;
-#else
- int byte;
- unsigned int i = 0;
+}
+
+static char *
+read_indirect_string (bfd *abfd, char *buf,
+ const struct comp_unit_head *cu_header,
+ unsigned int *bytes_read_ptr)
+{
+ LONGEST str_offset = read_offset (abfd, buf, cu_header,
+ (int *) bytes_read_ptr);
- while ((byte = bfd_get_8 (abfd, (bfd_byte *) buf)) != 0)
+ if (dwarf_str_buffer == NULL)
{
- obstack_1grow (&dwarf2_tmp_obstack, byte);
- i++;
- buf++;
+ error ("DW_FORM_strp used without .debug_str section [in module %s]",
+ bfd_get_filename (abfd));
+ return NULL;
}
- if (i == 0)
+ if (str_offset >= dwarf_str_size)
{
- *bytes_read_ptr = 1;
+ error ("DW_FORM_strp pointing outside of .debug_str section [in module %s]",
+ bfd_get_filename (abfd));
return NULL;
}
- obstack_1grow (&dwarf2_tmp_obstack, '\0');
- *bytes_read_ptr = i + 1;
- return obstack_finish (&dwarf2_tmp_obstack);
-#endif
+ gdb_assert (HOST_CHAR_BIT == 8);
+ if (dwarf_str_buffer[str_offset] == '\0')
+ return NULL;
+ return dwarf_str_buffer + str_offset;
}
-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)
{
break;
case DW_LANG_Fortran77:
case DW_LANG_Fortran90:
+ case DW_LANG_Fortran95:
cu_language = language_fortran;
break;
case DW_LANG_Mips_Assembler:
cu_language = language_asm;
break;
+ case DW_LANG_Java:
+ cu_language = language_java;
+ break;
case DW_LANG_Ada83:
+ case DW_LANG_Ada95:
case DW_LANG_Cobol74:
case DW_LANG_Cobol85:
case DW_LANG_Pascal83:
/* 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;
&& ! 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. */
-struct filenames
+/* Free the line_header structure *LH, and any arrays and strings it
+ refers to. */
+static void
+free_line_header (struct line_header *lh)
+{
+ if (lh->standard_opcode_lengths)
+ xfree (lh->standard_opcode_lengths);
+
+ /* Remember that all the lh->file_names[i].name pointers are
+ pointers into debug_line_buffer, and don't need to be freed. */
+ if (lh->file_names)
+ xfree (lh->file_names);
+
+ /* Similarly for the include directory names. */
+ if (lh->include_dirs)
+ xfree (lh->include_dirs);
+
+ xfree (lh);
+}
+
+
+/* Add an entry to LH's include directory table. */
+static void
+add_include_dir (struct line_header *lh, char *include_dir)
{
- unsigned int num_files;
- struct fileinfo
+ /* Grow the array if necessary. */
+ if (lh->include_dirs_size == 0)
{
- char *name;
- unsigned int dir;
- unsigned int time;
- unsigned int size;
+ lh->include_dirs_size = 1; /* for testing */
+ lh->include_dirs = xmalloc (lh->include_dirs_size
+ * sizeof (*lh->include_dirs));
+ }
+ else if (lh->num_include_dirs >= lh->include_dirs_size)
+ {
+ lh->include_dirs_size *= 2;
+ lh->include_dirs = xrealloc (lh->include_dirs,
+ (lh->include_dirs_size
+ * sizeof (*lh->include_dirs)));
}
- *files;
-};
-struct directories
- {
- unsigned int num_dirs;
- char **dirs;
- };
+ lh->include_dirs[lh->num_include_dirs++] = include_dir;
+}
+
+/* Add an entry to LH's file name table. */
static void
-dwarf_decode_lines (offset, comp_dir, abfd)
- unsigned int offset;
- char *comp_dir;
- bfd *abfd;
+add_file_name (struct line_header *lh,
+ char *name,
+ unsigned int dir_index,
+ unsigned int mod_time,
+ unsigned int length)
{
- char *line_ptr;
- char *line_end;
- struct line_head lh;
- struct cleanup *back_to;
- unsigned int i, bytes_read;
- char *cur_file, *cur_dir;
- unsigned char op_code, extended_op, adj_opcode;
+ struct file_entry *fe;
-#define FILE_ALLOC_CHUNK 5
-#define DIR_ALLOC_CHUNK 5
+ /* Grow the array if necessary. */
+ if (lh->file_names_size == 0)
+ {
+ lh->file_names_size = 1; /* for testing */
+ lh->file_names = xmalloc (lh->file_names_size
+ * sizeof (*lh->file_names));
+ }
+ else if (lh->num_file_names >= lh->file_names_size)
+ {
+ lh->file_names_size *= 2;
+ lh->file_names = xrealloc (lh->file_names,
+ (lh->file_names_size
+ * sizeof (*lh->file_names)));
+ }
- struct filenames files;
- struct directories dirs;
+ fe = &lh->file_names[lh->num_file_names++];
+ fe->name = name;
+ fe->dir_index = dir_index;
+ fe->mod_time = mod_time;
+ fe->length = length;
+}
+
+
+/* Read the statement program header starting at OFFSET in
+ dwarf_line_buffer, according to the endianness of ABFD. Return a
+ pointer to a struct line_header, allocated using xmalloc.
+
+ NOTE: the strings in the include directory and file name tables of
+ the returned object point into debug_line_buffer, and must not be
+ freed. */
+static struct line_header *
+dwarf_decode_line_header (unsigned int offset, bfd *abfd,
+ const struct comp_unit_head *cu_header)
+{
+ struct cleanup *back_to;
+ struct line_header *lh;
+ char *line_ptr;
+ int bytes_read;
+ int i;
+ char *cur_dir, *cur_file;
if (dwarf_line_buffer == NULL)
{
- complain (&dwarf2_missing_line_number_section);
- return;
+ complaint (&symfile_complaints, "missing .debug_line section");
+ return 0;
}
- files.num_files = 0;
- files.files = NULL;
+ /* Make sure that at least there's room for the total_length field. That
+ could be 12 bytes long, but we're just going to fudge that. */
+ if (offset + 4 >= dwarf_line_size)
+ {
+ dwarf2_statement_list_fits_in_line_number_section_complaint ();
+ return 0;
+ }
- dirs.num_dirs = 0;
- dirs.dirs = NULL;
+ lh = xmalloc (sizeof (*lh));
+ memset (lh, 0, sizeof (*lh));
+ back_to = make_cleanup ((make_cleanup_ftype *) free_line_header,
+ (void *) lh);
line_ptr = dwarf_line_buffer + offset;
- /* read in the prologue */
- lh.total_length = read_4_bytes (abfd, line_ptr);
- line_ptr += 4;
- line_end = line_ptr + lh.total_length;
- lh.version = read_2_bytes (abfd, line_ptr);
+ /* read in the header */
+ lh->total_length = read_initial_length (abfd, line_ptr, NULL, &bytes_read);
+ line_ptr += bytes_read;
+ if (line_ptr + lh->total_length > dwarf_line_buffer + dwarf_line_size)
+ {
+ dwarf2_statement_list_fits_in_line_number_section_complaint ();
+ return 0;
+ }
+ lh->statement_program_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.minimum_instruction_length = read_1_byte (abfd, line_ptr);
+ lh->header_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);
+ lh->default_is_stmt = read_1_byte (abfd, line_ptr);
line_ptr += 1;
- lh.line_base = read_1_signed_byte (abfd, line_ptr);
+ lh->line_base = read_1_signed_byte (abfd, line_ptr);
line_ptr += 1;
- lh.line_range = read_1_byte (abfd, line_ptr);
+ lh->line_range = read_1_byte (abfd, line_ptr);
line_ptr += 1;
- lh.opcode_base = read_1_byte (abfd, line_ptr);
+ lh->opcode_base = read_1_byte (abfd, line_ptr);
line_ptr += 1;
- lh.standard_opcode_lengths = (unsigned char *)
- xmalloc (lh.opcode_base * sizeof (unsigned char));
- back_to = make_cleanup ((make_cleanup_func) free_current_contents,
- &lh.standard_opcode_lengths);
+ lh->standard_opcode_lengths
+ = (unsigned char *) xmalloc (lh->opcode_base * sizeof (unsigned char));
- lh.standard_opcode_lengths[0] = 1;
- for (i = 1; i < lh.opcode_base; ++i)
+ lh->standard_opcode_lengths[0] = 1; /* This should never be used anyway. */
+ for (i = 1; i < lh->opcode_base; ++i)
{
- lh.standard_opcode_lengths[i] = read_1_byte (abfd, line_ptr);
+ lh->standard_opcode_lengths[i] = read_1_byte (abfd, line_ptr);
line_ptr += 1;
}
while ((cur_dir = read_string (abfd, line_ptr, &bytes_read)) != NULL)
{
line_ptr += bytes_read;
- if ((dirs.num_dirs % DIR_ALLOC_CHUNK) == 0)
- {
- dirs.dirs = (char **)
- xrealloc (dirs.dirs,
- (dirs.num_dirs + DIR_ALLOC_CHUNK) * sizeof (char *));
- if (dirs.num_dirs == 0)
- make_cleanup ((make_cleanup_func) free_current_contents, &dirs.dirs);
- }
- dirs.dirs[dirs.num_dirs++] = cur_dir;
+ add_include_dir (lh, cur_dir);
}
line_ptr += bytes_read;
/* Read file name table */
while ((cur_file = read_string (abfd, line_ptr, &bytes_read)) != NULL)
{
+ unsigned int dir_index, mod_time, length;
+
line_ptr += bytes_read;
- if ((files.num_files % FILE_ALLOC_CHUNK) == 0)
- {
- files.files = (struct fileinfo *)
- xrealloc (files.files,
- (files.num_files + FILE_ALLOC_CHUNK)
- * sizeof (struct fileinfo));
- if (files.num_files == 0)
- make_cleanup ((make_cleanup_func) free_current_contents,
- &files.files);
- }
- files.files[files.num_files].name = cur_file;
- files.files[files.num_files].dir =
- read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+ dir_index = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
line_ptr += bytes_read;
- files.files[files.num_files].time =
- read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+ mod_time = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
line_ptr += bytes_read;
- files.files[files.num_files].size =
- read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+ length = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
line_ptr += bytes_read;
- files.num_files++;
+
+ add_file_name (lh, cur_file, dir_index, mod_time, length);
}
line_ptr += bytes_read;
+ lh->statement_program_start = line_ptr;
+
+ if (line_ptr > dwarf_line_buffer + dwarf_line_size)
+ complaint (&symfile_complaints,
+ "line number info header doesn't fit in `.debug_line' section");
+
+ discard_cleanups (back_to);
+ return lh;
+}
+
+/* This function exists to work around a bug in certain compilers
+ (particularly GCC 2.95), in which the first line number marker of a
+ function does not show up until after the prologue, right before
+ the second line number marker. This function shifts ADDRESS down
+ to the beginning of the function if necessary, and is called on
+ addresses passed to record_line. */
+
+static CORE_ADDR
+check_cu_functions (CORE_ADDR address)
+{
+ struct function_range *fn;
+
+ /* Find the function_range containing address. */
+ if (!cu_first_fn)
+ return address;
+
+ if (!cu_cached_fn)
+ cu_cached_fn = cu_first_fn;
+
+ fn = cu_cached_fn;
+ while (fn)
+ if (fn->lowpc <= address && fn->highpc > address)
+ goto found;
+ else
+ fn = fn->next;
+
+ fn = cu_first_fn;
+ while (fn && fn != cu_cached_fn)
+ if (fn->lowpc <= address && fn->highpc > address)
+ goto found;
+ else
+ fn = fn->next;
+
+ return address;
+
+ found:
+ if (fn->seen_line)
+ return address;
+ if (address != fn->lowpc)
+ complaint (&symfile_complaints,
+ "misplaced first line number at 0x%lx for '%s'",
+ (unsigned long) address, fn->name);
+ fn->seen_line = 1;
+ return fn->lowpc;
+}
+
+/* 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. */
+
+static void
+dwarf_decode_lines (struct line_header *lh, char *comp_dir, bfd *abfd,
+ const struct comp_unit_head *cu_header)
+{
+ char *line_ptr;
+ char *line_end;
+ unsigned int i, bytes_read;
+ char *cur_dir;
+ unsigned char op_code, extended_op, adj_opcode;
+
+ line_ptr = lh->statement_program_start;
+ line_end = lh->statement_program_end;
/* Read the statement sequences until there's nothing left. */
while (line_ptr < line_end)
unsigned int file = 1;
unsigned int line = 1;
unsigned int column = 0;
- int is_stmt = lh.default_is_stmt;
+ int is_stmt = lh->default_is_stmt;
int basic_block = 0;
int end_sequence = 0;
/* Start a subfile for the current file of the state machine. */
- if (files.num_files >= file)
+ if (lh->num_file_names >= file)
{
- /* The file and directory tables are 0 based, the references
- are 1 based. */
- dwarf2_start_subfile (files.files[file - 1].name,
- (files.files[file - 1].dir
- ? dirs.dirs[files.files[file - 1].dir - 1]
- : comp_dir));
+ /* lh->include_dirs and lh->file_names are 0-based, but the
+ directory and file name numbers in the statement program
+ are 1-based. */
+ struct file_entry *fe = &lh->file_names[file - 1];
+ char *dir;
+ if (fe->dir_index)
+ dir = lh->include_dirs[fe->dir_index - 1];
+ else
+ dir = comp_dir;
+ dwarf2_start_subfile (fe->name, dir);
}
/* Decode the table. */
{
op_code = read_1_byte (abfd, line_ptr);
line_ptr += 1;
- switch (op_code)
+
+ if (op_code >= lh->opcode_base)
+ { /* Special operand. */
+ adj_opcode = op_code - lh->opcode_base;
+ address += (adj_opcode / lh->line_range)
+ * lh->minimum_instruction_length;
+ line += lh->line_base + (adj_opcode % lh->line_range);
+ /* append row to matrix using current values */
+ address = check_cu_functions (address);
+ record_line (current_subfile, line, address);
+ basic_block = 1;
+ }
+ else switch (op_code)
{
case DW_LNS_extended_op:
line_ptr += 1; /* ignore length */
{
case DW_LNE_end_sequence:
end_sequence = 1;
- /* 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. */
+ record_line (current_subfile, 0, address);
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);
- line_ptr += bytes_read;
- if ((files.num_files % FILE_ALLOC_CHUNK) == 0)
- {
- files.files = (struct fileinfo *)
- xrealloc (files.files,
- (files.num_files + FILE_ALLOC_CHUNK)
- * sizeof (struct fileinfo));
- if (files.num_files == 0)
- make_cleanup ((make_cleanup_func) free_current_contents,
- &files.files);
- }
- files.files[files.num_files].name = cur_file;
- files.files[files.num_files].dir =
- read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
- line_ptr += bytes_read;
- files.files[files.num_files].time =
- read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
- line_ptr += bytes_read;
- files.files[files.num_files].size =
- read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
- line_ptr += bytes_read;
- files.num_files++;
+ {
+ char *cur_file;
+ unsigned int dir_index, mod_time, length;
+
+ cur_file = read_string (abfd, line_ptr, &bytes_read);
+ line_ptr += bytes_read;
+ dir_index =
+ read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+ line_ptr += bytes_read;
+ mod_time =
+ read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+ line_ptr += bytes_read;
+ length =
+ read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+ line_ptr += bytes_read;
+ add_file_name (lh, cur_file, dir_index, mod_time, length);
+ }
break;
default:
- complain (&dwarf2_mangled_line_number_section);
- goto done;
+ complaint (&symfile_complaints,
+ "mangled .debug_line section");
+ return;
}
break;
case DW_LNS_copy:
+ address = check_cu_functions (address);
record_line (current_subfile, line, address);
basic_block = 0;
break;
case DW_LNS_advance_pc:
- address += lh.minimum_instruction_length
+ address += lh->minimum_instruction_length
* read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
line_ptr += bytes_read;
break;
line_ptr += bytes_read;
break;
case DW_LNS_set_file:
- /* The file and directory tables are 0 based, the references
- are 1 based. */
- file = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
- line_ptr += bytes_read;
- dwarf2_start_subfile
- (files.files[file - 1].name,
- (files.files[file - 1].dir
- ? dirs.dirs[files.files[file - 1].dir - 1]
- : comp_dir));
+ {
+ /* lh->include_dirs and lh->file_names are 0-based,
+ but the directory and file name numbers in the
+ statement program are 1-based. */
+ struct file_entry *fe;
+ char *dir;
+ file = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+ line_ptr += bytes_read;
+ fe = &lh->file_names[file - 1];
+ if (fe->dir_index)
+ dir = lh->include_dirs[fe->dir_index - 1];
+ else
+ dir = comp_dir;
+ dwarf2_start_subfile (fe->name, dir);
+ }
break;
case DW_LNS_set_column:
column = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
length since special opcode 255 would have scaled the
the increment. */
case DW_LNS_const_add_pc:
- address += (lh.minimum_instruction_length
- * ((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);
line_ptr += 2;
break;
- default: /* special operand */
- adj_opcode = op_code - lh.opcode_base;
- address += (adj_opcode / lh.line_range)
- * lh.minimum_instruction_length;
- line += lh.line_base + (adj_opcode % lh.line_range);
- /* append row to matrix using current values */
- record_line (current_subfile, line, address);
- basic_block = 1;
+ default:
+ { /* Unknown standard opcode, ignore it. */
+ int i;
+ for (i = 0; i < lh->standard_opcode_lengths[op_code]; i++)
+ {
+ (void) read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+ line_ptr += bytes_read;
+ }
+ }
}
}
}
-done:
- do_cleanups (back_to);
}
/* Start a subfile for DWARF. FILENAME is the name of the file and
DW_AT_name: /srcdir/list0.c
DW_AT_comp_dir: /compdir
- files.files[0].name: list0.h
+ files.files[0].name: list0.h
files.files[0].dir: /srcdir
- files.files[1].name: list0.c
+ 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 (*filename != '/' && dirname != NULL)
+ if (!IS_ABSOLUTE_PATH (filename) && dirname != NULL)
{
struct subfile *subfile;
char *fullname = concat (dirname, "/", filename, NULL);
for (subfile = subfiles; subfile; subfile = subfile->next)
{
- if (STREQ (subfile->name, fullname))
+ if (FILENAME_CMP (subfile->name, fullname) == 0)
{
current_subfile = subfile;
- free (fullname);
+ xfree (fullname);
return;
}
}
- free (fullname);
+ xfree (fullname);
}
start_subfile (filename, dirname);
}
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;
+ CORE_ADDR addr = 0;
name = dwarf2_linkage_name (die);
if (name)
sizeof (struct symbol));
OBJSTAT (objfile, n_syms++);
memset (sym, 0, sizeof (struct symbol));
- SYMBOL_NAME (sym) = obsavestring (name, strlen (name),
- &objfile->symbol_obstack);
+
+ /* Cache this symbol's name and the name's demangled form (if any). */
+ SYMBOL_LANGUAGE (sym) = cu_language;
+ SYMBOL_SET_NAMES (sym, name, strlen (name), objfile);
/* Default assumptions.
Use the passed type or decode it from the die. */
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)
{
SYMBOL_LINE (sym) = DW_UNSND (attr);
}
-
- /* If this symbol is from a C++ compilation, then attempt to
- cache the demangled form for future reference. This is a
- typical time versus space tradeoff, that was decided in favor
- of time because it sped up C++ symbol lookups by a factor of
- about 20. */
-
- SYMBOL_LANGUAGE (sym) = cu_language;
- SYMBOL_INIT_DEMANGLED_NAME (sym, &objfile->symbol_obstack);
switch (die->tag)
{
case DW_TAG_label:
attr = dwarf_attr (die, DW_AT_const_value);
if (attr)
{
- dwarf2_const_value (attr, sym, objfile);
+ 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);
attr2 = dwarf_attr (die, DW_AT_external);
if (attr2 && (DW_UNSND (attr2) != 0))
{
- SYMBOL_VALUE_ADDRESS (sym) =
- decode_locdesc (DW_BLOCK (attr), objfile);
+ /* Support the .debug_loc offsets */
+ if (attr_form_is_block (attr))
+ {
+ SYMBOL_VALUE_ADDRESS (sym) =
+ decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
+ }
+ else if (attr->form == DW_FORM_data4
+ || attr->form == DW_FORM_data8)
+ {
+ dwarf2_complex_location_expr_complaint ();
+ }
+ else
+ {
+ dwarf2_invalid_attrib_class_complaint ("DW_AT_location",
+ "external variable");
+ }
add_symbol_to_list (sym, &global_symbols);
+ if (is_thread_local)
+ {
+ /* SYMBOL_VALUE_ADDRESS contains at this point the
+ offset of the variable within the thread local
+ storage. */
+ SYMBOL_CLASS (sym) = LOC_THREAD_LOCAL_STATIC;
+ SYMBOL_OBJFILE (sym) = objfile;
+ }
/* In shared libraries the address of the variable
in the location descriptor might still be relocatable,
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))
+ else if (SYMBOL_VALUE_ADDRESS (sym))
{
- SYMBOL_VALUE_ADDRESS (sym) += baseaddr;
+ fixup_symbol_section (sym, objfile);
+ SYMBOL_VALUE_ADDRESS (sym) +=
+ ANOFFSET (objfile->section_offsets,
+ SYMBOL_SECTION (sym));
SYMBOL_CLASS (sym) = LOC_STATIC;
}
else
}
else
{
- SYMBOL_VALUE (sym) = addr =
- decode_locdesc (DW_BLOCK (attr), objfile);
+ /* Support the .debug_loc offsets */
+ if (attr_form_is_block (attr))
+ {
+ SYMBOL_VALUE (sym) = addr =
+ decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
+ }
+ else if (attr->form == DW_FORM_data4
+ || attr->form == DW_FORM_data8)
+ {
+ dwarf2_complex_location_expr_complaint ();
+ }
+ else
+ {
+ dwarf2_invalid_attrib_class_complaint ("DW_AT_location",
+ "external variable");
+ addr = 0;
+ }
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)
{
SYMBOL_CLASS (sym) = LOC_LOCAL;
}
+ else if (is_thread_local)
+ {
+ SYMBOL_CLASS (sym) = LOC_THREAD_LOCAL_STATIC;
+ SYMBOL_OBJFILE (sym) = objfile;
+ }
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;
}
}
}
attr = dwarf_attr (die, DW_AT_location);
if (attr)
{
- SYMBOL_VALUE (sym) = decode_locdesc (DW_BLOCK (attr), objfile);
+ 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);
+ dwarf2_complex_location_expr_complaint ();
SYMBOL_CLASS (sym) = LOC_REF_ARG;
}
else
{
SYMBOL_CLASS (sym) = LOC_BASEREG_ARG;
- SYMBOL_BASEREG (sym) = basereg;
+ SYMBOL_BASEREG (sym) = DWARF2_REG_TO_REGNUM (basereg);
}
}
else
attr = dwarf_attr (die, DW_AT_const_value);
if (attr)
{
- dwarf2_const_value (attr, sym, objfile);
+ dwarf2_const_value (attr, sym, objfile, cu_header);
}
add_symbol_to_list (sym, list_in_scope);
break;
attr = dwarf_attr (die, DW_AT_const_value);
if (attr)
{
- dwarf2_const_value (attr, sym, objfile);
+ dwarf2_const_value (attr, sym, objfile, cu_header);
}
add_symbol_to_list (sym, list_in_scope);
break;
trash data, but since we must specifically ignore things
we don't recognize, there is nothing else we should do at
this point. */
- complain (&dwarf2_unsupported_tag, dwarf_tag_name (die->tag));
+ complaint (&symfile_complaints, "unsupported tag: '%s'",
+ dwarf_tag_name (die->tag));
break;
}
}
/* Copy constant value from an attribute to a symbol. */
static void
-dwarf2_const_value (attr, sym, objfile)
- struct attribute *attr;
- struct symbol *sym;
- struct objfile *objfile;
+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)) != (unsigned int) address_size)
- complain (&dwarf2_const_value_length_mismatch, SYMBOL_NAME (sym),
- address_size, TYPE_LENGTH (SYMBOL_TYPE (sym)));
+ if (TYPE_LENGTH (SYMBOL_TYPE (sym)) != cu_header->addr_size)
+ dwarf2_const_value_length_mismatch_complaint (SYMBOL_NAME (sym),
+ cu_header->addr_size,
+ TYPE_LENGTH (SYMBOL_TYPE
+ (sym)));
SYMBOL_VALUE_BYTES (sym) = (char *)
- obstack_alloc (&objfile->symbol_obstack, address_size);
- store_address (SYMBOL_VALUE_BYTES (sym), address_size, DW_ADDR (attr));
+ 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_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)));
+ dwarf2_const_value_length_mismatch_complaint (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);
break;
default:
- complain (&dwarf2_unsupported_const_value_attr,
- dwarf_form_name (attr->form));
+ complaint (&symfile_complaints,
+ "unsupported const value attribute form: '%s'",
+ dwarf_form_name (attr->form));
SYMBOL_VALUE (sym) = 0;
SYMBOL_CLASS (sym) = LOC_CONST;
break;
if (TYPE_UNSIGNED (SYMBOL_TYPE (sym)))
l &= ((LONGEST) 1 << bits) - 1;
else
- l = (l << (sizeof (l) - bits)) >> (sizeof (l) - bits);
+ l = (l << (sizeof (l) * 8 - bits)) >> (sizeof (l) * 8 - bits);
}
SYMBOL_VALUE (sym) = l;
/* 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;
type_die = follow_die_ref (ref);
if (!type_die)
{
- error ("Dwarf Error: Cannot find referent at offset %d.", ref);
+ error ("Dwarf Error: Cannot find referent at offset %d [in module %s]",
+ ref, objfile->name);
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);
- error ("Dwarf Error: Problem turning type die at offset into gdb type.");
+ error ("Dwarf Error: Problem turning type die at offset into gdb type [in module %s]",
+ objfile->name);
}
return type;
}
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;
type_die = follow_die_ref (ref);
if (!type_die)
{
- error ("Dwarf Error: Cannot find referent at offset %d.", ref);
+ error ("Dwarf Error: Cannot find referent at offset %d [in module %s]", ref,
+ objfile->name);
return NULL;
}
- type = tag_type_to_type (type_die, objfile);
+ type = tag_type_to_type (type_die, objfile, cu_header);
}
if (!type)
{
if (type_die)
dump_die (type_die);
- error ("Dwarf Error: Problem turning containing type into gdb type.");
+ error ("Dwarf Error: Problem turning containing type into gdb type [in module %s]",
+ objfile->name);
}
return 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);
- error ("Dwarf Error: Cannot find type of die.");
+ error ("Dwarf Error: Cannot find type of die [in module %s]",
+ objfile->name);
}
return die->type;
}
}
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:
- 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;
default:
- complain (&dwarf2_unexpected_tag, dwarf_tag_name (die->tag));
+ complaint (&symfile_complaints, "unexepected tag in read_type_die: '%s'",
+ dwarf_tag_name (die->tag));
break;
}
}
static struct type *
-dwarf_base_type (encoding, size, objfile)
- int encoding;
- int size;
- struct objfile *objfile;
+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. */
#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;
+static struct die_info *
+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 (die)
- struct die_info *die;
+dwarf2_linkage_name (struct die_info *die)
{
struct attribute *attr;
/* 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)
{
return "DW_TAG_variable";
case DW_TAG_volatile_type:
return "DW_TAG_volatile_type";
+ case DW_TAG_dwarf_procedure:
+ return "DW_TAG_dwarf_procedure";
+ case DW_TAG_restrict_type:
+ return "DW_TAG_restrict_type";
+ case DW_TAG_interface_type:
+ return "DW_TAG_interface_type";
+ case DW_TAG_namespace:
+ return "DW_TAG_namespace";
+ case DW_TAG_imported_module:
+ return "DW_TAG_imported_module";
+ case DW_TAG_unspecified_type:
+ return "DW_TAG_unspecified_type";
+ case DW_TAG_partial_unit:
+ return "DW_TAG_partial_unit";
+ case DW_TAG_imported_unit:
+ return "DW_TAG_imported_unit";
case DW_TAG_MIPS_loop:
return "DW_TAG_MIPS_loop";
case DW_TAG_format_label:
/* 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)
{
return "DW_AT_virtuality";
case DW_AT_vtable_elem_location:
return "DW_AT_vtable_elem_location";
-
+ case DW_AT_allocated:
+ return "DW_AT_allocated";
+ case DW_AT_associated:
+ return "DW_AT_associated";
+ case DW_AT_data_location:
+ return "DW_AT_data_location";
+ case DW_AT_stride:
+ return "DW_AT_stride";
+ case DW_AT_entry_pc:
+ return "DW_AT_entry_pc";
+ case DW_AT_use_UTF8:
+ return "DW_AT_use_UTF8";
+ case DW_AT_extension:
+ return "DW_AT_extension";
+ case DW_AT_ranges:
+ return "DW_AT_ranges";
+ case DW_AT_trampoline:
+ return "DW_AT_trampoline";
+ case DW_AT_call_column:
+ return "DW_AT_call_column";
+ case DW_AT_call_file:
+ return "DW_AT_call_file";
+ case DW_AT_call_line:
+ return "DW_AT_call_line";
#ifdef MIPS
case DW_AT_MIPS_fde:
return "DW_AT_MIPS_fde";
return "DW_AT_body_begin";
case DW_AT_body_end:
return "DW_AT_body_end";
+ case DW_AT_GNU_vector:
+ return "DW_AT_GNU_vector";
default:
return "DW_AT_<unknown>";
}
/* 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)
{
return "DW_OP_xderef_size";
case DW_OP_nop:
return "DW_OP_nop";
+ /* DWARF 3 extensions. */
+ case DW_OP_push_object_address:
+ return "DW_OP_push_object_address";
+ case DW_OP_call2:
+ return "DW_OP_call2";
+ case DW_OP_call4:
+ return "DW_OP_call4";
+ case DW_OP_call_ref:
+ return "DW_OP_call_ref";
+ /* GNU extensions. */
+ case DW_OP_GNU_push_tls_address:
+ return "DW_OP_GNU_push_tls_address";
default:
return "OP_<unknown>";
}
}
static char *
-dwarf_bool_name (mybool)
- unsigned mybool;
+dwarf_bool_name (unsigned mybool)
{
if (mybool)
return "TRUE";
/* 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)
{
return "DW_ATE_unsigned";
case DW_ATE_unsigned_char:
return "DW_ATE_unsigned_char";
+ case DW_ATE_imaginary_float:
+ return "DW_ATE_imaginary_float";
default:
return "DW_ATE_<unknown>";
}
#if 0
static char *
-dwarf_cfi_name (cfi_opc)
- register unsigned cfi_opc;
+dwarf_cfi_name (register unsigned cfi_opc)
{
switch (cfi_opc)
{
return "DW_CFA_def_cfa_register";
case DW_CFA_def_cfa_offset:
return "DW_CFA_def_cfa_offset";
+
+ /* DWARF 3 */
+ case DW_CFA_def_cfa_expression:
+ return "DW_CFA_def_cfa_expression";
+ case DW_CFA_expression:
+ return "DW_CFA_expression";
+ case DW_CFA_offset_extended_sf:
+ return "DW_CFA_offset_extended_sf";
+ case DW_CFA_def_cfa_sf:
+ return "DW_CFA_def_cfa_sf";
+ case DW_CFA_def_cfa_offset_sf:
+ return "DW_CFA_def_cfa_offset_sf";
+
/* SGI/MIPS specific */
case DW_CFA_MIPS_advance_loc8:
return "DW_CFA_MIPS_advance_loc8";
+
+ /* GNU extensions */
+ case DW_CFA_GNU_window_save:
+ return "DW_CFA_GNU_window_save";
+ case DW_CFA_GNU_args_size:
+ return "DW_CFA_GNU_args_size";
+ case DW_CFA_GNU_negative_offset_extended:
+ return "DW_CFA_GNU_negative_offset_extended";
+
default:
return "DW_CFA_<unknown>";
}
}
#endif
-void
-dump_die (die)
- struct die_info *die;
+static void
+dump_die (struct die_info *die)
{
unsigned int i;
- fprintf (stderr, "Die: %s (abbrev = %d, offset = %d)\n",
+ fprintf_unfiltered (gdb_stderr, "Die: %s (abbrev = %d, offset = %d)\n",
dwarf_tag_name (die->tag), die->abbrev, die->offset);
- fprintf (stderr, "\thas children: %s\n",
+ fprintf_unfiltered (gdb_stderr, "\thas children: %s\n",
dwarf_bool_name (die->has_children));
- fprintf (stderr, "\tattributes:\n");
+ fprintf_unfiltered (gdb_stderr, "\tattributes:\n");
for (i = 0; i < die->num_attrs; ++i)
{
- fprintf (stderr, "\t\t%s (%s) ",
+ fprintf_unfiltered (gdb_stderr, "\t\t%s (%s) ",
dwarf_attr_name (die->attrs[i].name),
dwarf_form_name (die->attrs[i].form));
switch (die->attrs[i].form)
{
case DW_FORM_ref_addr:
case DW_FORM_addr:
- fprintf (stderr, "address: ");
+ fprintf_unfiltered (gdb_stderr, "address: ");
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", DW_BLOCK (&die->attrs[i])->size);
+ fprintf_unfiltered (gdb_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", DW_UNSND (&die->attrs[i]));
+ fprintf_unfiltered (gdb_stderr, "constant: %ld", DW_UNSND (&die->attrs[i]));
break;
case DW_FORM_string:
- fprintf (stderr, "string: \"%s\"",
+ case DW_FORM_strp:
+ fprintf_unfiltered (gdb_stderr, "string: \"%s\"",
DW_STRING (&die->attrs[i])
? DW_STRING (&die->attrs[i]) : "");
break;
case DW_FORM_flag:
if (DW_UNSND (&die->attrs[i]))
- fprintf (stderr, "flag: TRUE");
+ fprintf_unfiltered (gdb_stderr, "flag: TRUE");
else
- fprintf (stderr, "flag: FALSE");
+ fprintf_unfiltered (gdb_stderr, "flag: FALSE");
+ break;
+ case DW_FORM_indirect:
+ /* the reader will have reduced the indirect form to
+ the "base form" so this form should not occur */
+ fprintf_unfiltered (gdb_stderr, "unexpected attribute form: DW_FORM_indirect");
break;
- 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.",
+ fprintf_unfiltered (gdb_stderr, "unsupported attribute form: %d.",
die->attrs[i].form);
}
- fprintf (stderr, "\n");
+ fprintf_unfiltered (gdb_stderr, "\n");
}
}
-void
-dump_die_list (die)
- struct die_info *die;
+static void
+dump_die_list (struct die_info *die)
{
while (die)
{
}
}
-void
-store_in_ref_table (offset, die)
- unsigned int offset;
- struct die_info *die;
+static void
+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;
default:
- complain (&dwarf2_unsupported_die_ref_attr, dwarf_form_name (attr->form));
+ complaint (&symfile_complaints,
+ "unsupported die ref attribute form: '%s'",
+ dwarf_form_name (attr->form));
}
return result;
}
-struct die_info *
-follow_die_ref (offset)
- unsigned int offset;
+static struct die_info *
+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)
{
- error ("Dwarf Error: internal error - invalid fundamental type id %d.",
- typeid);
+ error ("Dwarf Error: internal error - invalid fundamental type id %d [in module %s]",
+ typeid, objfile->name);
}
/* Look for this particular type in the fundamental type vector. If
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;
offreg = 0;
isderef = 0;
islocal = 0;
+ is_thread_local = 0;
optimized_out = 1;
while (i < size)
op = data[i++];
switch (op)
{
+ case DW_OP_lit0:
+ case DW_OP_lit1:
+ case DW_OP_lit2:
+ case DW_OP_lit3:
+ case DW_OP_lit4:
+ case DW_OP_lit5:
+ case DW_OP_lit6:
+ case DW_OP_lit7:
+ case DW_OP_lit8:
+ case DW_OP_lit9:
+ case DW_OP_lit10:
+ case DW_OP_lit11:
+ case DW_OP_lit12:
+ case DW_OP_lit13:
+ case DW_OP_lit14:
+ case DW_OP_lit15:
+ case DW_OP_lit16:
+ case DW_OP_lit17:
+ case DW_OP_lit18:
+ case DW_OP_lit19:
+ case DW_OP_lit20:
+ case DW_OP_lit21:
+ case DW_OP_lit22:
+ case DW_OP_lit23:
+ case DW_OP_lit24:
+ case DW_OP_lit25:
+ case DW_OP_lit26:
+ case DW_OP_lit27:
+ case DW_OP_lit28:
+ case DW_OP_lit29:
+ case DW_OP_lit30:
+ case DW_OP_lit31:
+ stack[++stacki] = op - DW_OP_lit0;
+ break;
+
case DW_OP_reg0:
case DW_OP_reg1:
case DW_OP_reg2:
isreg = 1;
unsnd = read_unsigned_leb128 (NULL, (data + i), &bytes_read);
i += bytes_read;
-#if defined(HARRIS_TARGET) && defined(_M88K)
- /* The Harris 88110 gdb ports have long kept their special reg
- numbers between their gp-regs and their x-regs. This is
- not how our dwarf is generated. Punt. */
- unsnd += 6;
-#endif
stack[++stacki] = unsnd;
break;
}
else
{
- complain (&dwarf2_missing_at_frame_base);
+ complaint (&symfile_complaints,
+ "DW_AT_frame_base missing for DW_OP_fbreg");
islocal = 1;
}
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:
i += bytes_read;
break;
+ case DW_OP_dup:
+ stack[stacki + 1] = stack[stacki];
+ stacki++;
+ break;
+
case DW_OP_plus:
stack[stacki - 1] += stack[stacki];
stacki--;
break;
case DW_OP_minus:
- stack[stacki - 1] = stack[stacki] - stack[stacki - 1];
+ stack[stacki - 1] -= stack[stacki];
stacki--;
break;
/* 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);
+ dwarf2_complex_location_expr_complaint ();
break;
+ case DW_OP_GNU_push_tls_address:
+ is_thread_local = 1;
+ /* The top of the stack has the offset from the beginning
+ of the thread control block at which the variable is located. */
+ /* Nothing should follow this operator, so the top of stack would
+ be returned. */
+ if (i < size)
+ dwarf2_complex_location_expr_complaint ();
+ break;
+
default:
- complain (&dwarf2_unsupported_stack_op, dwarf_stack_op_name (op));
+ complaint (&symfile_complaints, "unsupported stack op: '%s'",
+ dwarf_stack_op_name (op));
return (stack[stacki]);
}
}
/* ARGSUSED */
static void
-dwarf2_free_tmp_obstack (ignore)
- PTR ignore;
+dwarf2_free_tmp_obstack (void *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;
memset (die, 0, sizeof (struct die_info));
return (die);
}
+
+\f
+/* Macro support. */
+
+
+/* Return the full name of file number I in *LH's file name table.
+ Use COMP_DIR as the name of the current directory of the
+ compilation. The result is allocated using xmalloc; the caller is
+ responsible for freeing it. */
+static char *
+file_full_name (int file, struct line_header *lh, const char *comp_dir)
+{
+ struct file_entry *fe = &lh->file_names[file - 1];
+
+ if (IS_ABSOLUTE_PATH (fe->name))
+ return xstrdup (fe->name);
+ else
+ {
+ const char *dir;
+ int dir_len;
+ char *full_name;
+
+ if (fe->dir_index)
+ dir = lh->include_dirs[fe->dir_index - 1];
+ else
+ dir = comp_dir;
+
+ if (dir)
+ {
+ dir_len = strlen (dir);
+ full_name = xmalloc (dir_len + 1 + strlen (fe->name) + 1);
+ strcpy (full_name, dir);
+ full_name[dir_len] = '/';
+ strcpy (full_name + dir_len + 1, fe->name);
+ return full_name;
+ }
+ else
+ return xstrdup (fe->name);
+ }
+}
+
+
+static struct macro_source_file *
+macro_start_file (int file, int line,
+ struct macro_source_file *current_file,
+ const char *comp_dir,
+ struct line_header *lh, struct objfile *objfile)
+{
+ /* The full name of this source file. */
+ char *full_name = file_full_name (file, lh, comp_dir);
+
+ /* We don't create a macro table for this compilation unit
+ at all until we actually get a filename. */
+ if (! pending_macros)
+ pending_macros = new_macro_table (&objfile->symbol_obstack,
+ objfile->macro_cache);
+
+ if (! current_file)
+ /* If we have no current file, then this must be the start_file
+ directive for the compilation unit's main source file. */
+ current_file = macro_set_main (pending_macros, full_name);
+ else
+ current_file = macro_include (current_file, line, full_name);
+
+ xfree (full_name);
+
+ return current_file;
+}
+
+
+/* Copy the LEN characters at BUF to a xmalloc'ed block of memory,
+ followed by a null byte. */
+static char *
+copy_string (const char *buf, int len)
+{
+ char *s = xmalloc (len + 1);
+ memcpy (s, buf, len);
+ s[len] = '\0';
+
+ return s;
+}
+
+
+static const char *
+consume_improper_spaces (const char *p, const char *body)
+{
+ if (*p == ' ')
+ {
+ complaint (&symfile_complaints,
+ "macro definition contains spaces in formal argument list:\n`%s'",
+ body);
+
+ while (*p == ' ')
+ p++;
+ }
+
+ return p;
+}
+
+
+static void
+parse_macro_definition (struct macro_source_file *file, int line,
+ const char *body)
+{
+ const char *p;
+
+ /* The body string takes one of two forms. For object-like macro
+ definitions, it should be:
+
+ <macro name> " " <definition>
+
+ For function-like macro definitions, it should be:
+
+ <macro name> "() " <definition>
+ or
+ <macro name> "(" <arg name> ( "," <arg name> ) * ") " <definition>
+
+ Spaces may appear only where explicitly indicated, and in the
+ <definition>.
+
+ The Dwarf 2 spec says that an object-like macro's name is always
+ followed by a space, but versions of GCC around March 2002 omit
+ the space when the macro's definition is the empty string.
+
+ The Dwarf 2 spec says that there should be no spaces between the
+ formal arguments in a function-like macro's formal argument list,
+ but versions of GCC around March 2002 include spaces after the
+ commas. */
+
+
+ /* Find the extent of the macro name. The macro name is terminated
+ by either a space or null character (for an object-like macro) or
+ an opening paren (for a function-like macro). */
+ for (p = body; *p; p++)
+ if (*p == ' ' || *p == '(')
+ break;
+
+ if (*p == ' ' || *p == '\0')
+ {
+ /* It's an object-like macro. */
+ int name_len = p - body;
+ char *name = copy_string (body, name_len);
+ const char *replacement;
+
+ if (*p == ' ')
+ replacement = body + name_len + 1;
+ else
+ {
+ dwarf2_macro_malformed_definition_complaint (body);
+ replacement = body + name_len;
+ }
+
+ macro_define_object (file, line, name, replacement);
+
+ xfree (name);
+ }
+ else if (*p == '(')
+ {
+ /* It's a function-like macro. */
+ char *name = copy_string (body, p - body);
+ int argc = 0;
+ int argv_size = 1;
+ char **argv = xmalloc (argv_size * sizeof (*argv));
+
+ p++;
+
+ p = consume_improper_spaces (p, body);
+
+ /* Parse the formal argument list. */
+ while (*p && *p != ')')
+ {
+ /* Find the extent of the current argument name. */
+ const char *arg_start = p;
+
+ while (*p && *p != ',' && *p != ')' && *p != ' ')
+ p++;
+
+ if (! *p || p == arg_start)
+ dwarf2_macro_malformed_definition_complaint (body);
+ else
+ {
+ /* Make sure argv has room for the new argument. */
+ if (argc >= argv_size)
+ {
+ argv_size *= 2;
+ argv = xrealloc (argv, argv_size * sizeof (*argv));
+ }
+
+ argv[argc++] = copy_string (arg_start, p - arg_start);
+ }
+
+ p = consume_improper_spaces (p, body);
+
+ /* Consume the comma, if present. */
+ if (*p == ',')
+ {
+ p++;
+
+ p = consume_improper_spaces (p, body);
+ }
+ }
+
+ if (*p == ')')
+ {
+ p++;
+
+ if (*p == ' ')
+ /* Perfectly formed definition, no complaints. */
+ macro_define_function (file, line, name,
+ argc, (const char **) argv,
+ p + 1);
+ else if (*p == '\0')
+ {
+ /* Complain, but do define it. */
+ dwarf2_macro_malformed_definition_complaint (body);
+ macro_define_function (file, line, name,
+ argc, (const char **) argv,
+ p);
+ }
+ else
+ /* Just complain. */
+ dwarf2_macro_malformed_definition_complaint (body);
+ }
+ else
+ /* Just complain. */
+ dwarf2_macro_malformed_definition_complaint (body);
+
+ xfree (name);
+ {
+ int i;
+
+ for (i = 0; i < argc; i++)
+ xfree (argv[i]);
+ }
+ xfree (argv);
+ }
+ else
+ dwarf2_macro_malformed_definition_complaint (body);
+}
+
+
+static void
+dwarf_decode_macros (struct line_header *lh, unsigned int offset,
+ char *comp_dir, bfd *abfd,
+ const struct comp_unit_head *cu_header,
+ struct objfile *objfile)
+{
+ char *mac_ptr, *mac_end;
+ struct macro_source_file *current_file = 0;
+
+ if (dwarf_macinfo_buffer == NULL)
+ {
+ complaint (&symfile_complaints, "missing .debug_macinfo section");
+ return;
+ }
+
+ mac_ptr = dwarf_macinfo_buffer + offset;
+ mac_end = dwarf_macinfo_buffer + dwarf_macinfo_size;
+
+ for (;;)
+ {
+ enum dwarf_macinfo_record_type macinfo_type;
+
+ /* Do we at least have room for a macinfo type byte? */
+ if (mac_ptr >= mac_end)
+ {
+ dwarf2_macros_too_long_complaint ();
+ return;
+ }
+
+ macinfo_type = read_1_byte (abfd, mac_ptr);
+ mac_ptr++;
+
+ switch (macinfo_type)
+ {
+ /* A zero macinfo type indicates the end of the macro
+ information. */
+ case 0:
+ return;
+
+ case DW_MACINFO_define:
+ case DW_MACINFO_undef:
+ {
+ int bytes_read;
+ int line;
+ char *body;
+
+ line = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
+ mac_ptr += bytes_read;
+ body = read_string (abfd, mac_ptr, &bytes_read);
+ mac_ptr += bytes_read;
+
+ if (! current_file)
+ complaint (&symfile_complaints,
+ "debug info gives macro %s outside of any file: %s",
+ macinfo_type ==
+ DW_MACINFO_define ? "definition" : macinfo_type ==
+ DW_MACINFO_undef ? "undefinition" :
+ "something-or-other", body);
+ else
+ {
+ if (macinfo_type == DW_MACINFO_define)
+ parse_macro_definition (current_file, line, body);
+ else if (macinfo_type == DW_MACINFO_undef)
+ macro_undef (current_file, line, body);
+ }
+ }
+ break;
+
+ case DW_MACINFO_start_file:
+ {
+ int bytes_read;
+ int line, file;
+
+ line = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
+ mac_ptr += bytes_read;
+ file = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
+ mac_ptr += bytes_read;
+
+ current_file = macro_start_file (file, line,
+ current_file, comp_dir,
+ lh, objfile);
+ }
+ break;
+
+ case DW_MACINFO_end_file:
+ if (! current_file)
+ complaint (&symfile_complaints,
+ "macro debug info has an unmatched `close_file' directive");
+ else
+ {
+ current_file = current_file->included_by;
+ if (! current_file)
+ {
+ enum dwarf_macinfo_record_type next_type;
+
+ /* GCC circa March 2002 doesn't produce the zero
+ type byte marking the end of the compilation
+ unit. Complain if it's not there, but exit no
+ matter what. */
+
+ /* Do we at least have room for a macinfo type byte? */
+ if (mac_ptr >= mac_end)
+ {
+ dwarf2_macros_too_long_complaint ();
+ return;
+ }
+
+ /* We don't increment mac_ptr here, so this is just
+ a look-ahead. */
+ next_type = read_1_byte (abfd, mac_ptr);
+ if (next_type != 0)
+ complaint (&symfile_complaints,
+ "no terminating 0-type entry for macros in `.debug_macinfo' section");
+
+ return;
+ }
+ }
+ break;
+
+ case DW_MACINFO_vendor_ext:
+ {
+ int bytes_read;
+ int constant;
+ char *string;
+
+ constant = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
+ mac_ptr += bytes_read;
+ string = read_string (abfd, mac_ptr, &bytes_read);
+ mac_ptr += bytes_read;
+
+ /* We don't recognize any vendor extensions. */
+ }
+ break;
+ }
+ }
+}
+
+/* Check if the attribute's form is a DW_FORM_block*
+ if so return true else false. */
+static int
+attr_form_is_block (struct attribute *attr)
+{
+ return (attr == NULL ? 0 :
+ attr->form == DW_FORM_block1
+ || attr->form == DW_FORM_block2
+ || attr->form == DW_FORM_block4
+ || attr->form == DW_FORM_block);
+}