X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fdwarf2read.c;h=945a387463d6c7375fe4c9b55ad0d2bdec5f0a39;hb=b9ff3018cd573e009421f7aa357ebba6345adf42;hp=b331bcb0a903dd350eca3d07a6462023115a397b;hpb=ce5d95e1bc788f341d68022da537c737496148f5;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index b331bcb0a9..945a387463 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -1,5 +1,6 @@ /* 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 @@ -35,14 +36,25 @@ #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 "dwarf2expr.h" +#include "dwarf2loc.h" +#include "cp-support.h" + #include #include "gdb_string.h" +#include "gdb_assert.h" #include +#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. */ @@ -57,6 +69,7 @@ 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 @@ -123,6 +136,9 @@ static file_ptr dwarf_aranges_offset; 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; @@ -132,6 +148,21 @@ static unsigned int dwarf_aranges_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 */ @@ -143,31 +174,105 @@ static unsigned int dwarf_str_size; #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]; + + /* Base address of this compilation unit. */ + + CORE_ADDR base_address; + + /* Non-zero if base_address has been set. */ + + int base_known; }; -/* 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. */ @@ -181,6 +286,7 @@ struct partial_die_info unsigned int offset; unsigned int abbrev; char *name; + int has_pc_info; CORE_ADDR lowpc; CORE_ADDR highpc; struct dwarf_block *locdesc; @@ -235,6 +341,16 @@ struct attribute 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) @@ -250,17 +366,10 @@ struct dwarf_block 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 @@ -268,11 +377,6 @@ static struct abbrev_info *dwarf2_abbrevs[ABBREV_HASH_SIZE]; static struct die_info *die_ref_table[REF_HASH_SIZE]; -#ifndef TYPE_HASH_SIZE -#define TYPE_HASH_SIZE 4096 -#endif -static struct type *dwarf2_cached_types[TYPE_HASH_SIZE]; - /* Obstack for allocating temporary storage used during symbol reading. */ static struct obstack dwarf2_tmp_obstack; @@ -293,6 +397,10 @@ static const struct language_defn *cu_language_defn; 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; +static char *dwarf_loc_buffer; /* A zeroed version of a partial die for initialization purposes. */ static struct partial_die_info zeroed_partial_die; @@ -374,6 +482,42 @@ struct dwarf2_pinfo /* 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; + + /* Pointer to start of dwarf locations buffer for the objfile. */ + + char *dwarf_loc_buffer; + + /* Size of dwarf locations buffer for the objfile. */ + + unsigned int dwarf_loc_size; }; #define PST_PRIVATE(p) ((struct dwarf2_pinfo *)(p)->read_symtab_private) @@ -382,6 +526,15 @@ struct dwarf2_pinfo #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) +#define DWARF_LOC_BUFFER(p) (PST_PRIVATE(p)->dwarf_loc_buffer) +#define DWARF_LOC_SIZE(p) (PST_PRIVATE(p)->dwarf_loc_size) /* Maintain an array of referenced fundamental types for the current compilation unit being read. For DWARF version 1, we have to construct @@ -447,116 +600,69 @@ struct field_info 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 = +static void +dwarf2_non_const_array_bound_ignored_complaint (const char *arg1) { - "cannot extract member name from '%s'", 0, 0 -}; -static struct complaint dwarf2_missing_member_fn_type_complaint = + complaint (&symfile_complaints, "non-constant array bounds form '%s' ignored", + arg1); +} + +static void +dwarf2_statement_list_fits_in_line_number_section_complaint (void) { - "member function type missing for '%s'", 0, 0 -}; -static struct complaint dwarf2_vtbl_not_found_complaint = + complaint (&symfile_complaints, + "statement list doesn't fit in .debug_line section"); +} + +static void +dwarf2_complex_location_expr_complaint (void) { - "virtual function table pointer not found when defining class '%s'", 0, 0 -}; -static struct complaint dwarf2_absolute_sibling_complaint = + complaint (&symfile_complaints, "location expression too complex"); +} + +static void +dwarf2_unsupported_at_frame_base_complaint (const char *arg1) { - "ignoring absolute DW_AT_sibling", 0, 0 -}; -static struct complaint dwarf2_const_value_length_mismatch = + 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) { - "const value length mismatch for '%s', got %d, expected %d", 0, 0 -}; -static struct complaint dwarf2_unsupported_const_value_attr = + complaint (&symfile_complaints, + "const value length mismatch for '%s', got %d, expected %d", arg1, + arg2, arg3); +} + +static void +dwarf2_macros_too_long_complaint (void) { - "unsupported const value attribute form: '%s'", 0, 0 -}; + complaint (&symfile_complaints, + "macro info runs off end of `.debug_macinfo' section"); +} -/* 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_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 (bfd *, asection *, PTR); +static void dwarf2_locate_sections (bfd *, asection *, void *); #if 0 static void dwarf2_build_psymtabs_easy (struct objfile *, int); @@ -565,29 +671,58 @@ static void dwarf2_build_psymtabs_easy (struct objfile *, int); static void dwarf2_build_psymtabs_hard (struct objfile *, int); static char *scan_partial_symbols (char *, struct objfile *, - CORE_ADDR *, CORE_ADDR *); - -static void add_partial_symbol (struct partial_die_info *, struct objfile *); + CORE_ADDR *, CORE_ADDR *, + const struct comp_unit_head *, + const char *namespace); + +static void add_partial_symbol (struct partial_die_info *, struct objfile *, + const struct comp_unit_head *, + const char *namespace); + +static char *add_partial_namespace (struct partial_die_info *pdi, + char *info_ptr, + struct objfile *objfile, + CORE_ADDR *lowpc, CORE_ADDR *highpc, + const struct comp_unit_head *cu_header, + const char *namespace); + +static char *add_partial_enumeration (struct partial_die_info *enum_pdi, + char *info_ptr, + struct objfile *objfile, + const struct comp_unit_head *cu_header, + const char *namespace); + +static char *locate_pdi_sibling (struct partial_die_info *orig_pdi, + char *info_ptr, + bfd *abfd, + const struct comp_unit_head *cu_header); static void dwarf2_psymtab_to_symtab (struct partial_symtab *); static void psymtab_to_symtab_1 (struct partial_symtab *); -static char *dwarf2_read_section (struct objfile *, file_ptr, unsigned int); +char *dwarf2_read_section (struct objfile *, file_ptr, unsigned int, + asection *); -static void dwarf2_read_abbrevs (bfd *, unsigned int); +static void dwarf2_read_abbrevs (bfd *abfd, struct comp_unit_head *cu_header); -static void dwarf2_empty_abbrev_table (PTR); +static void dwarf2_empty_abbrev_table (void *); -static struct abbrev_info *dwarf2_lookup_abbrev (unsigned int); +static struct abbrev_info *dwarf2_lookup_abbrev (unsigned int, + const struct comp_unit_head *cu_header); static char *read_partial_die (struct partial_die_info *, - bfd *, char *, int *); + bfd *, char *, + const struct comp_unit_head *); -static char *read_full_die (struct die_info **, bfd *, char *); +static char *read_full_die (struct die_info **, bfd *, char *, + const struct comp_unit_head *); static char *read_attribute (struct attribute *, struct attr_abbrev *, - bfd *, char *); + bfd *, char *, const struct comp_unit_head *); + +static char *read_attribute_value (struct attribute *, unsigned, + bfd *, char *, const struct comp_unit_head *); static unsigned int read_1_byte (bfd *, char *); @@ -599,12 +734,22 @@ static unsigned int read_4_bytes (bfd *, char *); static unsigned long read_8_bytes (bfd *, char *); -static CORE_ADDR read_address (bfd *, char *); +static CORE_ADDR read_address (bfd *, char *ptr, const struct comp_unit_head *, + int *bytes_read); + +static LONGEST read_initial_length (bfd *, char *, + struct comp_unit_head *, int *bytes_read); + +static LONGEST read_offset (bfd *, char *, const struct comp_unit_head *, + int *bytes_read); static char *read_n_bytes (bfd *, char *, unsigned int); static char *read_string (bfd *, char *, unsigned int *); +static char *read_indirect_string (bfd *, char *, const struct comp_unit_head *, + unsigned int *); + static unsigned long read_unsigned_leb128 (bfd *, char *, unsigned int *); static long read_signed_leb128 (bfd *, char *, unsigned int *); @@ -615,94 +760,132 @@ static struct attribute *dwarf_attr (struct die_info *, unsigned int); static int die_is_declaration (struct die_info *); -static void dwarf_decode_lines (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 (char *, char *); static struct symbol *new_symbol (struct die_info *, struct type *, - struct objfile *); + struct objfile *, const struct comp_unit_head *); static void dwarf2_const_value (struct attribute *, struct symbol *, - struct objfile *); + struct objfile *, const struct comp_unit_head *); static void dwarf2_const_value_data (struct attribute *attr, struct symbol *sym, int bits); -static struct type *die_type (struct die_info *, struct objfile *); +static struct type *die_type (struct die_info *, struct objfile *, + const struct comp_unit_head *); -static struct type *die_containing_type (struct die_info *, struct objfile *); +static struct type *die_containing_type (struct die_info *, struct objfile *, + const struct comp_unit_head *); #if 0 static struct type *type_at_offset (unsigned int, struct objfile *); #endif -static struct type *tag_type_to_type (struct die_info *, struct objfile *); +static struct type *tag_type_to_type (struct die_info *, struct objfile *, + const struct comp_unit_head *); -static void read_type_die (struct die_info *, struct objfile *); +static void read_type_die (struct die_info *, struct objfile *, + const struct comp_unit_head *); -static void read_typedef (struct die_info *, struct objfile *); +static void read_typedef (struct die_info *, struct objfile *, + const struct comp_unit_head *); static void read_base_type (struct die_info *, struct objfile *); -static void read_file_scope (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 (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 (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 (struct die_info *, - CORE_ADDR *, CORE_ADDR *, struct objfile *); + CORE_ADDR *, CORE_ADDR *, struct objfile *, + const struct comp_unit_head *); static void dwarf2_add_field (struct field_info *, struct die_info *, - struct objfile *); + struct objfile *, const struct comp_unit_head *); static void dwarf2_attach_fields_to_type (struct field_info *, struct type *, struct objfile *); static void dwarf2_add_member_fn (struct field_info *, struct die_info *, struct type *, - struct objfile *objfile); + struct objfile *objfile, + const struct comp_unit_head *); static void dwarf2_attach_fn_fields_to_type (struct field_info *, struct type *, struct objfile *); -static void read_structure_scope (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 (struct die_info *, struct objfile *); +static void read_common_block (struct die_info *, struct objfile *, + const struct comp_unit_head *); -static void read_enumeration (struct die_info *, struct objfile *); +static void read_namespace (struct die_info *die, struct objfile *objfile, + const struct comp_unit_head *cu_header); + +static void read_enumeration (struct die_info *, struct objfile *, + const struct comp_unit_head *); static struct type *dwarf_base_type (int, int, struct objfile *); -static CORE_ADDR decode_locdesc (struct dwarf_block *, struct objfile *); +static CORE_ADDR decode_locdesc (struct dwarf_block *, struct objfile *, + const struct comp_unit_head *); -static void read_array_type (struct die_info *, struct objfile *); +static void read_array_type (struct die_info *, struct objfile *, + const struct comp_unit_head *); -static void read_tag_pointer_type (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_ptr_to_member_type (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_reference_type (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_const_type (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_volatile_type (struct die_info *, struct objfile *); +static void read_tag_volatile_type (struct die_info *, struct objfile *, + const struct comp_unit_head *); static void read_tag_string_type (struct die_info *, struct objfile *); -static void read_subroutine_type (struct die_info *, struct objfile *); +static void read_subroutine_type (struct die_info *, struct objfile *, + const struct comp_unit_head *); -struct die_info *read_comp_unit (char *, bfd *); +static struct die_info *read_comp_unit (char *, bfd *, + const struct comp_unit_head *); static void free_die_list (struct die_info *); static struct cleanup *make_cleanup_free_die_list (struct die_info *); -static void process_die (struct die_info *, struct objfile *); +static void process_die (struct die_info *, struct objfile *, + const struct comp_unit_head *); static char *dwarf2_linkage_name (struct die_info *); +static char *dwarf2_name (struct die_info *die); + +static struct die_info *dwarf2_extension (struct die_info *die); + static char *dwarf_tag_name (unsigned int); static char *dwarf_attr_name (unsigned int); @@ -721,25 +904,25 @@ static char *dwarf_cfi_name (unsigned int); struct die_info *copy_die (struct die_info *); #endif -struct die_info *sibling_die (struct die_info *); +static struct die_info *sibling_die (struct die_info *); -void dump_die (struct die_info *); +static void dump_die (struct die_info *); -void dump_die_list (struct die_info *); +static void dump_die_list (struct die_info *); -void store_in_ref_table (unsigned int, struct die_info *); +static void store_in_ref_table (unsigned int, struct die_info *); -static void dwarf2_empty_die_ref_table (void); +static void dwarf2_empty_hash_tables (void); static unsigned int dwarf2_get_ref_die_offset (struct attribute *); -struct die_info *follow_die_ref (unsigned int); +static struct die_info *follow_die_ref (unsigned int); static struct type *dwarf2_fundamental_type (struct objfile *, int); /* memory allocation interface */ -static void dwarf2_free_tmp_obstack (PTR); +static void dwarf2_free_tmp_obstack (void *); static struct dwarf_block *dwarf_alloc_block (void); @@ -747,14 +930,37 @@ static struct abbrev_info *dwarf_alloc_abbrev (void); static struct die_info *dwarf_alloc_die (void); +static void initialize_cu_func_list (void); + +static void add_to_cu_func_list (const char *, CORE_ADDR, CORE_ADDR); + +static void dwarf_decode_macros (struct line_header *, unsigned int, + char *, bfd *, const struct comp_unit_head *, + struct objfile *); + +static int attr_form_is_block (struct attribute *); + +static void +dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym, + const struct comp_unit_head *, + struct objfile *objfile); + /* 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; + dwarf_loc_offset = 0; + bfd_map_over_sections (abfd, dwarf2_locate_sections, NULL); if (dwarf_info_offset && dwarf_abbrev_offset) { @@ -771,75 +977,140 @@ dwarf2_has_info (abfd) 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)) + { + flagword aflag = bfd_get_section_flags (ignore_abfd, sectp); + if (aflag & SEC_HAS_CONTENTS) + { + 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 (dwarf_loc_offset) + dwarf_loc_buffer = dwarf2_read_section (objfile, + dwarf_loc_offset, + dwarf_loc_size, + dwarf_loc_section); + else + dwarf_loc_buffer = NULL; + + if (mainline + || (objfile->global_psymbols.size == 0 + && objfile->static_psymbols.size == 0)) { init_psymbol_list (objfile, 1024); } @@ -866,9 +1137,7 @@ dwarf2_build_psymtabs (objfile, mainline) .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; @@ -877,12 +1146,17 @@ dwarf2_build_psymtabs_easy (objfile, mainline) 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); @@ -893,78 +1167,142 @@ dwarf2_build_psymtabs_easy (objfile, mainline) 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; 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; } + /* 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); @@ -984,7 +1322,16 @@ dwarf2_build_psymtabs_hard (objfile, mainline) 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; + DWARF_LOC_BUFFER (pst) = dwarf_loc_buffer; + DWARF_LOC_SIZE (pst) = dwarf_loc_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; @@ -994,11 +1341,20 @@ dwarf2_build_psymtabs_hard (objfile, mainline) 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); + lowpc = ((CORE_ADDR) -1); + highpc = ((CORE_ADDR) 0); + + info_ptr = scan_partial_symbols (info_ptr, objfile, &lowpc, &highpc, + &cu_header, NULL); + /* If we didn't find a lowpc, set it to highpc to avoid + complaints from `maint check'. */ + if (lowpc == ((CORE_ADDR) -1)) + lowpc = highpc; + /* If the compilation unit didn't have an explicit address range, then use the information extracted from its child dies. */ - if (!comp_unit_has_pc_info) + if (! comp_unit_die.has_pc_info) { comp_unit_die.lowpc = lowpc; comp_unit_die.highpc = highpc; @@ -1018,45 +1374,51 @@ dwarf2_build_psymtabs_hard (objfile, mainline) 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. */ +/* Read in all interesting dies to the end of the compilation unit or + to the end of the current namespace. NAMESPACE is NULL if we + haven't yet encountered any DW_TAG_namespace entries; otherwise, + it's the name of the current namespace. In particular, it's the + empty string if we're currently in the global namespace but have + previously encountered a DW_TAG_namespace. */ 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, + const char *namespace) { bfd *abfd = objfile->obfd; struct partial_die_info pdi; - /* This function is called after we've read in the comp_unit_die in - order to read its children. We start the nesting level at 1 since - we have pushed 1 level down in order to read the comp unit's children. - The comp unit itself is at level 0, so we stop reading when we pop - back to that level. */ + /* Now, march along the PDI's, descending into ones which have + interesting children but skipping the children of the other ones, + until we reach the end of the compilation unit. */ - int nesting_level = 1; - int has_pc_info; + while (1) + { + /* This flag tells whether or not info_ptr has gotten updated + inside the loop. */ + int info_ptr_updated = 0; - *lowpc = ((CORE_ADDR) -1); - *highpc = ((CORE_ADDR) 0); + info_ptr = read_partial_die (&pdi, abfd, info_ptr, cu_header); - while (nesting_level) - { - info_ptr = read_partial_die (&pdi, abfd, info_ptr, &has_pc_info); + /* Anonymous namespaces have no name but have interesting + children, so we need to look at them. Ditto for anonymous + enums. */ - if (pdi.name) + if (pdi.name != NULL || pdi.tag == DW_TAG_namespace + || pdi.tag == DW_TAG_enumeration_type) { switch (pdi.tag) { case DW_TAG_subprogram: - if (has_pc_info) + if (pdi.has_pc_info) { if (pdi.lowpc < *lowpc) { @@ -1066,75 +1428,77 @@ scan_partial_symbols (info_ptr, objfile, lowpc, highpc) { *highpc = pdi.highpc; } - if ((pdi.is_external || nesting_level == 1) - && !pdi.is_declaration) + if (!pdi.is_declaration) { - add_partial_symbol (&pdi, objfile); + add_partial_symbol (&pdi, objfile, cu_header, namespace); } } break; case DW_TAG_variable: case DW_TAG_typedef: + case DW_TAG_union_type: case DW_TAG_class_type: case DW_TAG_structure_type: - case DW_TAG_union_type: - case DW_TAG_enumeration_type: - if ((pdi.is_external || nesting_level == 1) - && !pdi.is_declaration) + if (!pdi.is_declaration) { - add_partial_symbol (&pdi, objfile); + add_partial_symbol (&pdi, objfile, cu_header, namespace); } break; - case DW_TAG_enumerator: - /* File scope enumerators are added to the partial symbol - table. */ - if (nesting_level == 2) - add_partial_symbol (&pdi, objfile); + case DW_TAG_enumeration_type: + if (!pdi.is_declaration) + { + info_ptr = add_partial_enumeration (&pdi, info_ptr, + objfile, cu_header, + namespace); + info_ptr_updated = 1; + } 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); + add_partial_symbol (&pdi, objfile, cu_header, namespace); + break; + case DW_TAG_namespace: + /* We've hit a DW_TAG_namespace entry, so we know this + file has been compiled using a compiler that + generates them; update NAMESPACE to reflect that. */ + if (namespace == NULL) + namespace = ""; + info_ptr = add_partial_namespace (&pdi, info_ptr, objfile, + lowpc, highpc, cu_header, + namespace); + info_ptr_updated = 1; break; 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) - { - info_ptr = pdi.sibling; - } - else if (pdi.has_children) - { - /* Die has children, but the optional DW_AT_sibling attribute - is missing. */ - nesting_level++; - } - if (pdi.tag == 0) - { - nesting_level--; - } + break; + + /* If the die has a sibling, skip to the sibling, unless another + function has already updated info_ptr for us. */ + + /* NOTE: carlton/2003-06-16: This is a bit hackish, but whether + or not we want to update this depends on enough stuff (not + only pdi.tag but also whether or not pdi.name is NULL) that + this seems like the easiest way to handle the issue. */ + + if (!info_ptr_updated) + info_ptr = locate_pdi_sibling (&pdi, info_ptr, abfd, cu_header); } - /* If we didn't find a lowpc, set it to highpc to avoid complaints - from `maint check'. */ - if (*lowpc == ((CORE_ADDR) -1)) - *lowpc = *highpc; return info_ptr; } static void -add_partial_symbol (pdi, objfile) - struct partial_die_info *pdi; - struct objfile *objfile; +add_partial_symbol (struct partial_die_info *pdi, struct objfile *objfile, + const struct comp_unit_head *cu_header, + const char *namespace) { CORE_ADDR addr = 0; + const struct partial_symbol *psym = NULL; switch (pdi->tag) { @@ -1143,19 +1507,21 @@ add_partial_symbol (pdi, objfile) { /*prim_record_minimal_symbol (pdi->name, pdi->lowpc + baseaddr, mst_text, objfile); */ - add_psymbol_to_list (pdi->name, strlen (pdi->name), - VAR_NAMESPACE, LOC_BLOCK, - &objfile->global_psymbols, - 0, pdi->lowpc + baseaddr, cu_language, objfile); + psym = add_psymbol_to_list (pdi->name, strlen (pdi->name), + VAR_DOMAIN, LOC_BLOCK, + &objfile->global_psymbols, + 0, pdi->lowpc + baseaddr, + cu_language, objfile); } else { /*prim_record_minimal_symbol (pdi->name, pdi->lowpc + baseaddr, mst_file_text, objfile); */ - add_psymbol_to_list (pdi->name, strlen (pdi->name), - VAR_NAMESPACE, LOC_BLOCK, - &objfile->static_psymbols, - 0, pdi->lowpc + baseaddr, cu_language, objfile); + psym = add_psymbol_to_list (pdi->name, strlen (pdi->name), + VAR_DOMAIN, LOC_BLOCK, + &objfile->static_psymbols, + 0, pdi->lowpc + baseaddr, + cu_language, objfile); } break; case DW_TAG_variable: @@ -1175,31 +1541,33 @@ add_partial_symbol (pdi, objfile) 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, - &objfile->global_psymbols, - 0, addr + baseaddr, cu_language, objfile); + psym = add_psymbol_to_list (pdi->name, strlen (pdi->name), + VAR_DOMAIN, LOC_STATIC, + &objfile->global_psymbols, + 0, addr + baseaddr, + cu_language, objfile); } else { /* 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), - VAR_NAMESPACE, LOC_STATIC, - &objfile->static_psymbols, - 0, addr + baseaddr, cu_language, objfile); + psym = add_psymbol_to_list (pdi->name, strlen (pdi->name), + VAR_DOMAIN, LOC_STATIC, + &objfile->static_psymbols, + 0, addr + baseaddr, + cu_language, objfile); } break; case DW_TAG_typedef: case DW_TAG_base_type: add_psymbol_to_list (pdi->name, strlen (pdi->name), - VAR_NAMESPACE, LOC_TYPEDEF, + VAR_DOMAIN, LOC_TYPEDEF, &objfile->static_psymbols, 0, (CORE_ADDR) 0, cu_language, objfile); break; @@ -1212,7 +1580,7 @@ add_partial_symbol (pdi, objfile) if (pdi->has_children == 0) return; add_psymbol_to_list (pdi->name, strlen (pdi->name), - STRUCT_NAMESPACE, LOC_TYPEDEF, + STRUCT_DOMAIN, LOC_TYPEDEF, &objfile->static_psymbols, 0, (CORE_ADDR) 0, cu_language, objfile); @@ -1220,27 +1588,144 @@ add_partial_symbol (pdi, objfile) { /* For C++, these implicitly act as typedefs as well. */ add_psymbol_to_list (pdi->name, strlen (pdi->name), - VAR_NAMESPACE, LOC_TYPEDEF, + VAR_DOMAIN, LOC_TYPEDEF, &objfile->static_psymbols, 0, (CORE_ADDR) 0, cu_language, objfile); } break; case DW_TAG_enumerator: add_psymbol_to_list (pdi->name, strlen (pdi->name), - VAR_NAMESPACE, LOC_CONST, + VAR_DOMAIN, LOC_CONST, &objfile->static_psymbols, 0, (CORE_ADDR) 0, cu_language, objfile); break; default: break; } + + /* Check to see if we should scan the name for possible namespace + info. Only do this if this is C++, if we don't have namespace + debugging info in the file, if the psym is of an appropriate type + (otherwise we'll have psym == NULL), and if we actually had a + mangled name to begin with. */ + + if (cu_language == language_cplus + && namespace == NULL + && psym != NULL + && SYMBOL_CPLUS_DEMANGLED_NAME (psym) != NULL) + cp_check_possible_namespace_symbols (SYMBOL_CPLUS_DEMANGLED_NAME (psym), + objfile); +} + +/* Read a partial die corresponding to a namespace; also, add a symbol + corresponding to that namespace to the symbol table. NAMESPACE is + the name of the enclosing namespace. */ + +static char * +add_partial_namespace (struct partial_die_info *pdi, char *info_ptr, + struct objfile *objfile, + CORE_ADDR *lowpc, CORE_ADDR *highpc, + const struct comp_unit_head *cu_header, + const char *namespace) +{ + /* Calculate the full name of the namespace that we just entered. */ + + const char *new_name = pdi->name; + char *full_name; + + if (new_name == NULL) + new_name = "(anonymous namespace)"; + full_name = alloca (strlen (namespace) + 2 + strlen (new_name) + 1); + strcpy (full_name, namespace); + if (*namespace != '\0') + strcat (full_name, "::"); + strcat (full_name, new_name); + + /* FIXME: carlton/2003-06-27: Once we build qualified names for more + symbols than just namespaces, we should replace this by a call to + add_partial_symbol. */ + + add_psymbol_to_list (full_name, strlen (full_name), + VAR_DOMAIN, LOC_TYPEDEF, + &objfile->global_psymbols, + 0, 0, cu_language, objfile); + + /* Now scan partial symbols in that namespace. */ + + if (pdi->has_children) + info_ptr = scan_partial_symbols (info_ptr, objfile, + lowpc, highpc, + cu_header, full_name); + + return info_ptr; +} + +/* Read a partial die corresponding to an enumeration type. */ + +static char * +add_partial_enumeration (struct partial_die_info *enum_pdi, char *info_ptr, + struct objfile *objfile, + const struct comp_unit_head *cu_header, + const char *namespace) +{ + bfd *abfd = objfile->obfd; + struct partial_die_info pdi; + + if (enum_pdi->name != NULL) + add_partial_symbol (enum_pdi, objfile, cu_header, namespace); + + while (1) + { + info_ptr = read_partial_die (&pdi, abfd, info_ptr, cu_header); + if (pdi.tag == 0) + break; + if (pdi.tag != DW_TAG_enumerator || pdi.name == NULL) + complaint (&symfile_complaints, "malformed enumerator DIE ignored"); + else + add_partial_symbol (&pdi, objfile, cu_header, namespace); + } + + return info_ptr; +} + +/* Locate ORIG_PDI's sibling; INFO_PTR should point to the next DIE + after ORIG_PDI. */ + +static char * +locate_pdi_sibling (struct partial_die_info *orig_pdi, char *info_ptr, + bfd *abfd, const struct comp_unit_head *cu_header) +{ + /* Do we know the sibling already? */ + + if (orig_pdi->sibling) + return orig_pdi->sibling; + + /* Are there any children to deal with? */ + + if (!orig_pdi->has_children) + return info_ptr; + + /* Okay, we don't know the sibling, but we have children that we + want to skip. So read children until we run into one without a + tag; return whatever follows it. */ + + while (1) + { + struct partial_die_info pdi; + + info_ptr = read_partial_die (&pdi, abfd, info_ptr, cu_header); + + if (pdi.tag == 0) + return info_ptr; + else + info_ptr = locate_pdi_sibling (&pdi, info_ptr, abfd, cu_header); + } } /* 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) @@ -1267,8 +1752,7 @@ dwarf2_psymtab_to_symtab (pst) } 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; @@ -1280,6 +1764,7 @@ psymtab_to_symtab_1 (pst) char *info_ptr; struct symtab *symtab; struct cleanup *back_to; + struct attribute *attr; /* Set local variables from the partial symbol table info. */ offset = DWARF_INFO_OFFSET (pst); @@ -1287,7 +1772,16 @@ psymtab_to_symtab_1 (pst) dwarf_abbrev_buffer = DWARF_ABBREV_BUFFER (pst); dwarf_abbrev_size = DWARF_ABBREV_SIZE (pst); dwarf_line_buffer = DWARF_LINE_BUFFER (pst); - baseaddr = ANOFFSET (pst->section_offsets, 0); + 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); + dwarf_loc_buffer = DWARF_LOC_BUFFER (pst); + dwarf_loc_size = DWARF_LOC_SIZE (pst); + baseaddr = ANOFFSET (pst->section_offsets, SECT_OFF_TEXT (objfile)); cu_header_offset = offset; info_ptr = dwarf_info_buffer + offset; @@ -1298,27 +1792,45 @@ psymtab_to_symtab_1 (pst) 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_free_die_list (dies); + /* Find the base address of the compilation unit for range lists and + location lists. It will normally be specified by DW_AT_low_pc. + In DWARF-3 draft 4, the base address could be overridden by + DW_AT_entry_pc. It's been removed, but GCC still uses this for + compilation units with discontinuous ranges. */ + + cu_header.base_known = 0; + cu_header.base_address = 0; + + attr = dwarf_attr (dies, DW_AT_entry_pc); + if (attr) + { + cu_header.base_address = DW_ADDR (attr); + cu_header.base_known = 1; + } + else + { + attr = dwarf_attr (dies, DW_AT_low_pc); + if (attr) + { + cu_header.base_address = DW_ADDR (attr); + cu_header.base_known = 1; + } + } + /* Do line number decoding in read_file_scope () */ - process_die (dies, objfile); + 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, @@ -1333,7 +1845,8 @@ psymtab_to_symtab_1 (pst) { 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); } @@ -1342,7 +1855,7 @@ psymtab_to_symtab_1 (pst) } } } - 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, @@ -1354,7 +1867,6 @@ psymtab_to_symtab_1 (pst) } pst->symtab = symtab; pst->readin = 1; - sort_symtab_syms (pst->symtab); do_cleanups (back_to); } @@ -1362,20 +1874,19 @@ psymtab_to_symtab_1 (pst) /* 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. @@ -1383,30 +1894,32 @@ process_die (die, objfile) of a function and make GDB `next' properly over inlined functions. */ break; case DW_TAG_lexical_block: - read_lexical_block_scope (die, objfile); + case DW_TAG_try_block: + case DW_TAG_catch_block: + 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); @@ -1416,26 +1929,54 @@ process_die (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: + if (!processing_has_namespace_info) + { + processing_has_namespace_info = 1; + processing_current_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. */ + if (!processing_has_namespace_info) + { + processing_has_namespace_info = 1; + processing_current_namespace = ""; + } + 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; @@ -1443,8 +1984,9 @@ read_file_scope (die, objfile) 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) { @@ -1455,7 +1997,8 @@ read_file_scope (die, objfile) { 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); @@ -1496,8 +2039,8 @@ read_file_scope (die, objfile) if (objfile->ei.entry_point >= lowpc && objfile->ei.entry_point < highpc) { - objfile->ei.entry_file_lowpc = lowpc; - objfile->ei.entry_file_highpc = highpc; + objfile->ei.deprecated_entry_file_lowpc = lowpc; + objfile->ei.deprecated_entry_file_highpc = highpc; } attr = dwarf_attr (die, DW_AT_language); @@ -1523,13 +2066,7 @@ read_file_scope (die, objfile) 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) @@ -1537,18 +2074,66 @@ read_file_scope (die, objfile) 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; + struct context_stack *new; CORE_ADDR lowpc; CORE_ADDR highpc; struct die_info *child_die; @@ -1559,12 +2144,15 @@ read_func_scope (die, objfile) /* 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) { @@ -1579,9 +2167,26 @@ read_func_scope (die, objfile) 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) @@ -1590,11 +2195,18 @@ read_func_scope (die, objfile) 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); + + /* If there was a location expression for DW_AT_frame_base above, + record it. We still need to decode it above because not all + symbols use location expressions exclusively. */ + if (attr) + dwarf2_symbol_mark_computed (attr, new->name, cu_header, objfile); + list_in_scope = &local_symbols; if (die->has_children) @@ -1602,7 +2214,7 @@ read_func_scope (die, objfile) 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); } } @@ -1611,23 +2223,37 @@ read_func_scope (die, objfile) /* 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; + 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; @@ -1638,7 +2264,7 @@ read_lexical_block_scope (die, objfile) 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); } } @@ -1652,30 +2278,148 @@ read_lexical_block_scope (die, objfile) 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_ranges section. */ + unsigned int offset = DW_UNSND (attr); + /* Base address selection entry. */ + CORE_ADDR base; + int found_base; + int dummy; + unsigned int i; + char *buffer; + CORE_ADDR marker; + int low_set; + + found_base = cu_header->base_known; + base = cu_header->base_address; + + if (offset >= dwarf_ranges_size) + { + complaint (&symfile_complaints, + "Offset %d out of bounds for DW_AT_ranges attribute", + offset); + return 0; + } + 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; @@ -1688,21 +2432,20 @@ dwarf2_get_pc_bounds (die, lowpc, highpc, objfile) 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; @@ -1711,7 +2454,7 @@ dwarf2_add_field (fip, die, objfile) /* 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; @@ -1736,10 +2479,15 @@ dwarf2_add_field (fip, die, objfile) 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); @@ -1757,7 +2505,7 @@ dwarf2_add_field (fip, die, objfile) 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; @@ -1820,12 +2568,18 @@ dwarf2_add_field (fip, die, objfile) 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); @@ -1837,7 +2591,7 @@ dwarf2_add_field (fip, die, objfile) 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); } @@ -1846,9 +2600,11 @@ dwarf2_add_field (fip, die, objfile) /* 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++; } @@ -1857,10 +2613,8 @@ dwarf2_add_field (fip, die, objfile) /* 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; @@ -1924,8 +2678,8 @@ dwarf2_attach_fields_to_type (fip, type, objfile) 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; } @@ -1946,11 +2700,9 @@ dwarf2_attach_fields_to_type (fip, type, objfile) /* 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; @@ -2001,7 +2753,7 @@ dwarf2_add_member_fn (fip, die, type, objfile) /* 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; @@ -2015,23 +2767,15 @@ dwarf2_add_member_fn (fip, die, type, objfile) if (die->type && TYPE_CODE (die->type) == TYPE_CODE_FUNC) { struct type *return_type = TYPE_TARGET_TYPE (die->type); - struct type **arg_types; int nparams = TYPE_NFIELDS (die->type); - int iparams; - - /* Copy argument types from the subroutine type. */ - arg_types = (struct type **) - TYPE_ALLOC (fnp->type, (nparams + 1) * sizeof (struct type *)); - for (iparams = 0; iparams < nparams; iparams++) - arg_types[iparams] = TYPE_FIELD_TYPE (die->type, iparams); - - /* Set last entry in argument type vector. */ - if (TYPE_FLAGS (die->type) & TYPE_FLAG_VARARGS) - arg_types[nparams] = NULL; - else - arg_types[nparams] = dwarf2_fundamental_type (objfile, FT_VOID); - smash_to_method_type (fnp->type, type, return_type, arg_types); + /* 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 @@ -2043,11 +2787,12 @@ dwarf2_add_member_fn (fip, die, type, objfile) 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. */ @@ -2067,19 +2812,37 @@ dwarf2_add_member_fn (fip, die, type, objfile) } } + /* 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; @@ -2126,9 +2889,8 @@ dwarf2_attach_fn_fields_to_type (fip, type, objfile) 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; @@ -2186,29 +2948,30 @@ read_structure_scope (die, objfile) while (child_die && child_die->tag) { - if (child_die->tag == DW_TAG_member) + if (child_die->tag == DW_TAG_member + || child_die->tag == DW_TAG_variable) { - dwarf2_add_field (&fi, child_die, objfile); - } - else if (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); } @@ -2226,7 +2989,7 @@ read_structure_scope (die, objfile) 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) @@ -2252,8 +3015,10 @@ read_structure_scope (die, objfile) /* 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 { @@ -2262,7 +3027,7 @@ read_structure_scope (die, objfile) } } - new_symbol (die, type, objfile); + new_symbol (die, type, objfile, cu_header); do_cleanups (back_to); } @@ -2271,8 +3036,6 @@ read_structure_scope (die, objfile) /* 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 @@ -2285,9 +3048,8 @@ read_structure_scope (die, objfile) 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; @@ -2327,14 +3089,14 @@ read_enumeration (die, objfile) { 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; @@ -2346,10 +3108,11 @@ read_enumeration (die, objfile) * sizeof (struct field)); } - FIELD_NAME (fields[num_fields]) = SYMBOL_NAME (sym); + FIELD_NAME (fields[num_fields]) = DEPRECATED_SYMBOL_NAME (sym); 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++; } @@ -2365,13 +3128,13 @@ read_enumeration (die, objfile) 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 @@ -2379,9 +3142,8 @@ read_enumeration (die, objfile) 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; @@ -2397,7 +3159,7 @@ read_array_type (die, objfile) 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. */ @@ -2426,7 +3188,7 @@ read_array_type (die, objfile) 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) { @@ -2437,14 +3199,15 @@ read_array_type (die, objfile) 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; @@ -2463,7 +3226,8 @@ read_array_type (die, objfile) 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); } @@ -2478,8 +3242,8 @@ read_array_type (die, objfile) } 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; @@ -2509,6 +3273,16 @@ read_array_type (die, objfile) 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. */ @@ -2518,9 +3292,8 @@ read_array_type (die, objfile) /* 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; @@ -2530,19 +3303,32 @@ read_common_block (die, objfile) 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); @@ -2550,32 +3336,144 @@ read_common_block (die, objfile) } } +/* Read a C++ namespace. */ + +static void +read_namespace (struct die_info *die, struct objfile *objfile, + const struct comp_unit_head *cu_header) +{ + const char *previous_namespace = processing_current_namespace; + const char *name = NULL; + int is_anonymous; + struct die_info *current_die; + + /* Loop through the extensions until we find a name. */ + + for (current_die = die; + current_die != NULL; + current_die = dwarf2_extension (die)) + { + name = dwarf2_name (current_die); + if (name != NULL) + break; + } + + /* Is it an anonymous namespace? */ + + is_anonymous = (name == NULL); + if (is_anonymous) + name = "(anonymous namespace)"; + + /* Now build the name of the current namespace. */ + + if (previous_namespace[0] == '\0') + { + processing_current_namespace = name; + } + else + { + /* We need temp_name around because processing_current_namespace + is a const char *. */ + char *temp_name = alloca (strlen (previous_namespace) + + 2 + strlen(name) + 1); + strcpy (temp_name, previous_namespace); + strcat (temp_name, "::"); + strcat (temp_name, name); + + processing_current_namespace = temp_name; + } + + /* Add a symbol associated to this if we haven't seen the namespace + before. Also, add a using directive if it's an anonymous + namespace. */ + + if (dwarf2_extension (die) == NULL) + { + struct type *type; + + /* FIXME: carlton/2003-06-27: Once GDB is more const-correct, + this cast will hopefully become unnecessary. */ + type = init_type (TYPE_CODE_NAMESPACE, 0, 0, + (char *) processing_current_namespace, + objfile); + TYPE_TAG_NAME (type) = TYPE_NAME (type); + + new_symbol (die, type, objfile, cu_header); + + if (is_anonymous) + cp_add_using_directive (processing_current_namespace, + strlen (previous_namespace), + strlen (processing_current_namespace)); + } + + 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); + } + } + + processing_current_namespace = previous_namespace; +} + /* 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; } @@ -2583,9 +3481,8 @@ read_tag_pointer_type (die, objfile) 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; @@ -2597,8 +3494,8 @@ read_tag_ptr_to_member_type (die, objfile) } 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; @@ -2608,9 +3505,8 @@ read_tag_ptr_to_member_type (die, objfile) 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; @@ -2620,7 +3516,7 @@ read_tag_reference_type (die, objfile) 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) { @@ -2628,37 +3524,39 @@ read_tag_reference_type (die, objfile) } 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 @@ -2667,9 +3565,7 @@ read_tag_volatile_type (die, objfile) 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; @@ -2687,12 +3583,30 @@ read_tag_string_type (die, objfile) } 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; } @@ -2708,9 +3622,8 @@ read_tag_string_type (die, objfile) */ 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 */ @@ -2721,7 +3634,7 @@ read_subroutine_type (die, objfile) { return; } - type = die_type (die, objfile); + type = die_type (die, objfile, cu_header); ftype = lookup_function_type (type); /* All functions in C++ have prototypes. */ @@ -2769,7 +3682,8 @@ read_subroutine_type (die, objfile) 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); @@ -2780,30 +3694,21 @@ read_subroutine_type (die, objfile) } 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); } } @@ -2811,9 +3716,7 @@ read_typedef (die, objfile) 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; @@ -2839,18 +3742,18 @@ read_base_type (die, objfile) 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; @@ -2863,16 +3766,28 @@ read_base_type (die, objfile) 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 { @@ -2883,24 +3798,24 @@ read_base_type (die, objfile) /* 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++; @@ -2932,8 +3847,7 @@ read_comp_unit (info_ptr, abfd) /* 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; @@ -2941,8 +3855,8 @@ free_die_list (dies) while (die) { next = die->next; - free (die->attrs); - free (die); + xfree (die->attrs); + xfree (die); die = next; } } @@ -2963,21 +3877,24 @@ make_cleanup_free_die_list (struct die_info *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'", @@ -2992,19 +3909,18 @@ dwarf2_read_section (objfile, offset, size) 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; @@ -3043,8 +3959,8 @@ dwarf2_read_abbrevs (abfd, offset) } 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 @@ -3058,7 +3974,7 @@ dwarf2_read_abbrevs (abfd, offset) 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; } } @@ -3067,38 +3983,39 @@ dwarf2_read_abbrevs (abfd, offset) /* 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) { @@ -3113,11 +4030,8 @@ dwarf2_lookup_abbrev (number) /* 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; @@ -3128,16 +4042,16 @@ read_partial_die (part_die, abfd, info_ptr, has_pc_info) 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; @@ -3146,7 +4060,8 @@ read_partial_die (part_die, abfd, info_ptr, has_pc_info) 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. */ @@ -3170,7 +4085,20 @@ read_partial_die (part_die, abfd, info_ptr, has_pc_info) 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); @@ -3193,7 +4121,7 @@ read_partial_die (part_die, abfd, info_ptr, has_pc_info) /* 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); @@ -3213,7 +4141,7 @@ read_partial_die (part_die, abfd, info_ptr, has_pc_info) 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; @@ -3236,7 +4164,7 @@ read_partial_die (part_die, abfd, info_ptr, has_pc_info) && 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; } @@ -3244,10 +4172,8 @@ read_partial_die (part_die, abfd, info_ptr, has_pc_info) 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; @@ -3266,10 +4192,11 @@ read_full_die (diep, abfd, info_ptr) 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; @@ -3285,33 +4212,30 @@ read_full_die (diep, abfd, info_ptr) 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 (); @@ -3345,6 +4269,11 @@ read_attribute (attr, abbrev, abfd, info_ptr) 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); @@ -3389,138 +4318,262 @@ read_attribute (attr, abbrev, abfd, info_ptr) 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; +read_1_signed_byte (bfd *abfd, char *buf) { return bfd_get_signed_8 (abfd, (bfd_byte *) buf); } static unsigned int -read_2_bytes (abfd, buf) - bfd *abfd; - char *buf; +read_2_bytes (bfd *abfd, char *buf) { return bfd_get_16 (abfd, (bfd_byte *) buf); } static int -read_2_signed_bytes (abfd, buf) - bfd *abfd; - char *buf; +read_2_signed_bytes (bfd *abfd, char *buf) { return bfd_get_signed_16 (abfd, (bfd_byte *) buf); } static unsigned int -read_4_bytes (abfd, buf) - bfd *abfd; - char *buf; +read_4_bytes (bfd *abfd, char *buf) { return bfd_get_32 (abfd, (bfd_byte *) buf); } static int -read_4_signed_bytes (abfd, buf) - bfd *abfd; - char *buf; +read_4_signed_bytes (bfd *abfd, char *buf) { return bfd_get_signed_32 (abfd, (bfd_byte *) buf); } static unsigned long -read_8_bytes (abfd, buf) - bfd *abfd; - char *buf; +read_8_bytes (bfd *abfd, char *buf) { return bfd_get_64 (abfd, (bfd_byte *) buf); } static CORE_ADDR -read_address (abfd, buf) - bfd *abfd; - char *buf; +read_address (bfd *abfd, char *buf, const struct comp_unit_head *cu_header, + int *bytes_read) { CORE_ADDR retval = 0; - switch (address_size) + 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; +} + +/* 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) +{ + LONGEST retval = 0; + + retval = bfd_get_32 (abfd, (bfd_byte *) buf); + + if (retval == 0xffffffff) + { + retval = bfd_get_64 (abfd, (bfd_byte *) buf + 4); + *bytes_read = 12; + if (cu_header != NULL) + { + cu_header->initial_length_size = 12; + cu_header->offset_size = 8; + } + } + else 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; + } + } + + return retval; +} + +/* Read an offset from the data stream. The size of the offset is + given by cu_header->offset_size. */ + +static LONGEST +read_offset (bfd *abfd, char *buf, const struct comp_unit_head *cu_header, + int *bytes_read) +{ + LONGEST retval = 0; + + switch (cu_header->offset_size) { - case 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)); } 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; @@ -3528,32 +4581,36 @@ read_string (abfd, buf, bytes_read_ptr) } *bytes_read_ptr = strlen (buf) + 1; return buf; -#else - int byte; - unsigned int i = 0; +} - while ((byte = bfd_get_8 (abfd, (bfd_byte *) buf)) != 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); + + 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 long -read_unsigned_leb128 (abfd, buf, bytes_read_ptr) - bfd *abfd; - char *buf; - unsigned int *bytes_read_ptr; +read_unsigned_leb128 (bfd *abfd, char *buf, unsigned int *bytes_read_ptr) { unsigned long result; unsigned int num_read; @@ -3581,10 +4638,7 @@ read_unsigned_leb128 (abfd, buf, bytes_read_ptr) } static long -read_signed_leb128 (abfd, buf, bytes_read_ptr) - bfd *abfd; - char *buf; - unsigned int *bytes_read_ptr; +read_signed_leb128 (bfd *abfd, char *buf, unsigned int *bytes_read_ptr) { long result; int i, shift, size, num_read; @@ -3616,8 +4670,7 @@ read_signed_leb128 (abfd, buf, bytes_read_ptr) } static void -set_cu_language (lang) - unsigned int lang; +set_cu_language (unsigned int lang) { switch (lang) { @@ -3630,18 +4683,23 @@ set_cu_language (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: case DW_LANG_Modula2: default: - cu_language = language_unknown; + cu_language = language_minimal; break; } cu_language_defn = language_def (cu_language); @@ -3650,9 +4708,7 @@ set_cu_language (lang) /* 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; @@ -3686,89 +4742,153 @@ die_is_declaration (struct die_info *die) && ! 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 (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; } @@ -3776,44 +4896,98 @@ dwarf_decode_lines (offset, comp_dir, abfd) 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 (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; + 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); } 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. */ - /* Read file name table */ - while ((cur_file = read_string (abfd, line_ptr, &bytes_read)) != NULL) - { - 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 (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++; - } - line_ptr += bytes_read; +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) @@ -3823,19 +4997,23 @@ dwarf_decode_lines (offset, comp_dir, abfd) 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. */ @@ -3843,7 +5021,19 @@ dwarf_decode_lines (offset, comp_dir, abfd) { 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 */ + record_line (current_subfile, line, + check_cu_functions (address)); + basic_block = 1; + } + else switch (op_code) { case DW_LNS_extended_op: line_ptr += 1; /* ignore length */ @@ -3853,52 +5043,45 @@ dwarf_decode_lines (offset, comp_dir, abfd) { 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 (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: - record_line (current_subfile, line, address); + record_line (current_subfile, line, + check_cu_functions (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; @@ -3907,15 +5090,21 @@ dwarf_decode_lines (offset, comp_dir, abfd) 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); @@ -3933,26 +5122,25 @@ dwarf_decode_lines (offset, comp_dir, abfd) 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 @@ -3976,32 +5164,85 @@ done: 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); } +static void +var_decode_location (struct attribute *attr, struct symbol *sym, + struct objfile *objfile, + const struct comp_unit_head *cu_header) +{ + /* NOTE drow/2003-01-30: There used to be a comment and some special + code here to turn a symbol with DW_AT_external and a + SYMBOL_VALUE_ADDRESS of 0 into a LOC_UNRESOLVED symbol. This was + necessary for platforms (maybe Alpha, certainly PowerPC GNU/Linux + with some versions of binutils) where shared libraries could have + relocations against symbols in their debug information - the + minimal symbol would have the right address, but the debug info + would not. It's no longer necessary, because we will explicitly + apply relocations when we read in the debug information now. */ + + /* A DW_AT_location attribute with no contents indicates that a + variable has been optimized away. */ + if (attr_form_is_block (attr) && DW_BLOCK (attr)->size == 0) + { + SYMBOL_CLASS (sym) = LOC_OPTIMIZED_OUT; + return; + } + + /* Handle one degenerate form of location expression specially, to + preserve GDB's previous behavior when section offsets are + specified. If this is just a DW_OP_addr then mark this symbol + as LOC_STATIC. */ + + if (attr_form_is_block (attr) + && DW_BLOCK (attr)->size == 1 + cu_header->addr_size + && DW_BLOCK (attr)->data[0] == DW_OP_addr) + { + int dummy; + + SYMBOL_VALUE_ADDRESS (sym) = + read_address (objfile->obfd, DW_BLOCK (attr)->data + 1, cu_header, + &dummy); + fixup_symbol_section (sym, objfile); + SYMBOL_VALUE_ADDRESS (sym) += ANOFFSET (objfile->section_offsets, + SYMBOL_SECTION (sym)); + SYMBOL_CLASS (sym) = LOC_STATIC; + return; + } + + /* NOTE drow/2002-01-30: It might be worthwhile to have a static + expression evaluator, and use LOC_COMPUTED only when necessary + (i.e. when the value of a register or memory location is + referenced, or a thread-local block, etc.). Then again, it might + not be worthwhile. I'm assuming that it isn't unless performance + or memory numbers show me otherwise. */ + + dwarf2_symbol_mark_computed (attr, sym, cu_header, objfile); + SYMBOL_CLASS (sym) = LOC_COMPUTED; +} + /* Given a pointer to a DWARF information entry, figure out if we need to make a symbol table entry for it, and if so, create a new entry and return a pointer to it. @@ -4009,49 +5250,44 @@ dwarf2_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; + + if (die->tag != DW_TAG_namespace) + name = dwarf2_linkage_name (die); + else + name = TYPE_NAME (type); - name = dwarf2_linkage_name (die); if (name) { sym = (struct symbol *) obstack_alloc (&objfile->symbol_obstack, sizeof (struct symbol)); OBJSTAT (objfile, n_syms++); memset (sym, 0, sizeof (struct symbol)); - SYMBOL_NAME (sym) = obsavestring (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. */ - SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; + SYMBOL_DOMAIN (sym) = VAR_DOMAIN; SYMBOL_CLASS (sym) = LOC_STATIC; if (type != NULL) SYMBOL_TYPE (sym) = type; else - SYMBOL_TYPE (sym) = die_type (die, objfile); + SYMBOL_TYPE (sym) = die_type (die, objfile, cu_header); attr = dwarf_attr (die, DW_AT_decl_line); if (attr) { 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: @@ -4088,7 +5324,7 @@ new_symbol (die, type, objfile) 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); @@ -4099,56 +5335,12 @@ new_symbol (die, type, objfile) attr = dwarf_attr (die, DW_AT_location); if (attr) { + var_decode_location (attr, sym, objfile, cu_header); attr2 = dwarf_attr (die, DW_AT_external); if (attr2 && (DW_UNSND (attr2) != 0)) - { - SYMBOL_VALUE_ADDRESS (sym) = - decode_locdesc (DW_BLOCK (attr), objfile); - add_symbol_to_list (sym, &global_symbols); - - /* In shared libraries the address of the variable - in the location descriptor might still be relocatable, - so its value could be zero. - Enter the symbol as a LOC_UNRESOLVED symbol, if its - value is zero, the address of the variable will then - be determined from the minimal symbol table whenever - the variable is referenced. */ - if (SYMBOL_VALUE_ADDRESS (sym)) - { - SYMBOL_VALUE_ADDRESS (sym) += baseaddr; - SYMBOL_CLASS (sym) = LOC_STATIC; - } - else - SYMBOL_CLASS (sym) = LOC_UNRESOLVED; - } + add_symbol_to_list (sym, &global_symbols); else - { - SYMBOL_VALUE (sym) = addr = - decode_locdesc (DW_BLOCK (attr), objfile); - add_symbol_to_list (sym, list_in_scope); - if (optimized_out) - { - SYMBOL_CLASS (sym) = LOC_OPTIMIZED_OUT; - } - else if (isreg) - { - SYMBOL_CLASS (sym) = LOC_REGISTER; - } - else if (offreg) - { - SYMBOL_CLASS (sym) = LOC_BASEREG; - SYMBOL_BASEREG (sym) = basereg; - } - else if (islocal) - { - SYMBOL_CLASS (sym) = LOC_LOCAL; - } - else - { - SYMBOL_CLASS (sym) = LOC_STATIC; - SYMBOL_VALUE_ADDRESS (sym) = addr + baseaddr; - } - } + add_symbol_to_list (sym, list_in_scope); } else { @@ -4171,34 +5363,15 @@ new_symbol (die, type, objfile) attr = dwarf_attr (die, DW_AT_location); if (attr) { - SYMBOL_VALUE (sym) = decode_locdesc (DW_BLOCK (attr), objfile); - if (isreg) - { - SYMBOL_CLASS (sym) = LOC_REGPARM; - } - else if (offreg) - { - if (isderef) - { - if (basereg != frame_base_reg) - complain (&dwarf2_complex_location_expr); - SYMBOL_CLASS (sym) = LOC_REF_ARG; - } - else - { - SYMBOL_CLASS (sym) = LOC_BASEREG_ARG; - SYMBOL_BASEREG (sym) = basereg; - } - } - else - { - SYMBOL_CLASS (sym) = LOC_ARG; - } + var_decode_location (attr, sym, objfile, cu_header); + /* FIXME drow/2003-07-31: Is LOC_COMPUTED_ARG necessary? */ + if (SYMBOL_CLASS (sym) == LOC_COMPUTED) + SYMBOL_CLASS (sym) = LOC_COMPUTED_ARG; } 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; @@ -4212,7 +5385,7 @@ new_symbol (die, type, objfile) case DW_TAG_union_type: case DW_TAG_enumeration_type: SYMBOL_CLASS (sym) = LOC_TYPEDEF; - SYMBOL_NAMESPACE (sym) = STRUCT_NAMESPACE; + SYMBOL_DOMAIN (sym) = STRUCT_DOMAIN; add_symbol_to_list (sym, list_in_scope); /* The semantics of C++ state that "struct foo { ... }" also @@ -4224,11 +5397,11 @@ new_symbol (die, type, objfile) obstack_alloc (&objfile->symbol_obstack, sizeof (struct symbol)); *typedef_sym = *sym; - SYMBOL_NAMESPACE (typedef_sym) = VAR_NAMESPACE; + SYMBOL_DOMAIN (typedef_sym) = VAR_DOMAIN; if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0) TYPE_NAME (SYMBOL_TYPE (sym)) = - obsavestring (SYMBOL_NAME (sym), - strlen (SYMBOL_NAME (sym)), + obsavestring (DEPRECATED_SYMBOL_NAME (sym), + strlen (DEPRECATED_SYMBOL_NAME (sym)), &objfile->type_obstack); add_symbol_to_list (typedef_sym, list_in_scope); } @@ -4236,23 +5409,28 @@ new_symbol (die, type, objfile) case DW_TAG_typedef: case DW_TAG_base_type: SYMBOL_CLASS (sym) = LOC_TYPEDEF; - SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; + SYMBOL_DOMAIN (sym) = VAR_DOMAIN; add_symbol_to_list (sym, list_in_scope); break; case DW_TAG_enumerator: 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; + case DW_TAG_namespace: + SYMBOL_CLASS (sym) = LOC_TYPEDEF; + add_symbol_to_list (sym, &global_symbols); + break; default: /* Not a tag we recognize. Hopefully we aren't processing 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; } } @@ -4262,22 +5440,26 @@ new_symbol (die, type, objfile) /* 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 (DEPRECATED_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); + /* NOTE: cagney/2003-05-09: In-lined store_address call with + it's body - store_unsigned_integer. */ + store_unsigned_integer (SYMBOL_VALUE_BYTES (sym), cu_header->addr_size, + DW_ADDR (attr)); SYMBOL_CLASS (sym) = LOC_CONST_BYTES; break; case DW_FORM_block1: @@ -4286,8 +5468,10 @@ dwarf2_const_value (attr, sym, objfile) 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 (DEPRECATED_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); @@ -4323,8 +5507,9 @@ dwarf2_const_value (attr, sym, objfile) 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; @@ -4357,9 +5542,8 @@ dwarf2_const_value_data (struct attribute *attr, /* 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; @@ -4378,15 +5562,17 @@ die_type (die, objfile) 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; } @@ -4395,9 +5581,8 @@ die_type (die, objfile) 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; @@ -4411,25 +5596,25 @@ die_containing_type (die, objfile) 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; @@ -4446,9 +5631,8 @@ type_at_offset (offset, objfile) #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) { @@ -4456,104 +5640,71 @@ tag_type_to_type (die, objfile) } else { - struct attribute *attr; - attr = dwarf_attr (die, DW_AT_name); - if (attr && DW_STRING (attr)) - { - char *attrname=DW_STRING (attr); - unsigned long hashval=hash(attrname, strlen(attrname)) % TYPE_HASH_SIZE; - - if (dwarf2_cached_types[hashval] != NULL) - { - const char *nameoftype; - nameoftype = TYPE_NAME(dwarf2_cached_types[hashval]) == NULL ? TYPE_TAG_NAME(dwarf2_cached_types[hashval]) : TYPE_NAME(dwarf2_cached_types[hashval]); - if (strcmp(attrname, nameoftype) == 0) - { - die->type=dwarf2_cached_types[hashval]; - } - else - { - read_type_die (die, objfile); - dwarf2_cached_types[hashval] = die->type; - } - } - else - { - read_type_die (die, objfile); - dwarf2_cached_types[hashval] = 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. */ @@ -4630,8 +5781,7 @@ dwarf_base_type (encoding, size, objfile) #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; @@ -4664,9 +5814,8 @@ copy_die (old_die) /* 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; @@ -4710,8 +5859,7 @@ sibling_die (die) /* 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; @@ -4724,11 +5872,47 @@ dwarf2_linkage_name (die) return NULL; } +/* Get name of a die, return NULL if not found. */ + +static char * +dwarf2_name (struct die_info *die) +{ + struct attribute *attr; + + attr = dwarf_attr (die, DW_AT_name); + if (attr && DW_STRING (attr)) + return DW_STRING (attr); + return NULL; +} + +/* Return the die that this die in an extension of, or NULL if there + is none. */ + +static struct die_info * +dwarf2_extension (struct die_info *die) +{ + struct attribute *attr; + struct die_info *extension_die; + unsigned int ref; + + attr = dwarf_attr (die, DW_AT_extension); + if (attr == NULL) + return NULL; + + ref = dwarf2_get_ref_die_offset (attr); + extension_die = follow_die_ref (ref); + if (!extension_die) + { + error ("Dwarf Error: Cannot find referent at offset %d.", ref); + } + + return extension_die; +} + /* Convert a DIE tag into its string name. */ static char * -dwarf_tag_name (tag) - register unsigned tag; +dwarf_tag_name (unsigned tag) { switch (tag) { @@ -4828,6 +6012,22 @@ dwarf_tag_name (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: @@ -4844,8 +6044,7 @@ dwarf_tag_name (tag) /* Convert a DWARF attribute code into its string name. */ static char * -dwarf_attr_name (attr) - register unsigned attr; +dwarf_attr_name (unsigned attr) { switch (attr) { @@ -4973,7 +6172,30 @@ dwarf_attr_name (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"; @@ -4987,9 +6209,9 @@ dwarf_attr_name (attr) return "DW_AT_MIPS_loop_unroll_factor"; case DW_AT_MIPS_software_pipeline_depth: return "DW_AT_MIPS_software_pipeline_depth"; +#endif case DW_AT_MIPS_linkage_name: return "DW_AT_MIPS_linkage_name"; -#endif case DW_AT_sf_names: return "DW_AT_sf_names"; @@ -5003,6 +6225,8 @@ dwarf_attr_name (attr) 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_"; } @@ -5011,8 +6235,7 @@ dwarf_attr_name (attr) /* Convert a DWARF value form code into its string name. */ static char * -dwarf_form_name (form) - register unsigned form; +dwarf_form_name (unsigned form) { switch (form) { @@ -5066,8 +6289,7 @@ dwarf_form_name (form) /* Convert a DWARF stack opcode into its string name. */ static char * -dwarf_stack_op_name (op) - register unsigned op; +dwarf_stack_op_name (unsigned op) { switch (op) { @@ -5361,14 +6583,25 @@ dwarf_stack_op_name (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_"; } } static char * -dwarf_bool_name (mybool) - unsigned mybool; +dwarf_bool_name (unsigned mybool) { if (mybool) return "TRUE"; @@ -5379,8 +6612,7 @@ dwarf_bool_name (mybool) /* Convert a DWARF type code into its string name. */ static char * -dwarf_type_encoding_name (enc) - register unsigned enc; +dwarf_type_encoding_name (unsigned enc) { switch (enc) { @@ -5400,6 +6632,8 @@ dwarf_type_encoding_name (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_"; } @@ -5409,8 +6643,7 @@ dwarf_type_encoding_name (enc) #if 0 static char * -dwarf_cfi_name (cfi_opc) - register unsigned cfi_opc; +dwarf_cfi_name (unsigned cfi_opc) { switch (cfi_opc) { @@ -5450,44 +6683,65 @@ dwarf_cfi_name (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_"; } } #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: @@ -5498,33 +6752,35 @@ dump_die (die) case DW_FORM_ref4: case DW_FORM_udata: case DW_FORM_sdata: - fprintf (stderr, "constant: %ld", 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 */ 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) { @@ -5533,10 +6789,8 @@ dump_die_list (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; @@ -5549,14 +6803,13 @@ store_in_ref_table (offset, die) 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; @@ -5568,18 +6821,20 @@ dwarf2_get_ref_die_offset (attr) 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; @@ -5598,14 +6853,12 @@ follow_die_ref (offset) } 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 @@ -5649,9 +6902,8 @@ dwarf2_fundamental_type (objfile, typeid) 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; @@ -5676,6 +6928,41 @@ decode_locdesc (blk, objfile) 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: @@ -5716,12 +7003,6 @@ decode_locdesc (blk, objfile) 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; @@ -5782,14 +7063,16 @@ decode_locdesc (blk, objfile) } 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: @@ -5833,6 +7116,11 @@ decode_locdesc (blk, objfile) 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--; @@ -5844,7 +7132,7 @@ decode_locdesc (blk, objfile) break; case DW_OP_minus: - stack[stacki - 1] = stack[stacki] - stack[stacki - 1]; + stack[stacki - 1] -= stack[stacki]; stacki--; break; @@ -5853,11 +7141,21 @@ decode_locdesc (blk, objfile) /* 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: + /* 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]); } } @@ -5868,14 +7166,13 @@ decode_locdesc (blk, objfile) /* 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; @@ -5885,7 +7182,7 @@ dwarf_alloc_block () } static struct abbrev_info * -dwarf_alloc_abbrev () +dwarf_alloc_abbrev (void) { struct abbrev_info *abbrev; @@ -5895,7 +7192,7 @@ dwarf_alloc_abbrev () } static struct die_info * -dwarf_alloc_die () +dwarf_alloc_die (void) { struct die_info *die; @@ -5903,3 +7200,448 @@ dwarf_alloc_die () memset (die, 0, sizeof (struct die_info)); return (die); } + + +/* 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: + + " " + + For function-like macro definitions, it should be: + + "() " + or + "(" ( "," ) * ") " + + Spaces may appear only where explicitly indicated, and in the + . + + 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); +} + +static void +dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym, + const struct comp_unit_head *cu_header, + struct objfile *objfile) +{ + if (attr->form == DW_FORM_data4 || attr->form == DW_FORM_data8) + { + struct dwarf2_loclist_baton *baton; + + baton = obstack_alloc (&objfile->symbol_obstack, + sizeof (struct dwarf2_loclist_baton)); + baton->objfile = objfile; + + /* We don't know how long the location list is, but make sure we + don't run off the edge of the section. */ + baton->size = dwarf_loc_size - DW_UNSND (attr); + baton->data = dwarf_loc_buffer + DW_UNSND (attr); + baton->base_address = cu_header->base_address; + if (cu_header->base_known == 0) + complaint (&symfile_complaints, + "Location list used without specifying the CU base address."); + + SYMBOL_LOCATION_FUNCS (sym) = &dwarf2_loclist_funcs; + SYMBOL_LOCATION_BATON (sym) = baton; + } + else + { + struct dwarf2_locexpr_baton *baton; + + baton = obstack_alloc (&objfile->symbol_obstack, + sizeof (struct dwarf2_locexpr_baton)); + baton->objfile = objfile; + + if (attr_form_is_block (attr)) + { + /* Note that we're just copying the block's data pointer + here, not the actual data. We're still pointing into the + dwarf_info_buffer for SYM's objfile; right now we never + release that buffer, but when we do clean up properly + this may need to change. */ + baton->size = DW_BLOCK (attr)->size; + baton->data = DW_BLOCK (attr)->data; + } + else + { + dwarf2_invalid_attrib_class_complaint ("location description", + SYMBOL_NATURAL_NAME (sym)); + baton->size = 0; + baton->data = NULL; + } + + SYMBOL_LOCATION_FUNCS (sym) = &dwarf2_locexpr_funcs; + SYMBOL_LOCATION_BATON (sym) = baton; + } +}