diff options
Diffstat (limited to 'gdb/dwarf2read.c')
-rw-r--r-- | gdb/dwarf2read.c | 160 |
1 files changed, 109 insertions, 51 deletions
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 63e0c7a..55c2412 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -43,6 +43,7 @@ #include "bcache.h" #include "dwarf2expr.h" #include "dwarf2loc.h" +#include "cp-support.h" #include <fcntl.h> #include "gdb_string.h" @@ -221,9 +222,13 @@ struct comp_unit_head struct abbrev_info *dwarf2_abbrevs[ABBREV_HASH_SIZE]; - /* Pointer to the DIE associated with the compilation unit. */ + /* Base address of this compilation unit. */ + + CORE_ADDR base_address; - struct die_info *die; + /* Non-zero if base_address has been set. */ + + int base_known; }; /* The line number information for a compilation unit (found in the @@ -396,6 +401,7 @@ static char *dwarf_line_buffer; static char *dwarf_str_buffer; static char *dwarf_macinfo_buffer; static char *dwarf_ranges_buffer; +static char *dwarf_loc_buffer; /* A zeroed version of a partial die for initialization purposes. */ static struct partial_die_info zeroed_partial_die; @@ -512,6 +518,13 @@ struct dwarf2_pinfo unsigned int dwarf_ranges_size; + /* Pointer to start of dwarf locations buffer for the objfile. */ + + char *dwarf_loc_buffer; + + /* Size of dwarf locations buffer for the objfile. */ + + unsigned int dwarf_loc_size; }; #define PST_PRIVATE(p) ((struct dwarf2_pinfo *)(p)->read_symtab_private) @@ -527,6 +540,8 @@ struct dwarf2_pinfo #define DWARF_MACINFO_SIZE(p) (PST_PRIVATE(p)->dwarf_macinfo_size) #define DWARF_RANGES_BUFFER(p) (PST_PRIVATE(p)->dwarf_ranges_buffer) #define DWARF_RANGES_SIZE(p) (PST_PRIVATE(p)->dwarf_ranges_size) +#define DWARF_LOC_BUFFER(p) (PST_PRIVATE(p)->dwarf_loc_buffer) +#define DWARF_LOC_SIZE(p) (PST_PRIVATE(p)->dwarf_loc_size) /* Maintain an array of referenced fundamental types for the current compilation unit being read. For DWARF version 1, we have to construct @@ -959,6 +974,7 @@ dwarf2_has_info (bfd *abfd) dwarf_frame_offset = 0; dwarf_eh_frame_offset = 0; dwarf_ranges_offset = 0; + dwarf_loc_offset = 0; bfd_map_over_sections (abfd, dwarf2_locate_sections, NULL); if (dwarf_info_offset && dwarf_abbrev_offset) @@ -1095,6 +1111,14 @@ dwarf2_build_psymtabs (struct objfile *objfile, int mainline) else dwarf_ranges_buffer = NULL; + if (dwarf_loc_offset) + dwarf_loc_buffer = dwarf2_read_section (objfile, + dwarf_loc_offset, + dwarf_loc_size, + dwarf_loc_section); + else + dwarf_loc_buffer = NULL; + if (mainline || (objfile->global_psymbols.size == 0 && objfile->static_psymbols.size == 0)) @@ -1316,6 +1340,8 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline) DWARF_MACINFO_SIZE (pst) = dwarf_macinfo_size; DWARF_RANGES_BUFFER (pst) = dwarf_ranges_buffer; DWARF_RANGES_SIZE (pst) = dwarf_ranges_size; + DWARF_LOC_BUFFER (pst) = dwarf_loc_buffer; + DWARF_LOC_SIZE (pst) = dwarf_loc_size; baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); /* Store the function that reads in the rest of the symbol table */ @@ -1838,6 +1864,7 @@ psymtab_to_symtab_1 (struct partial_symtab *pst) char *info_ptr; struct symtab *symtab; struct cleanup *back_to; + struct attribute *attr; /* Set local variables from the partial symbol table info. */ offset = DWARF_INFO_OFFSET (pst); @@ -1852,6 +1879,8 @@ psymtab_to_symtab_1 (struct partial_symtab *pst) dwarf_macinfo_size = DWARF_MACINFO_SIZE (pst); dwarf_ranges_buffer = DWARF_RANGES_BUFFER (pst); dwarf_ranges_size = DWARF_RANGES_SIZE (pst); + dwarf_loc_buffer = DWARF_LOC_BUFFER (pst); + dwarf_loc_size = DWARF_LOC_SIZE (pst); baseaddr = ANOFFSET (pst->section_offsets, SECT_OFF_TEXT (objfile)); cu_header_offset = offset; info_ptr = dwarf_info_buffer + offset; @@ -1876,8 +1905,32 @@ psymtab_to_symtab_1 (struct partial_symtab *pst) make_cleanup_free_die_list (dies); + /* Find the base address of the compilation unit for range lists and + location lists. It will normally be specified by DW_AT_low_pc. + In DWARF-3 draft 4, the base address could be overridden by + DW_AT_entry_pc. It's been removed, but GCC still uses this for + compilation units with discontinuous ranges. */ + + cu_header.base_known = 0; + cu_header.base_address = 0; + + attr = dwarf_attr (dies, DW_AT_entry_pc); + if (attr) + { + cu_header.base_address = DW_ADDR (attr); + cu_header.base_known = 1; + } + else + { + attr = dwarf_attr (dies, DW_AT_low_pc); + if (attr) + { + cu_header.base_address = DW_ADDR (attr); + cu_header.base_known = 1; + } + } + /* Do line number decoding in read_file_scope () */ - cu_header.die = dies; process_die (dies, objfile, &cu_header); if (!dwarf2_get_pc_bounds (dies, &lowpc, &highpc, objfile, &cu_header)) @@ -2355,40 +2408,18 @@ dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc, .debug_renges section. */ unsigned int offset = DW_UNSND (attr); /* Base address selection entry. */ - CORE_ADDR base = 0; - int found_base = 0; + CORE_ADDR base; + int found_base; int dummy; unsigned int i; char *buffer; CORE_ADDR marker; int low_set; - /* The applicable base address is determined by (1) the closest - preceding base address selection entry in the range list or - (2) the DW_AT_low_pc of the compilation unit. */ - - /* ??? Was in dwarf3 draft4, and has since been removed. - GCC still uses it though. */ - attr = dwarf_attr (cu_header->die, DW_AT_entry_pc); - if (attr) - { - base = DW_ADDR (attr); - found_base = 1; - } - - if (!found_base) - { - attr = dwarf_attr (cu_header->die, DW_AT_low_pc); - if (attr) - { - base = DW_ADDR (attr); - found_base = 1; - } - } - + found_base = cu_header->base_known; + base = cu_header->base_address; buffer = dwarf_ranges_buffer + offset; - /* Read in the largest possible address. */ marker = read_address (obfd, buffer, cu_header, &dummy); if ((marker & mask) == mask) @@ -3490,7 +3521,7 @@ read_namespace (struct die_info *die, struct objfile *objfile, } else { - /* We need temp_name around because processing_current_namespace + /* We need temp_name around because processing_current_prefix is a const char *. */ char *temp_name = alloca (strlen (previous_prefix) + 2 + strlen(name) + 1); @@ -3505,9 +3536,9 @@ read_namespace (struct die_info *die, struct objfile *objfile, time, add a using directive. */ if (is_anonymous && dwarf_attr (die, DW_AT_extension) == NULL) - add_using_directive (processing_current_prefix, - strlen (previous_prefix), - strlen (processing_current_prefix)); + cp_add_using_directive (processing_current_prefix, + strlen (previous_prefix), + strlen (processing_current_prefix)); if (die->has_children) { @@ -7778,26 +7809,53 @@ 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)) + if (attr->form == DW_FORM_data4 || attr->form == DW_FORM_data8) { - dwarf2_complex_location_expr_complaint (); - return; - } + struct dwarf2_loclist_baton *baton; - baton = obstack_alloc (&objfile->symbol_obstack, - sizeof (struct dwarf2_locexpr_baton)); - baton->objfile = objfile; + baton = obstack_alloc (&objfile->symbol_obstack, + sizeof (struct dwarf2_loclist_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; + /* We don't know how long the location list is, but make sure we + don't run off the edge of the section. */ + baton->size = dwarf_loc_size - DW_UNSND (attr); + baton->data = dwarf_loc_buffer + DW_UNSND (attr); + baton->base_address = cu_header->base_address; + if (cu_header->base_known == 0) + complaint (&symfile_complaints, + "Location list used without specifying the CU base address."); - SYMBOL_LOCATION_FUNCS (sym) = &dwarf2_locexpr_funcs; - SYMBOL_LOCATION_BATON (sym) = baton; + SYMBOL_LOCATION_FUNCS (sym) = &dwarf2_loclist_funcs; + SYMBOL_LOCATION_BATON (sym) = baton; + } + else + { + struct dwarf2_locexpr_baton *baton; + + baton = obstack_alloc (&objfile->symbol_obstack, + sizeof (struct dwarf2_locexpr_baton)); + baton->objfile = objfile; + + if (attr_form_is_block (attr)) + { + /* Note that we're just copying the block's data pointer + here, not the actual data. We're still pointing into the + dwarf_info_buffer for SYM's objfile; right now we never + release that buffer, but when we do clean up properly + this may need to change. */ + baton->size = DW_BLOCK (attr)->size; + baton->data = DW_BLOCK (attr)->data; + } + else + { + dwarf2_invalid_attrib_class_complaint ("location description", + SYMBOL_NATURAL_NAME (sym)); + baton->size = 0; + baton->data = NULL; + } + + SYMBOL_LOCATION_FUNCS (sym) = &dwarf2_locexpr_funcs; + SYMBOL_LOCATION_BATON (sym) = baton; + } } |