diff options
Diffstat (limited to 'gdb/dwarf2read.c')
-rw-r--r-- | gdb/dwarf2read.c | 287 |
1 files changed, 151 insertions, 136 deletions
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 62f0fee2ed5..c77642d239a 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -38,10 +38,12 @@ #include "expression.h" #include "filenames.h" /* for DOSish file names */ #include "macrotab.h" - #include "language.h" #include "complaints.h" #include "bcache.h" +#include "dwarf2expr.h" +#include "dwarf2loc.h" + #include <fcntl.h> #include "gdb_string.h" #include "gdb_assert.h" @@ -905,6 +907,11 @@ static void dwarf_decode_macros (struct line_header *, unsigned int, static int attr_form_is_block (struct attribute *); +static void +dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym, + const struct comp_unit_head *, + struct objfile *objfile); + /* Try to locate the sections we need for DWARF 2 debugging information and return true if we have enough to do something. */ @@ -978,7 +985,7 @@ dwarf2_locate_sections (bfd *ignore_abfd, asection *sectp, void *ignore_ptr) { dwarf_macinfo_offset = sectp->filepos; dwarf_macinfo_size = bfd_get_section_size_before_reloc (sectp); - dwarf_loc_section = sectp; + dwarf_macinfo_section = sectp; } else if (STREQ (sectp->name, STR_SECTION)) { @@ -1218,22 +1225,24 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline) if (cu_header.version != 2) { - error ("Dwarf Error: wrong version in compilation unit header."); + error ("Dwarf Error: wrong version in compilation unit header (is %d, should be %d) [in module %s]", cu_header.version, 2, bfd_get_filename (abfd)); return; } if (cu_header.abbrev_offset >= dwarf_abbrev_size) { - error ("Dwarf Error: bad offset (0x%lx) in compilation unit header (offset 0x%lx + 6).", + error ("Dwarf Error: bad offset (0x%lx) in compilation unit header (offset 0x%lx + 6) [in module %s]", (long) cu_header.abbrev_offset, - (long) (beg_of_comp_unit - dwarf_info_buffer)); + (long) (beg_of_comp_unit - dwarf_info_buffer), + bfd_get_filename (abfd)); return; } if (beg_of_comp_unit + cu_header.length + cu_header.initial_length_size > dwarf_info_buffer + dwarf_info_size) { - error ("Dwarf Error: bad length (0x%lx) in compilation unit header (offset 0x%lx + 0).", + error ("Dwarf Error: bad length (0x%lx) in compilation unit header (offset 0x%lx + 0) [in module %s]", (long) cu_header.length, - (long) (beg_of_comp_unit - dwarf_info_buffer)); + (long) (beg_of_comp_unit - dwarf_info_buffer), + bfd_get_filename (abfd)); return; } /* Complete the cu_header */ @@ -1996,6 +2005,13 @@ read_func_scope (struct die_info *die, struct objfile *objfile, new = push_context (0, lowpc); new->name = new_symbol (die, die->type, objfile, cu_header); + + /* If there was a location expression for DW_AT_frame_base above, + record it. We still need to decode it above because not all + symbols use location expressions exclusively. */ + if (attr) + dwarf2_symbol_mark_computed (attr, new->name, cu_header, objfile); + list_in_scope = &local_symbols; if (die->has_children) @@ -2193,6 +2209,9 @@ dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc, return 0; } + range_beginning += base; + range_end += base; + /* FIXME: This is recording everything as a low-high segment of consecutive addresses. We should have a data structure for discontiguous block ranges @@ -2908,7 +2927,7 @@ read_enumeration (struct die_info *die, struct objfile *objfile, * sizeof (struct field)); } - FIELD_NAME (fields[num_fields]) = SYMBOL_NAME (sym); + FIELD_NAME (fields[num_fields]) = DEPRECATED_SYMBOL_NAME (sym); FIELD_TYPE (fields[num_fields]) = NULL; FIELD_BITPOS (fields[num_fields]) = SYMBOL_VALUE (sym); FIELD_BITSIZE (fields[num_fields]) = 0; @@ -3787,7 +3806,8 @@ read_partial_die (struct partial_die_info *part_die, bfd *abfd, abbrev = dwarf2_lookup_abbrev (abbrev_number, cu_header); if (!abbrev) { - error ("Dwarf Error: Could not find abbrev number %d.", abbrev_number); + error ("Dwarf Error: Could not find abbrev number %d [in module %s]", abbrev_number, + bfd_get_filename (abfd)); } part_die->offset = info_ptr - dwarf_info_buffer; part_die->tag = abbrev->tag; @@ -3931,7 +3951,8 @@ read_full_die (struct die_info **diep, bfd *abfd, char *info_ptr, abbrev = dwarf2_lookup_abbrev (abbrev_number, cu_header); if (!abbrev) { - error ("Dwarf Error: could not find abbrev number %d.", abbrev_number); + error ("Dwarf Error: could not find abbrev number %d [in module %s]", abbrev_number, + bfd_get_filename (abfd)); } die = dwarf_alloc_die (); die->offset = offset; @@ -4067,8 +4088,9 @@ read_attribute_value (struct attribute *attr, unsigned form, 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 (form)); + error ("Dwarf Error: Cannot handle %s in DWARF reader [in module %s]", + dwarf_form_name (form), + bfd_get_filename (abfd)); } return info_ptr; } @@ -4149,7 +4171,8 @@ read_address (bfd *abfd, char *buf, const struct comp_unit_head *cu_header, break; default: internal_error (__FILE__, __LINE__, - "read_address: bad switch, signed"); + "read_address: bad switch, signed [in module %s]", + bfd_get_filename (abfd)); } } else @@ -4167,7 +4190,8 @@ read_address (bfd *abfd, char *buf, const struct comp_unit_head *cu_header, break; default: internal_error (__FILE__, __LINE__, - "read_address: bad switch, unsigned"); + "read_address: bad switch, unsigned [in module %s]", + bfd_get_filename (abfd)); } } @@ -4282,7 +4306,8 @@ read_offset (bfd *abfd, char *buf, const struct comp_unit_head *cu_header, break; default: internal_error (__FILE__, __LINE__, - "read_offset: bad switch"); + "read_offset: bad switch [in module %s]", + bfd_get_filename (abfd)); } return retval; @@ -4324,12 +4349,14 @@ read_indirect_string (bfd *abfd, char *buf, if (dwarf_str_buffer == NULL) { - error ("DW_FORM_strp used without .debug_str section"); + error ("DW_FORM_strp used without .debug_str section [in module %s]", + bfd_get_filename (abfd)); return NULL; } if (str_offset >= dwarf_str_size) { - error ("DW_FORM_strp pointing outside of .debug_str section"); + error ("DW_FORM_strp pointing outside of .debug_str section [in module %s]", + bfd_get_filename (abfd)); return NULL; } gdb_assert (HOST_CHAR_BIT == 8); @@ -4917,6 +4944,61 @@ dwarf2_start_subfile (char *filename, char *dirname) start_subfile (filename, dirname); } +static void +var_decode_location (struct attribute *attr, struct symbol *sym, + struct objfile *objfile, + const struct comp_unit_head *cu_header) +{ + /* NOTE drow/2003-01-30: There used to be a comment and some special + code here to turn a symbol with DW_AT_external and a + SYMBOL_VALUE_ADDRESS of 0 into a LOC_UNRESOLVED symbol. This was + necessary for platforms (maybe Alpha, certainly PowerPC GNU/Linux + with some versions of binutils) where shared libraries could have + relocations against symbols in their debug information - the + minimal symbol would have the right address, but the debug info + would not. It's no longer necessary, because we will explicitly + apply relocations when we read in the debug information now. */ + + /* A DW_AT_location attribute with no contents indicates that a + variable has been optimized away. */ + if (attr_form_is_block (attr) && DW_BLOCK (attr)->size == 0) + { + SYMBOL_CLASS (sym) = LOC_OPTIMIZED_OUT; + return; + } + + /* Handle one degenerate form of location expression specially, to + preserve GDB's previous behavior when section offsets are + specified. If this is just a DW_OP_addr then mark this symbol + as LOC_STATIC. */ + + if (attr_form_is_block (attr) + && DW_BLOCK (attr)->size == 1 + cu_header->addr_size + && DW_BLOCK (attr)->data[0] == DW_OP_addr) + { + int dummy; + + SYMBOL_VALUE_ADDRESS (sym) = + read_address (objfile->obfd, DW_BLOCK (attr)->data + 1, cu_header, + &dummy); + fixup_symbol_section (sym, objfile); + SYMBOL_VALUE_ADDRESS (sym) += ANOFFSET (objfile->section_offsets, + SYMBOL_SECTION (sym)); + SYMBOL_CLASS (sym) = LOC_STATIC; + return; + } + + /* NOTE drow/2002-01-30: It might be worthwhile to have a static + expression evaluator, and use LOC_COMPUTED only when necessary + (i.e. when the value of a register or memory location is + referenced, or a thread-local block, etc.). Then again, it might + not be worthwhile. I'm assuming that it isn't unless performance + or memory numbers show me otherwise. */ + + dwarf2_symbol_mark_computed (attr, sym, cu_header, objfile); + SYMBOL_CLASS (sym) = LOC_COMPUTED; +} + /* Given a pointer to a DWARF information entry, figure out if we need to make a symbol table entry for it, and if so, create a new entry and return a pointer to it. @@ -4940,8 +5022,10 @@ new_symbol (struct die_info *die, struct type *type, struct objfile *objfile, sizeof (struct symbol)); OBJSTAT (objfile, n_syms++); memset (sym, 0, sizeof (struct symbol)); - SYMBOL_NAME (sym) = obsavestring (name, strlen (name), - &objfile->symbol_obstack); + + /* Cache this symbol's name and the name's demangled form (if any). */ + SYMBOL_LANGUAGE (sym) = cu_language; + SYMBOL_SET_NAMES (sym, name, strlen (name), objfile); /* Default assumptions. Use the passed type or decode it from the die. */ @@ -4956,15 +5040,6 @@ new_symbol (struct die_info *die, struct type *type, struct objfile *objfile, { SYMBOL_LINE (sym) = DW_UNSND (attr); } - - /* If this symbol is from a C++ compilation, then attempt to - cache the demangled form for future reference. This is a - typical time versus space tradeoff, that was decided in favor - of time because it sped up C++ symbol lookups by a factor of - about 20. */ - - SYMBOL_LANGUAGE (sym) = cu_language; - SYMBOL_INIT_DEMANGLED_NAME (sym, &objfile->symbol_obstack); switch (die->tag) { case DW_TAG_label: @@ -5012,106 +5087,12 @@ new_symbol (struct die_info *die, struct type *type, struct objfile *objfile, attr = dwarf_attr (die, DW_AT_location); if (attr) { + var_decode_location (attr, sym, objfile, cu_header); attr2 = dwarf_attr (die, DW_AT_external); if (attr2 && (DW_UNSND (attr2) != 0)) - { - /* Support the .debug_loc offsets */ - if (attr_form_is_block (attr)) - { - SYMBOL_VALUE_ADDRESS (sym) = - decode_locdesc (DW_BLOCK (attr), objfile, cu_header); - } - else if (attr->form == DW_FORM_data4 - || attr->form == DW_FORM_data8) - { - dwarf2_complex_location_expr_complaint (); - } - else - { - dwarf2_invalid_attrib_class_complaint ("DW_AT_location", - "external variable"); - } - add_symbol_to_list (sym, &global_symbols); - if (is_thread_local) - { - /* SYMBOL_VALUE_ADDRESS contains at this point the - offset of the variable within the thread local - storage. */ - SYMBOL_CLASS (sym) = LOC_THREAD_LOCAL_STATIC; - SYMBOL_OBJFILE (sym) = objfile; - } - - /* In shared libraries the address of the variable - in the location descriptor might still be relocatable, - so its value could be zero. - Enter the symbol as a LOC_UNRESOLVED symbol, if its - value is zero, the address of the variable will then - be determined from the minimal symbol table whenever - the variable is referenced. */ - else if (SYMBOL_VALUE_ADDRESS (sym)) - { - fixup_symbol_section (sym, objfile); - SYMBOL_VALUE_ADDRESS (sym) += - ANOFFSET (objfile->section_offsets, - SYMBOL_SECTION (sym)); - SYMBOL_CLASS (sym) = LOC_STATIC; - } - else - SYMBOL_CLASS (sym) = LOC_UNRESOLVED; - } + add_symbol_to_list (sym, &global_symbols); else - { - /* Support the .debug_loc offsets */ - if (attr_form_is_block (attr)) - { - SYMBOL_VALUE (sym) = addr = - decode_locdesc (DW_BLOCK (attr), objfile, cu_header); - } - else if (attr->form == DW_FORM_data4 - || attr->form == DW_FORM_data8) - { - dwarf2_complex_location_expr_complaint (); - } - else - { - dwarf2_invalid_attrib_class_complaint ("DW_AT_location", - "external variable"); - addr = 0; - } - add_symbol_to_list (sym, list_in_scope); - if (optimized_out) - { - SYMBOL_CLASS (sym) = LOC_OPTIMIZED_OUT; - } - else if (isreg) - { - SYMBOL_CLASS (sym) = LOC_REGISTER; - SYMBOL_VALUE (sym) = - DWARF2_REG_TO_REGNUM (SYMBOL_VALUE (sym)); - } - else if (offreg) - { - SYMBOL_CLASS (sym) = LOC_BASEREG; - SYMBOL_BASEREG (sym) = DWARF2_REG_TO_REGNUM (basereg); - } - else if (islocal) - { - SYMBOL_CLASS (sym) = LOC_LOCAL; - } - else if (is_thread_local) - { - SYMBOL_CLASS (sym) = LOC_THREAD_LOCAL_STATIC; - SYMBOL_OBJFILE (sym) = objfile; - } - else - { - fixup_symbol_section (sym, objfile); - SYMBOL_VALUE_ADDRESS (sym) = - addr + ANOFFSET (objfile->section_offsets, - SYMBOL_SECTION (sym)); - SYMBOL_CLASS (sym) = LOC_STATIC; - } - } + add_symbol_to_list (sym, list_in_scope); } else { @@ -5193,8 +5174,8 @@ new_symbol (struct die_info *die, struct type *type, struct objfile *objfile, SYMBOL_NAMESPACE (typedef_sym) = VAR_NAMESPACE; if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0) TYPE_NAME (SYMBOL_TYPE (sym)) = - obsavestring (SYMBOL_NAME (sym), - strlen (SYMBOL_NAME (sym)), + obsavestring (DEPRECATED_SYMBOL_NAME (sym), + strlen (DEPRECATED_SYMBOL_NAME (sym)), &objfile->type_obstack); add_symbol_to_list (typedef_sym, list_in_scope); } @@ -5239,7 +5220,7 @@ dwarf2_const_value (struct attribute *attr, struct symbol *sym, { case DW_FORM_addr: if (TYPE_LENGTH (SYMBOL_TYPE (sym)) != cu_header->addr_size) - dwarf2_const_value_length_mismatch_complaint (SYMBOL_NAME (sym), + dwarf2_const_value_length_mismatch_complaint (DEPRECATED_SYMBOL_NAME (sym), cu_header->addr_size, TYPE_LENGTH (SYMBOL_TYPE (sym))); @@ -5255,7 +5236,7 @@ dwarf2_const_value (struct attribute *attr, struct symbol *sym, case DW_FORM_block: blk = DW_BLOCK (attr); if (TYPE_LENGTH (SYMBOL_TYPE (sym)) != blk->size) - dwarf2_const_value_length_mismatch_complaint (SYMBOL_NAME (sym), + dwarf2_const_value_length_mismatch_complaint (DEPRECATED_SYMBOL_NAME (sym), blk->size, TYPE_LENGTH (SYMBOL_TYPE (sym))); @@ -5349,7 +5330,8 @@ die_type (struct die_info *die, struct objfile *objfile, type_die = follow_die_ref (ref); if (!type_die) { - error ("Dwarf Error: Cannot find referent at offset %d.", ref); + error ("Dwarf Error: Cannot find referent at offset %d [in module %s]", + ref, objfile->name); return NULL; } } @@ -5357,7 +5339,8 @@ die_type (struct die_info *die, struct objfile *objfile, if (!type) { dump_die (type_die); - error ("Dwarf Error: Problem turning type die at offset into gdb type."); + error ("Dwarf Error: Problem turning type die at offset into gdb type [in module %s]", + objfile->name); } return type; } @@ -5381,7 +5364,8 @@ die_containing_type (struct die_info *die, struct objfile *objfile, type_die = follow_die_ref (ref); if (!type_die) { - error ("Dwarf Error: Cannot find referent at offset %d.", ref); + error ("Dwarf Error: Cannot find referent at offset %d [in module %s]", ref, + objfile->name); return NULL; } type = tag_type_to_type (type_die, objfile, cu_header); @@ -5390,7 +5374,8 @@ die_containing_type (struct die_info *die, struct objfile *objfile, { if (type_die) dump_die (type_die); - error ("Dwarf Error: Problem turning containing type into gdb type."); + error ("Dwarf Error: Problem turning containing type into gdb type [in module %s]", + objfile->name); } return type; } @@ -5427,7 +5412,8 @@ tag_type_to_type (struct die_info *die, struct objfile *objfile, if (!die->type) { dump_die (die); - error ("Dwarf Error: Cannot find type of die."); + error ("Dwarf Error: Cannot find type of die [in module %s]", + objfile->name); } return die->type; } @@ -6602,8 +6588,8 @@ dwarf2_fundamental_type (struct objfile *objfile, int typeid) { if (typeid < 0 || typeid >= FT_NUM_MEMBERS) { - error ("Dwarf Error: internal error - invalid fundamental type id %d.", - typeid); + error ("Dwarf Error: internal error - invalid fundamental type id %d [in module %s]", + typeid, objfile->name); } /* Look for this particular type in the fundamental type vector. If @@ -7336,3 +7322,32 @@ attr_form_is_block (struct attribute *attr) || attr->form == DW_FORM_block4 || attr->form == DW_FORM_block); } + +static void +dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym, + const struct comp_unit_head *cu_header, + struct objfile *objfile) +{ + struct dwarf2_locexpr_baton *baton; + + /* When support for location lists is added, this will go away. */ + if (!attr_form_is_block (attr)) + { + dwarf2_complex_location_expr_complaint (); + return; + } + + baton = obstack_alloc (&objfile->symbol_obstack, + sizeof (struct dwarf2_locexpr_baton)); + baton->objfile = objfile; + + /* Note that we're just copying the block's data pointer here, not + the actual data. We're still pointing into the dwarf_info_buffer + for SYM's objfile; right now we never release that buffer, but + when we do clean up properly this may need to change. */ + baton->size = DW_BLOCK (attr)->size; + baton->data = DW_BLOCK (attr)->data; + + SYMBOL_LOCATION_FUNCS (sym) = &dwarf2_locexpr_funcs; + SYMBOL_LOCATION_BATON (sym) = baton; +} |