X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fdwarf2read.c;h=7ede81b71f18d0c3a6967cf5c4b67555b248409d;hb=413dad4d0e146d92406ab65b299172840ece4295;hp=3d9902c799994738fc8c6fc387a767cec5ccf6c6;hpb=bebd888e231b53bb94ecc2ce841e8ec4be1ffc5f;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 3d9902c799..7ede81b71f 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -1,5 +1,5 @@ /* DWARF 2 debugging format support for GDB. - Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 + Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology, @@ -37,12 +37,14 @@ #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 #include "gdb_string.h" +#include "gdb_assert.h" #include #ifndef DWARF2_REG_TO_REGNUM @@ -131,6 +133,8 @@ static file_ptr dwarf_aranges_offset; static file_ptr dwarf_loc_offset; static file_ptr dwarf_macinfo_offset; static file_ptr dwarf_str_offset; +file_ptr dwarf_frame_offset; +file_ptr dwarf_eh_frame_offset; static unsigned int dwarf_info_size; static unsigned int dwarf_abbrev_size; @@ -140,6 +144,8 @@ static unsigned int dwarf_aranges_size; static unsigned int dwarf_loc_size; static unsigned int dwarf_macinfo_size; static unsigned int dwarf_str_size; +unsigned int dwarf_frame_size; +unsigned int dwarf_eh_frame_size; /* names of the debugging sections */ @@ -151,9 +157,16 @@ static unsigned int dwarf_str_size; #define LOC_SECTION ".debug_loc" #define MACINFO_SECTION ".debug_macinfo" #define STR_SECTION ".debug_str" +#define FRAME_SECTION ".debug_frame" +#define EH_FRAME_SECTION ".eh_frame" /* local data types */ +/* 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 @@ -166,21 +179,74 @@ struct comp_unit_head 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]; }; -/* 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. */ @@ -194,6 +260,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; @@ -248,6 +315,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) @@ -263,17 +340,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 @@ -301,6 +371,8 @@ 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; /* A zeroed version of a partial die for initialization purposes. */ static struct partial_die_info zeroed_partial_die; @@ -338,6 +410,12 @@ static int islocal; /* Variable is at the returned offset this function, so we can't say which register it's relative to; use LOC_LOCAL. */ +static int is_thread_local; /* Variable is at a constant offset in the + thread-local storage block for the + current thread and the dynamic linker + module containing this expression. + decode_locdesc returns the offset from + that base. */ /* DW_AT_frame_base values for the current function. frame_base_reg is -1 if DW_AT_frame_base is missing, otherwise it @@ -382,6 +460,27 @@ 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; + }; #define PST_PRIVATE(p) ((struct dwarf2_pinfo *)(p)->read_symtab_private) @@ -390,6 +489,11 @@ 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) /* Maintain an array of referenced fundamental types for the current compilation unit being read. For DWARF version 1, we have to construct @@ -455,106 +559,140 @@ 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 = +static struct deprecated_complaint dwarf2_const_ignored = { "type qualifier 'const' ignored", 0, 0 }; -static struct complaint dwarf2_volatile_ignored = +static struct deprecated_complaint dwarf2_volatile_ignored = { "type qualifier 'volatile' ignored", 0, 0 }; -static struct complaint dwarf2_non_const_array_bound_ignored = +static struct deprecated_complaint dwarf2_non_const_array_bound_ignored = { "non-constant array bounds form '%s' ignored", 0, 0 }; -static struct complaint dwarf2_missing_line_number_section = +static struct deprecated_complaint dwarf2_missing_line_number_section = { "missing .debug_line section", 0, 0 }; -static struct complaint dwarf2_mangled_line_number_section = +static struct deprecated_complaint dwarf2_statement_list_fits_in_line_number_section = +{ + "statement list doesn't fit in .debug_line section", 0, 0 +}; +static struct deprecated_complaint dwarf2_mangled_line_number_section = { "mangled .debug_line section", 0, 0 }; -static struct complaint dwarf2_unsupported_die_ref_attr = +static struct deprecated_complaint dwarf2_unsupported_die_ref_attr = { "unsupported die ref attribute form: '%s'", 0, 0 }; -static struct complaint dwarf2_unsupported_stack_op = +static struct deprecated_complaint dwarf2_unsupported_stack_op = { "unsupported stack op: '%s'", 0, 0 }; -static struct complaint dwarf2_complex_location_expr = +static struct deprecated_complaint dwarf2_complex_location_expr = { "location expression too complex", 0, 0 }; -static struct complaint dwarf2_unsupported_tag = +static struct deprecated_complaint dwarf2_unsupported_tag = { "unsupported tag: '%s'", 0, 0 }; -static struct complaint dwarf2_unsupported_at_encoding = +static struct deprecated_complaint dwarf2_unsupported_at_encoding = { "unsupported DW_AT_encoding: '%s'", 0, 0 }; -static struct complaint dwarf2_unsupported_at_frame_base = +static struct deprecated_complaint dwarf2_unsupported_at_frame_base = { "unsupported DW_AT_frame_base for function '%s'", 0, 0 }; -static struct complaint dwarf2_unexpected_tag = +static struct deprecated_complaint dwarf2_unexpected_tag = { "unexepected tag in read_type_die: '%s'", 0, 0 }; -static struct complaint dwarf2_missing_at_frame_base = +static struct deprecated_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 = +static struct deprecated_complaint dwarf2_bad_static_member_name = { "unrecognized static data member name '%s'", 0, 0 }; -static struct complaint dwarf2_unsupported_accessibility = +static struct deprecated_complaint dwarf2_unsupported_accessibility = { "unsupported accessibility %d", 0, 0 }; -static struct complaint dwarf2_bad_member_name_complaint = +static struct deprecated_complaint dwarf2_bad_member_name_complaint = { "cannot extract member name from '%s'", 0, 0 }; -static struct complaint dwarf2_missing_member_fn_type_complaint = +static struct deprecated_complaint dwarf2_missing_member_fn_type_complaint = { "member function type missing for '%s'", 0, 0 }; -static struct complaint dwarf2_vtbl_not_found_complaint = +static struct deprecated_complaint dwarf2_vtbl_not_found_complaint = { "virtual function table pointer not found when defining class '%s'", 0, 0 }; -static struct complaint dwarf2_absolute_sibling_complaint = +static struct deprecated_complaint dwarf2_absolute_sibling_complaint = { "ignoring absolute DW_AT_sibling", 0, 0 }; -static struct complaint dwarf2_const_value_length_mismatch = +static struct deprecated_complaint dwarf2_const_value_length_mismatch = { "const value length mismatch for '%s', got %d, expected %d", 0, 0 }; -static struct complaint dwarf2_unsupported_const_value_attr = +static struct deprecated_complaint dwarf2_unsupported_const_value_attr = { "unsupported const value attribute form: '%s'", 0, 0 }; - -/* Externals references. */ -extern int info_verbose; /* From main.c; nonzero => verbose */ +static struct deprecated_complaint dwarf2_misplaced_line_number = +{ + "misplaced first line number at 0x%lx for '%s'", 0, 0 +}; +static struct deprecated_complaint dwarf2_line_header_too_long = +{ + "line number info header doesn't fit in `.debug_line' section", 0, 0 +}; +static struct deprecated_complaint dwarf2_missing_macinfo_section = +{ + "missing .debug_macinfo section", 0, 0 +}; +static struct deprecated_complaint dwarf2_macros_too_long = +{ + "macro info runs off end of `.debug_macinfo' section", 0, 0 +}; +static struct deprecated_complaint dwarf2_macros_not_terminated = +{ + "no terminating 0-type entry for macros in `.debug_macinfo' section", 0, 0 +}; +static struct deprecated_complaint dwarf2_macro_outside_file = +{ + "debug info gives macro %s outside of any file: %s", 0, 0 +}; +static struct deprecated_complaint dwarf2_macro_unmatched_end_file = +{ + "macro debug info has an unmatched `close_file' directive", 0, 0 +}; +static struct deprecated_complaint dwarf2_macro_malformed_definition = +{ + "macro debug info contains a malformed macro definition:\n`%s'", 0, 0 +}; +static struct deprecated_complaint dwarf2_macro_spaces_in_definition = +{ + "macro definition contains spaces in formal argument list:\n`%s'", 0, 0 +}; +static struct deprecated_complaint dwarf2_invalid_attrib_class = +{ + "invalid attribute class or form for '%s' in '%s'", 0, 0 +}; +static struct deprecated_complaint dwarf2_invalid_pointer_size = +{ + "invalid pointer size %d", 0, 0 +}; /* local function prototypes */ @@ -577,16 +715,17 @@ 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); -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 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 *, @@ -595,6 +734,9 @@ static char *read_full_die (struct die_info **, bfd *, char *, static char *read_attribute (struct attribute *, struct attr_abbrev *, 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 *); static int read_1_signed_byte (bfd *, char *); @@ -618,6 +760,9 @@ 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 *); @@ -628,7 +773,14 @@ 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 *); @@ -696,6 +848,9 @@ static void read_structure_scope (struct die_info *, struct objfile *, static void read_common_block (struct die_info *, struct objfile *, const struct comp_unit_head *); +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 *); @@ -727,7 +882,8 @@ static void read_tag_string_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 *, const struct comp_unit_head *); +static struct die_info *read_comp_unit (char *, bfd *, + const struct comp_unit_head *); static void free_die_list (struct die_info *); @@ -756,19 +912,19 @@ 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_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); @@ -782,13 +938,29 @@ 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 *); + /* 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 (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; bfd_map_over_sections (abfd, dwarf2_locate_sections, NULL); if (dwarf_info_offset && dwarf_abbrev_offset) { @@ -847,6 +1019,16 @@ dwarf2_locate_sections (bfd *ignore_abfd, asection *sectp, PTR ignore_ptr) dwarf_str_offset = sectp->filepos; dwarf_str_size = bfd_get_section_size_before_reloc (sectp); } + else if (STREQ (sectp->name, FRAME_SECTION)) + { + dwarf_frame_offset = sectp->filepos; + dwarf_frame_size = bfd_get_section_size_before_reloc (sectp); + } + else if (STREQ (sectp->name, EH_FRAME_SECTION)) + { + dwarf_eh_frame_offset = sectp->filepos; + dwarf_eh_frame_size = bfd_get_section_size_before_reloc (sectp); + } } /* Build a partial symbol table. */ @@ -863,12 +1045,31 @@ dwarf2_build_psymtabs (struct objfile *objfile, int mainline) 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); - if (mainline || objfile->global_psymbols.size == 0 || - objfile->static_psymbols.size == 0) + if (dwarf_line_offset) + dwarf_line_buffer = dwarf2_read_section (objfile, + dwarf_line_offset, + dwarf_line_size); + else + dwarf_line_buffer = NULL; + + if (dwarf_str_offset) + dwarf_str_buffer = dwarf2_read_section (objfile, + dwarf_str_offset, + dwarf_str_size); + else + dwarf_str_buffer = NULL; + + if (dwarf_macinfo_offset) + dwarf_macinfo_buffer = dwarf2_read_section (objfile, + dwarf_macinfo_offset, + dwarf_macinfo_size); + else + dwarf_macinfo_buffer = NULL; + + if (mainline + || (objfile->global_psymbols.size == 0 + && objfile->static_psymbols.size == 0)) { init_psymbol_list (objfile, 1024); } @@ -970,17 +1171,56 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline) 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; @@ -1006,13 +1246,18 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline) (long) (beg_of_comp_unit - dwarf_info_buffer)); 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, &cu_header); + &cu_header); /* Set the language we're debugging */ set_cu_language (comp_unit_die.language); @@ -1032,6 +1277,11 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline) DWARF_ABBREV_BUFFER (pst) = dwarf_abbrev_buffer; DWARF_ABBREV_SIZE (pst) = dwarf_abbrev_size; DWARF_LINE_BUFFER (pst) = dwarf_line_buffer; + 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; baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); /* Store the function that reads in the rest of the symbol table */ @@ -1047,7 +1297,7 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline) /* 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; @@ -1090,22 +1340,31 @@ scan_partial_symbols (char *info_ptr, struct objfile *objfile, back to that level. */ int nesting_level = 1; - int has_pc_info; + + /* We only want to read in symbols corresponding to variables or + other similar objects that are global or static. Normally, these + are all children of the DW_TAG_compile_unit die, so are all at + level 1. But C++ namespaces give ries to DW_TAG_namespace dies + whose children are global objects. So we keep track of what + level we currently think of as referring to file scope; this + should always equal 1 plus the number of namespaces that we are + currently nested within. */ + + int file_scope_level = 1; *lowpc = ((CORE_ADDR) -1); *highpc = ((CORE_ADDR) 0); while (nesting_level) { - info_ptr = read_partial_die (&pdi, abfd, info_ptr, - &has_pc_info, cu_header); + info_ptr = read_partial_die (&pdi, abfd, info_ptr, cu_header); if (pdi.name) { switch (pdi.tag) { case DW_TAG_subprogram: - if (has_pc_info) + if (pdi.has_pc_info) { if (pdi.lowpc < *lowpc) { @@ -1115,7 +1374,7 @@ scan_partial_symbols (char *info_ptr, struct objfile *objfile, { *highpc = pdi.highpc; } - if ((pdi.is_external || nesting_level == 1) + if ((pdi.is_external || nesting_level == file_scope_level) && !pdi.is_declaration) { add_partial_symbol (&pdi, objfile, cu_header); @@ -1128,46 +1387,65 @@ scan_partial_symbols (char *info_ptr, struct objfile *objfile, case DW_TAG_structure_type: case DW_TAG_union_type: case DW_TAG_enumeration_type: - if ((pdi.is_external || nesting_level == 1) + if ((pdi.is_external || nesting_level == file_scope_level) && !pdi.is_declaration) { add_partial_symbol (&pdi, objfile, cu_header); } break; case DW_TAG_enumerator: - /* File scope enumerators are added to the partial symbol - table. */ - if (nesting_level == 2) + /* File scope enumerators are added to the partial + symbol table. They're children of the enumeration + type die, so they occur at a level one higher than we + normally look for. */ + if (nesting_level == file_scope_level + 1) add_partial_symbol (&pdi, objfile, cu_header); break; case DW_TAG_base_type: /* File scope base type definitions are added to the partial symbol table. */ - if (nesting_level == 1) + if (nesting_level == file_scope_level) add_partial_symbol (&pdi, objfile, cu_header); break; + case DW_TAG_namespace: + /* FIXME: carlton/2002-10-16: we're not yet doing + anything useful with this, but for now make sure that + these tags at least don't cause us to miss any + important symbols. */ + if (pdi.has_children) + file_scope_level++; default: break; } } - /* If the die has a sibling, skip to the sibling. - Do not skip enumeration types, we want to record their - enumerators. */ - if (pdi.sibling && pdi.tag != DW_TAG_enumeration_type) + /* If the die has a sibling, skip to the sibling. Do not skip + enumeration types, we want to record their enumerators. Do + not skip namespaces, we want to record symbols inside + them. */ + if (pdi.sibling + && pdi.tag != DW_TAG_enumeration_type + && pdi.tag != DW_TAG_namespace) { info_ptr = pdi.sibling; } else if (pdi.has_children) { - /* Die has children, but the optional DW_AT_sibling attribute - is missing. */ + /* Die has children, but either the optional DW_AT_sibling + attribute is missing or we want to look at them. */ nesting_level++; } if (pdi.tag == 0) { nesting_level--; + /* If this is the end of a DW_TAG_namespace entry, then + decrease the file_scope_level, too. */ + if (nesting_level < file_scope_level) + { + file_scope_level--; + gdb_assert (nesting_level == file_scope_level); + } } } @@ -1333,6 +1611,11 @@ psymtab_to_symtab_1 (struct partial_symtab *pst) dwarf_abbrev_buffer = DWARF_ABBREV_BUFFER (pst); dwarf_abbrev_size = DWARF_ABBREV_SIZE (pst); dwarf_line_buffer = DWARF_LINE_BUFFER (pst); + 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); baseaddr = ANOFFSET (pst->section_offsets, SECT_OFF_TEXT (objfile)); cu_header_offset = offset; info_ptr = dwarf_info_buffer + offset; @@ -1347,8 +1630,8 @@ psymtab_to_symtab_1 (struct partial_symtab *pst) 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, &cu_header); @@ -1462,17 +1745,36 @@ process_die (struct die_info *die, struct objfile *objfile, break; case DW_TAG_common_inclusion: break; + case DW_TAG_namespace: + read_namespace (die, objfile, cu_header); + break; + case DW_TAG_imported_declaration: + case DW_TAG_imported_module: + /* FIXME: carlton/2002-10-16: Eventually, we should use the + information contained in these. DW_TAG_imported_declaration + dies shouldn't have children; DW_TAG_imported_module dies + shouldn't in the C++ case, but conceivably could in the + Fortran case, so we'll have to replace this gdb_assert if + Fortran compilers start generating that info. */ + gdb_assert (!die->has_children); + break; default: new_symbol (die, NULL, objfile, cu_header); break; } } +static void +initialize_cu_func_list (void) +{ + 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) { - unsigned int line_offset = 0; + struct cleanup *back_to = make_cleanup (null_cleanup, 0); CORE_ADDR lowpc = ((CORE_ADDR) -1); CORE_ADDR highpc = ((CORE_ADDR) 0); struct attribute *attr; @@ -1480,6 +1782,7 @@ read_file_scope (struct die_info *die, struct objfile *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)) { @@ -1560,13 +1863,7 @@ read_file_scope (struct die_info *die, struct objfile *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, cu_header); - } + initialize_cu_func_list (); /* Process all dies in compilation unit. */ if (die->has_children) @@ -1578,6 +1875,55 @@ read_file_scope (struct die_info *die, struct objfile *objfile, 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 @@ -1601,6 +1947,9 @@ read_func_scope (struct die_info *die, struct objfile *objfile, 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) { @@ -1615,7 +1964,24 @@ read_func_scope (struct die_info *die, struct objfile *objfile, attr = dwarf_attr (die, DW_AT_frame_base); if (attr) { - CORE_ADDR addr = decode_locdesc (DW_BLOCK (attr), objfile, cu_header); + 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) + { + complain (&dwarf2_complex_location_expr); + addr = 0; + } + else + { + complain (&dwarf2_invalid_attrib_class, "DW_AT_frame_base", name); + addr = 0; + } + if (isderef) complain (&dwarf2_unsupported_at_frame_base, name); else if (isreg) @@ -2043,23 +2409,15 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die, 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 @@ -2095,10 +2453,30 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die, } } + /* 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, cu_header) + 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) + { + complain (&dwarf2_complex_location_expr); + } + else + { + complain (&dwarf2_invalid_attrib_class, "DW_AT_vtable_elem_location", + fieldname); + } + } } /* Create the vector of member function fields, and attach it to the type. */ @@ -2296,8 +2674,6 @@ read_structure_scope (struct die_info *die, struct objfile *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 @@ -2460,7 +2836,8 @@ read_array_type (struct die_info *die, struct objfile *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); } @@ -2486,7 +2863,8 @@ read_array_type (struct die_info *die, struct objfile *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); } @@ -2532,6 +2910,16 @@ read_array_type (struct die_info *die, struct objfile *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. */ @@ -2552,7 +2940,20 @@ read_common_block (struct die_info *die, struct objfile *objfile, attr = dwarf_attr (die, DW_AT_location); if (attr) { - base = decode_locdesc (DW_BLOCK (attr), objfile, cu_header); + /* 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) + { + complain (&dwarf2_complex_location_expr); + } + else + { + complain (&dwarf2_invalid_attrib_class, "DW_AT_location", + "common block member"); + } } if (die->has_children) { @@ -2572,6 +2973,27 @@ read_common_block (struct die_info *die, struct objfile *objfile, } } +/* Read a C++ namespace. */ + +/* FIXME: carlton/2002-10-16: For now, we don't actually do anything + useful with the namespace data: we just process its children. */ + +static void +read_namespace (struct die_info *die, struct objfile *objfile, + const struct comp_unit_head *cu_header) +{ + if (die->has_children) + { + struct die_info *child_die = die->next; + + while (child_die && child_die->tag) + { + process_die (child_die, objfile, cu_header); + child_die = sibling_die (child_die); + } + } +} + /* Extract all information from a DW_TAG_pointer_type DIE and add to the user defined type vector. */ @@ -2580,7 +3002,9 @@ 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) { @@ -2588,15 +3012,42 @@ read_tag_pointer_type (struct die_info *die, struct objfile *objfile, } type = lookup_pointer_type (die_type (die, objfile, cu_header)); - attr = dwarf_attr (die, DW_AT_byte_size); - if (attr) - { - TYPE_LENGTH (type) = DW_UNSND (attr); - } + + 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) = cu_header->addr_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) + { + complain (&dwarf2_invalid_pointer_size, byte_size); + } + else { + /* Should we also complain about unhandled address classes? */ + } } + + TYPE_LENGTH (type) = byte_size; die->type = type; } @@ -2706,12 +3157,30 @@ read_tag_string_type (struct die_info *die, struct objfile *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; } @@ -2802,26 +3271,18 @@ static void 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, cu_header); - - type = alloc_type (objfile); - TYPE_CODE (type) = TYPE_CODE_TYPEDEF; - TYPE_FLAGS (type) |= TYPE_FLAG_TARGET_STUB; - TYPE_TARGET_TYPE (type) = xtype; attr = dwarf_attr (die, DW_AT_name); if (attr && 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); } } @@ -2855,18 +3316,18 @@ read_base_type (struct die_info *die, struct objfile *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; @@ -2879,16 +3340,28 @@ read_base_type (struct die_info *die, struct objfile *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)); 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 { @@ -2899,7 +3372,7 @@ read_base_type (struct die_info *die, struct objfile *objfile) /* Read a whole compilation unit into a linked list of dies. */ -struct die_info * +static struct die_info * read_comp_unit (char *info_ptr, bfd *abfd, const struct comp_unit_head *cu_header) { @@ -2978,7 +3451,7 @@ 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 * +char * dwarf2_read_section (struct objfile *objfile, file_ptr offset, unsigned int size) { @@ -2990,7 +3463,7 @@ dwarf2_read_section (struct objfile *objfile, file_ptr offset, buf = (char *) obstack_alloc (&objfile->psymbol_obstack, size); 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'", @@ -3005,17 +3478,18 @@ dwarf2_read_section (struct objfile *objfile, file_ptr offset, in a hash table. */ static void -dwarf2_read_abbrevs (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; @@ -3054,8 +3528,8 @@ dwarf2_read_abbrevs (bfd *abfd, unsigned int 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 @@ -3069,7 +3543,7 @@ dwarf2_read_abbrevs (bfd *abfd, unsigned int 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; } } @@ -3078,15 +3552,18 @@ dwarf2_read_abbrevs (bfd *abfd, unsigned int offset) /* ARGSUSED */ static void -dwarf2_empty_abbrev_table (PTR ignore) +dwarf2_empty_abbrev_table (PTR 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; @@ -3094,20 +3571,20 @@ dwarf2_empty_abbrev_table (PTR ignore) 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 (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) { @@ -3123,8 +3600,7 @@ dwarf2_lookup_abbrev (unsigned int number) static char * read_partial_die (struct partial_die_info *part_die, bfd *abfd, - char *info_ptr, int *has_pc_info, - const struct comp_unit_head *cu_header) + char *info_ptr, const struct comp_unit_head *cu_header) { unsigned int abbrev_number, bytes_read, i; struct abbrev_info *abbrev; @@ -3135,13 +3611,12 @@ read_partial_die (struct partial_die_info *part_die, bfd *abfd, 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); @@ -3178,7 +3653,20 @@ read_partial_die (struct partial_die_info *part_die, bfd *abfd, 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) + { + complain (&dwarf2_complex_location_expr); + } + else + { + complain (&dwarf2_invalid_attrib_class, "DW_AT_location", + "partial symbol information"); + } break; case DW_AT_language: part_die->language = DW_UNSND (&attr); @@ -3221,7 +3709,7 @@ read_partial_die (struct partial_die_info *part_die, bfd *abfd, int dummy; spec_ptr = dwarf_info_buffer + dwarf2_get_ref_die_offset (&spec_attr); - read_partial_die (&spec_die, abfd, spec_ptr, &dummy, cu_header); + read_partial_die (&spec_die, abfd, spec_ptr, cu_header); if (spec_die.name) { part_die->name = spec_die.name; @@ -3244,7 +3732,7 @@ read_partial_die (struct partial_die_info *part_die, bfd *abfd, && 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; } @@ -3272,7 +3760,7 @@ read_full_die (struct die_info **diep, bfd *abfd, char *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); @@ -3298,19 +3786,18 @@ read_full_die (struct die_info **diep, bfd *abfd, char *info_ptr, return info_ptr; } -/* Read an attribute described by an abbreviated attribute. */ +/* Read an attribute value described by an attribute form. */ static char * -read_attribute (struct attribute *attr, struct attr_abbrev *abbrev, +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: @@ -3349,6 +3836,11 @@ read_attribute (struct attribute *attr, struct attr_abbrev *abbrev, 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); @@ -3401,15 +3893,29 @@ read_attribute (struct attribute *attr, struct attr_abbrev *abbrev, 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)); + dwarf_form_name (form)); } 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 @@ -3501,12 +4007,25 @@ read_address (bfd *abfd, char *buf, const struct comp_unit_head *cu_header, return retval; } -/* Reads the initial length from a section. The (draft) DWARF 2.1 +/* 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(). @@ -3517,14 +4036,18 @@ read_address (bfd *abfd, char *buf, const struct comp_unit_head *cu_header, [ Note: read_initial_length() and read_offset() are based on the document entitled "DWARF Debugging Information Format", revision - 2.1, draft 4, dated July 20, 2000. This document was obtained + 3, draft 8, dated November 19, 2001. This document was obtained from: - http://reality.sgi.com/dehnert_engr/dwarf/dwarf2p1-draft4-000720.pdf + http://reality.sgiweb.org/davea/dwarf3-draft8-011125.pdf This document is only a draft and is subject to change. (So beware.) - - Kevin, Aug 4, 2000 + 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 @@ -3545,6 +4068,18 @@ read_initial_length (bfd *abfd, char *buf, struct comp_unit_head *cu_header, 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; @@ -3591,20 +4126,8 @@ 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 * @@ -3613,7 +4136,7 @@ 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; @@ -3621,25 +4144,30 @@ read_string (bfd *abfd, char *buf, unsigned int *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"); + 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"); 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 @@ -3716,6 +4244,7 @@ set_cu_language (unsigned int lang) break; case DW_LANG_Fortran77: case DW_LANG_Fortran90: + case DW_LANG_Fortran95: cu_language = language_fortran; break; case DW_LANG_Mips_Assembler: @@ -3725,6 +4254,7 @@ set_cu_language (unsigned int lang) 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: @@ -3773,87 +4303,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 (unsigned int offset, char *comp_dir, bfd *abfd, - const struct comp_unit_head *cu_header) +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; + 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) + { + complain (&dwarf2_statement_list_fits_in_line_number_section); + 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_initial_length (abfd, line_ptr, NULL, &bytes_read); + /* read in the header */ + lh->total_length = read_initial_length (abfd, line_ptr, NULL, &bytes_read); line_ptr += bytes_read; - line_end = line_ptr + lh.total_length; - lh.version = read_2_bytes (abfd, line_ptr); + if (line_ptr + lh->total_length > dwarf_line_buffer + dwarf_line_size) + { + complain (&dwarf2_statement_list_fits_in_line_number_section); + 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_offset (abfd, line_ptr, cu_header, &bytes_read); + 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); + 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; } @@ -3861,44 +4457,96 @@ dwarf_decode_lines (unsigned int offset, char *comp_dir, bfd *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; - 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); + dir_index = read_unsigned_leb128 (abfd, line_ptr, &bytes_read); line_ptr += bytes_read; - files.files[files.num_files].time = - read_unsigned_leb128 (abfd, line_ptr, &bytes_read); + mod_time = read_unsigned_leb128 (abfd, line_ptr, &bytes_read); line_ptr += bytes_read; - files.files[files.num_files].size = - read_unsigned_leb128 (abfd, line_ptr, &bytes_read); + length = read_unsigned_leb128 (abfd, line_ptr, &bytes_read); line_ptr += bytes_read; - files.num_files++; + + add_file_name (lh, cur_file, dir_index, mod_time, length); } line_ptr += bytes_read; + lh->statement_program_start = line_ptr; + + if (line_ptr > dwarf_line_buffer + dwarf_line_size) + complain (&dwarf2_line_header_too_long); + + 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) + complain (&dwarf2_misplaced_line_number, + (unsigned long) address, fn->name); + fn->seen_line = 1; + return fn->lowpc; +} + +/* Decode the line number information for the compilation unit whose + line number info is at OFFSET in the .debug_line section. + The compilation directory of the file is passed in COMP_DIR. */ + +static void +dwarf_decode_lines (struct line_header *lh, char *comp_dir, bfd *abfd, + const struct comp_unit_head *cu_header) +{ + char *line_ptr; + char *line_end; + unsigned int i, bytes_read; + char *cur_dir; + unsigned char op_code, extended_op, adj_opcode; + + line_ptr = lh->statement_program_start; + line_end = lh->statement_program_end; /* Read the statement sequences until there's nothing left. */ while (line_ptr < line_end) @@ -3908,19 +4556,23 @@ dwarf_decode_lines (unsigned int offset, char *comp_dir, bfd *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. */ @@ -3928,7 +4580,19 @@ dwarf_decode_lines (unsigned int offset, char *comp_dir, bfd *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 */ + address = check_cu_functions (address); + record_line (current_subfile, line, address); + basic_block = 1; + } + else switch (op_code) { case DW_LNS_extended_op: line_ptr += 1; /* ignore length */ @@ -3938,12 +4602,7 @@ dwarf_decode_lines (unsigned int offset, char *comp_dir, bfd *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, cu_header, &bytes_read); @@ -3951,40 +4610,36 @@ dwarf_decode_lines (unsigned int offset, char *comp_dir, bfd *abfd, 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; + return; } break; case DW_LNS_copy: + address = check_cu_functions (address); record_line (current_subfile, line, address); basic_block = 0; break; case DW_LNS_advance_pc: - address += lh.minimum_instruction_length + address += lh->minimum_instruction_length * read_unsigned_leb128 (abfd, line_ptr, &bytes_read); line_ptr += bytes_read; break; @@ -3993,15 +4648,21 @@ dwarf_decode_lines (unsigned int offset, char *comp_dir, bfd *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); @@ -4019,26 +4680,25 @@ dwarf_decode_lines (unsigned int offset, char *comp_dir, bfd *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 @@ -4100,7 +4760,7 @@ new_symbol (struct die_info *die, struct type *type, struct objfile *objfile, char *name; struct attribute *attr = NULL; struct attribute *attr2 = NULL; - CORE_ADDR addr; + CORE_ADDR addr = 0; name = dwarf2_linkage_name (die); if (name) @@ -4184,9 +4844,31 @@ new_symbol (struct die_info *die, struct type *type, struct objfile *objfile, attr2 = dwarf_attr (die, DW_AT_external); if (attr2 && (DW_UNSND (attr2) != 0)) { - SYMBOL_VALUE_ADDRESS (sym) = - decode_locdesc (DW_BLOCK (attr), objfile, cu_header); + /* Support the .debug_loc offsets */ + if (attr_form_is_block (attr)) + { + SYMBOL_VALUE_ADDRESS (sym) = + decode_locdesc (DW_BLOCK (attr), objfile, cu_header); + } + else if (attr->form == DW_FORM_data4 + || attr->form == DW_FORM_data8) + { + complain (&dwarf2_complex_location_expr); + } + else + { + complain (&dwarf2_invalid_attrib_class, "DW_AT_location", + "external variable"); + } add_symbol_to_list (sym, &global_symbols); + if (is_thread_local) + { + /* SYMBOL_VALUE_ADDRESS contains at this point the + offset of the variable within the thread local + storage. */ + SYMBOL_CLASS (sym) = LOC_THREAD_LOCAL_STATIC; + SYMBOL_OBJFILE (sym) = objfile; + } /* In shared libraries the address of the variable in the location descriptor might still be relocatable, @@ -4195,7 +4877,7 @@ new_symbol (struct die_info *die, struct type *type, struct objfile *objfile, value is zero, the address of the variable will then be determined from the minimal symbol table whenever the variable is referenced. */ - if (SYMBOL_VALUE_ADDRESS (sym)) + else if (SYMBOL_VALUE_ADDRESS (sym)) { fixup_symbol_section (sym, objfile); SYMBOL_VALUE_ADDRESS (sym) += @@ -4208,8 +4890,23 @@ new_symbol (struct die_info *die, struct type *type, struct objfile *objfile, } else { - SYMBOL_VALUE (sym) = addr = - decode_locdesc (DW_BLOCK (attr), objfile, cu_header); + /* Support the .debug_loc offsets */ + if (attr_form_is_block (attr)) + { + SYMBOL_VALUE (sym) = addr = + decode_locdesc (DW_BLOCK (attr), objfile, cu_header); + } + else if (attr->form == DW_FORM_data4 + || attr->form == DW_FORM_data8) + { + complain (&dwarf2_complex_location_expr); + } + else + { + complain (&dwarf2_invalid_attrib_class, "DW_AT_location", + "external variable"); + addr = 0; + } add_symbol_to_list (sym, list_in_scope); if (optimized_out) { @@ -4230,6 +4927,11 @@ new_symbol (struct die_info *die, struct type *type, struct objfile *objfile, { SYMBOL_CLASS (sym) = LOC_LOCAL; } + else if (is_thread_local) + { + SYMBOL_CLASS (sym) = LOC_THREAD_LOCAL_STATIC; + SYMBOL_OBJFILE (sym) = objfile; + } else { fixup_symbol_section (sym, objfile); @@ -4716,7 +5418,7 @@ copy_die (struct die_info *old_die) /* Return sibling of die, NULL if no sibling. */ -struct die_info * +static struct die_info * sibling_die (struct die_info *die) { int nesting_level = 0; @@ -4877,6 +5579,22 @@ dwarf_tag_name (register unsigned 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: @@ -5021,7 +5739,30 @@ dwarf_attr_name (register unsigned 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"; @@ -5051,6 +5792,8 @@ dwarf_attr_name (register unsigned 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_"; } @@ -5407,6 +6150,18 @@ dwarf_stack_op_name (register unsigned 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_"; } @@ -5444,6 +6199,8 @@ dwarf_type_encoding_name (register unsigned 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_"; } @@ -5493,43 +6250,65 @@ dwarf_cfi_name (register unsigned 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 +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: @@ -5540,31 +6319,34 @@ dump_die (struct die_info *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 +static void dump_die_list (struct die_info *die) { while (die) @@ -5574,7 +6356,7 @@ dump_die_list (struct die_info *die) } } -void +static void store_in_ref_table (unsigned int offset, struct die_info *die) { int h; @@ -5616,7 +6398,7 @@ dwarf2_get_ref_die_offset (struct attribute *attr) return result; } -struct die_info * +static struct die_info * follow_die_ref (unsigned int offset) { struct die_info *die; @@ -5703,6 +6485,7 @@ decode_locdesc (struct dwarf_block *blk, struct objfile *objfile, offreg = 0; isderef = 0; islocal = 0; + is_thread_local = 0; optimized_out = 1; while (i < size) @@ -5711,6 +6494,41 @@ decode_locdesc (struct dwarf_block *blk, struct objfile *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: @@ -5751,12 +6569,6 @@ decode_locdesc (struct dwarf_block *blk, struct objfile *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; @@ -5869,6 +6681,11 @@ decode_locdesc (struct dwarf_block *blk, struct objfile *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--; @@ -5880,7 +6697,7 @@ decode_locdesc (struct dwarf_block *blk, struct objfile *objfile, break; case DW_OP_minus: - stack[stacki - 1] = stack[stacki] - stack[stacki - 1]; + stack[stacki - 1] -= stack[stacki]; stacki--; break; @@ -5892,6 +6709,16 @@ decode_locdesc (struct dwarf_block *blk, struct objfile *objfile, complain (&dwarf2_complex_location_expr); break; + case DW_OP_GNU_push_tls_address: + is_thread_local = 1; + /* The top of the stack has the offset from the beginning + of the thread control block at which the variable is located. */ + /* Nothing should follow this operator, so the top of stack would + be returned. */ + if (i < size) + complain (&dwarf2_complex_location_expr); + break; + default: complain (&dwarf2_unsupported_stack_op, dwarf_stack_op_name (op)); return (stack[stacki]); @@ -5938,3 +6765,388 @@ dwarf_alloc_die (void) 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 == ' ') + { + complain (&dwarf2_macro_spaces_in_definition, 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 + { + complain (&dwarf2_macro_malformed_definition, 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) + complain (&dwarf2_macro_malformed_definition, + 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. */ + complain (&dwarf2_macro_malformed_definition, body); + macro_define_function (file, line, name, + argc, (const char **) argv, + p); + } + else + /* Just complain. */ + complain (&dwarf2_macro_malformed_definition, body); + } + else + /* Just complain. */ + complain (&dwarf2_macro_malformed_definition, body); + + xfree (name); + { + int i; + + for (i = 0; i < argc; i++) + xfree (argv[i]); + } + xfree (argv); + } + else + complain (&dwarf2_macro_malformed_definition, 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) + { + complain (&dwarf2_missing_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) + { + complain (&dwarf2_macros_too_long); + 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) + complain (&dwarf2_macro_outside_file, + 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) + complain (&dwarf2_macro_unmatched_end_file); + 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) + { + complain (&dwarf2_macros_too_long); + 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) + complain (&dwarf2_macros_not_terminated); + + 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); +}