diff options
-rw-r--r-- | gdb/ChangeLog | 28 | ||||
-rw-r--r-- | gdb/dwarf2read.c | 714 |
2 files changed, 430 insertions, 312 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 3c0f578..ed766f8 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,31 @@ +2009-07-15 Doug Evans <dje@google.com> + + Code reorg in preparation for adding comdat types support. + * dwarf2read.c (struct die_reader_specs): New struct. + (locate_pdi_sibling): New arg buffer. All callers updated. + (load_partial_dies, read_partial_die): Ditto. + (read_8_bytes): Change return type to ULONGEST. + (read_comp_unit): Delete arg abfd. All callers updated. + (read_die_and_children_1): Delete args abfd, cu. New arg reader. + All callers updated. + (read_die_and_children, read_die_and_siblings): Ditto. + (read_full_die): Ditto. Move closer to callers. + (skip_one_die): New arg buffer. All callers updated. + (load_full_comp_unit): Change return type to void. All callers + updated. + (partial_read_comp_unit_head): New args buffer, buffer_size. + All callers updated. + (process_psymtab_comp_unit): New function, split out from + dwarf2_build_psymtabs_hard. + (dwarf2_build_psymtabs_hard): Call it. + (load_partial_comp_unit): Renamed from load_comp_unit. + All callers updated. + (skip_children): New arg buffer. All callers updated. + (init_cu_die_reader): New function. + (is_ref_attr): New function. + (dwarf2_get_ref_die_offset): Call it. + (alloc_one_comp_unit): New function. + 2009-07-14 Stan Shebs <stan@codesourcery.com> * MAINTAINERS (Global Maintainers): Add Doug Evans. diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 8b485bd..d294aea 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -373,6 +373,25 @@ struct dwarf2_per_cu_data struct partial_symtab *psymtab; }; +/* Struct used to pass misc. parameters to read_die_and_children, et. al. + which are used for both .debug_info and .debug_types dies. + All parameters here are unchanging for the life of the call. + This struct exists to abstract away the constant parameters of + die reading. */ + +struct die_reader_specs +{ + /* The bfd of this objfile. */ + bfd* abfd; + + /* The CU of the DIE we are parsing. */ + struct dwarf2_cu *cu; + + /* Pointer to start of section buffer. + This is either the start of .debug_info or .debug_types. */ + const gdb_byte *buffer; +}; + /* 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. */ @@ -467,7 +486,7 @@ struct partial_die_info CORE_ADDR lowpc; CORE_ADDR highpc; - /* Pointer into the info_buffer pointing at the target of + /* Pointer into the info_buffer (or types_buffer) pointing at the target of DW_AT_sibling, if any. */ gdb_byte *sibling; @@ -538,7 +557,7 @@ struct die_info /* Abbrev number */ unsigned int abbrev; - /* Offset in .debug_info section */ + /* Offset in .debug_info or .debug_types section. */ unsigned int offset; /* The dies in a compilation unit form an n-ary tree. PARENT @@ -773,9 +792,8 @@ static void add_partial_subprogram (struct partial_die_info *pdi, int need_pc, struct dwarf2_cu *cu); static gdb_byte *locate_pdi_sibling (struct partial_die_info *orig_pdi, - gdb_byte *info_ptr, - bfd *abfd, - struct dwarf2_cu *cu); + gdb_byte *buffer, gdb_byte *info_ptr, + bfd *abfd, struct dwarf2_cu *cu); static void dwarf2_psymtab_to_symtab (struct partial_symtab *); @@ -791,12 +809,15 @@ static struct abbrev_info *peek_die_abbrev (gdb_byte *, unsigned int *, static struct abbrev_info *dwarf2_lookup_abbrev (unsigned int, struct dwarf2_cu *); -static struct partial_die_info *load_partial_dies (bfd *, gdb_byte *, int, - struct dwarf2_cu *); +static struct partial_die_info *load_partial_dies (bfd *, + gdb_byte *, gdb_byte *, + int, struct dwarf2_cu *); static gdb_byte *read_partial_die (struct partial_die_info *, - struct abbrev_info *abbrev, unsigned int, - bfd *, gdb_byte *, struct dwarf2_cu *); + struct abbrev_info *abbrev, + unsigned int, bfd *, + gdb_byte *, gdb_byte *, + struct dwarf2_cu *); static struct partial_die_info *find_partial_die (unsigned int, struct dwarf2_cu *); @@ -804,9 +825,6 @@ static struct partial_die_info *find_partial_die (unsigned int, static void fixup_partial_die (struct partial_die_info *, struct dwarf2_cu *); -static gdb_byte *read_full_die (struct die_info **, bfd *, gdb_byte *, - struct dwarf2_cu *, int *); - static gdb_byte *read_attribute (struct attribute *, struct attr_abbrev *, bfd *, gdb_byte *, struct dwarf2_cu *); @@ -821,7 +839,7 @@ static unsigned int read_2_bytes (bfd *, gdb_byte *); static unsigned int read_4_bytes (bfd *, gdb_byte *); -static unsigned long read_8_bytes (bfd *, gdb_byte *); +static ULONGEST read_8_bytes (bfd *, gdb_byte *); static CORE_ADDR read_address (bfd *, gdb_byte *ptr, struct dwarf2_cu *, unsigned int *); @@ -959,23 +977,27 @@ static CORE_ADDR decode_locdesc (struct dwarf_block *, struct dwarf2_cu *); static enum dwarf_array_dim_ordering read_array_order (struct die_info *, struct dwarf2_cu *); -static struct die_info *read_comp_unit (gdb_byte *, bfd *, struct dwarf2_cu *); +static struct die_info *read_comp_unit (gdb_byte *, struct dwarf2_cu *); -static struct die_info *read_die_and_children_1 (gdb_byte *info_ptr, bfd *abfd, - struct dwarf2_cu *, +static struct die_info *read_die_and_children_1 (const struct die_reader_specs *reader, + gdb_byte *info_ptr, gdb_byte **new_info_ptr, struct die_info *parent); -static struct die_info *read_die_and_children (gdb_byte *info_ptr, bfd *abfd, - struct dwarf2_cu *, +static struct die_info *read_die_and_children (const struct die_reader_specs *reader, + gdb_byte *info_ptr, gdb_byte **new_info_ptr, struct die_info *parent); -static struct die_info *read_die_and_siblings (gdb_byte *info_ptr, bfd *abfd, - struct dwarf2_cu *, +static struct die_info *read_die_and_siblings (const struct die_reader_specs *reader, + gdb_byte *info_ptr, gdb_byte **new_info_ptr, struct die_info *parent); +static gdb_byte *read_full_die (const struct die_reader_specs *reader, + struct die_info **, gdb_byte *, + int *); + static void process_die (struct die_info *, struct dwarf2_cu *); static char *dwarf2_linkage_name (struct die_info *, struct dwarf2_cu *); @@ -1018,6 +1040,8 @@ static void dump_die_1 (struct ui_file *, int level, int max_level, static void store_in_ref_table (struct die_info *, struct dwarf2_cu *); +static int is_ref_attr (struct attribute *); + static unsigned int dwarf2_get_ref_die_offset (struct attribute *); static int dwarf2_get_attr_constant_value (struct attribute *, int); @@ -1052,8 +1076,9 @@ static void dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym, struct dwarf2_cu *cu); -static gdb_byte *skip_one_die (gdb_byte *info_ptr, struct abbrev_info *abbrev, - struct dwarf2_cu *cu); +static gdb_byte *skip_one_die (gdb_byte *buffer, gdb_byte *info_ptr, + struct abbrev_info *abbrev, + struct dwarf2_cu *cu); static void free_stack_comp_unit (void *); @@ -1067,6 +1092,8 @@ static struct dwarf2_per_cu_data *dwarf2_find_containing_comp_unit static struct dwarf2_per_cu_data *dwarf2_find_comp_unit (unsigned int offset, struct objfile *objfile); +static struct dwarf2_cu *alloc_one_comp_unit (struct objfile *objfile); + static void free_one_comp_unit (void *); static void free_cached_comp_units (void *); @@ -1080,8 +1107,8 @@ static struct type *set_die_type (struct die_info *, struct type *, static void create_all_comp_units (struct objfile *); -static struct dwarf2_cu *load_full_comp_unit (struct dwarf2_per_cu_data *, - struct objfile *); +static void load_full_comp_unit (struct dwarf2_per_cu_data *, + struct objfile *); static void process_full_comp_unit (struct dwarf2_per_cu_data *); @@ -1464,8 +1491,9 @@ offset_in_cu_p (const struct comp_unit_head *cu_header, unsigned int offset) return (offset >= bottom && offset < top); } -/* Read in the comp unit header information from the debug_info at - info_ptr. */ +/* Read in the comp unit header information from the debug_info at info_ptr. + NOTE: This leaves members offset, first_die_offset to be filled in + by the caller. */ static gdb_byte * read_comp_unit_head (struct comp_unit_head *cu_header, @@ -1496,6 +1524,7 @@ read_comp_unit_head (struct comp_unit_head *cu_header, static gdb_byte * partial_read_comp_unit_head (struct comp_unit_head *header, gdb_byte *info_ptr, + gdb_byte *buffer, unsigned int buffer_size, bfd *abfd) { gdb_byte *beg_of_comp_unit = info_ptr; @@ -1511,15 +1540,15 @@ partial_read_comp_unit_head (struct comp_unit_head *header, gdb_byte *info_ptr, error (_("Dwarf Error: bad offset (0x%lx) in compilation unit header " "(offset 0x%lx + 6) [in module %s]"), (long) header->abbrev_offset, - (long) (beg_of_comp_unit - dwarf2_per_objfile->info.buffer), + (long) (beg_of_comp_unit - buffer), bfd_get_filename (abfd)); if (beg_of_comp_unit + header->length + header->initial_length_size - > dwarf2_per_objfile->info.buffer + dwarf2_per_objfile->info.size) + > buffer + buffer_size) error (_("Dwarf Error: bad length (0x%lx) in compilation unit header " "(offset 0x%lx + 0) [in module %s]"), (long) header->length, - (long) (beg_of_comp_unit - dwarf2_per_objfile->info.buffer), + (long) (beg_of_comp_unit - buffer), bfd_get_filename (abfd)); return info_ptr; @@ -1584,204 +1613,226 @@ dwarf2_build_include_psymtabs (struct dwarf2_cu *cu, free_line_header (lh); } +/* Subroutine of dwarf2_build_psymtabs_hard to simplify it. + Process a compilation unit for a psymtab. + BUFFER is a pointer to the beginning of the dwarf section buffer. + INFO_PTR is a pointer to the start of the CU. + Returns a pointer to the next CU. */ -/* Build the partial symbol table by doing a quick pass through the - .debug_info and .debug_abbrev sections. */ - -static void -dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline) +static gdb_byte * +process_psymtab_comp_unit (struct objfile *objfile, + struct dwarf2_per_cu_data *this_cu, + gdb_byte *buffer, gdb_byte *info_ptr, + unsigned int buffer_size) { - /* Instead of reading this into a big buffer, we should probably use - mmap() on architectures that support it. (FIXME) */ bfd *abfd = objfile->obfd; - gdb_byte *info_ptr; - gdb_byte *beg_of_comp_unit; + gdb_byte *beg_of_comp_unit = info_ptr; struct partial_die_info comp_unit_die; struct partial_symtab *pst; - struct cleanup *back_to; CORE_ADDR baseaddr; + struct cleanup *back_to_inner; + struct dwarf2_cu cu; + struct abbrev_info *abbrev; + unsigned int bytes_read; - info_ptr = dwarf2_per_objfile->info.buffer; + memset (&cu, 0, sizeof (cu)); + cu.objfile = objfile; + obstack_init (&cu.comp_unit_obstack); - /* Any cached compilation units will be linked by the per-objfile - read_in_chain. Make sure to free them when we're done. */ - back_to = make_cleanup (free_cached_comp_units, NULL); + back_to_inner = make_cleanup (free_stack_comp_unit, &cu); - create_all_comp_units (objfile); + info_ptr = partial_read_comp_unit_head (&cu.header, info_ptr, + buffer, buffer_size, + abfd); - objfile->psymtabs_addrmap = addrmap_create_mutable - (&objfile->objfile_obstack); + /* Complete the cu_header. */ + cu.header.offset = beg_of_comp_unit - buffer; + cu.header.first_die_offset = info_ptr - beg_of_comp_unit; - /* Since the objects we're extracting from .debug_info vary in - length, only the individual functions to extract them (like - read_comp_unit_head and load_partial_die) can really know whether - the buffer is large enough to hold another complete object. + cu.list_in_scope = &file_symbols; - At the moment, they don't actually check that. If .debug_info - 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. + /* Read the abbrevs for this compilation unit into a table. */ + dwarf2_read_abbrevs (abfd, &cu); + make_cleanup (dwarf2_free_abbrev_table, &cu); - For this loop condition, simply checking whether there's any data - left at all should be sufficient. */ - while (info_ptr < (dwarf2_per_objfile->info.buffer - + dwarf2_per_objfile->info.size)) + /* Read the compilation unit die. */ + abbrev = peek_die_abbrev (info_ptr, &bytes_read, &cu); + info_ptr = read_partial_die (&comp_unit_die, abbrev, bytes_read, abfd, + buffer, info_ptr, &cu); + + if (comp_unit_die.tag == DW_TAG_partial_unit) { - struct cleanup *back_to_inner; - struct dwarf2_cu cu; - struct abbrev_info *abbrev; - unsigned int bytes_read; - struct dwarf2_per_cu_data *this_cu; + info_ptr = (beg_of_comp_unit + cu.header.length + + cu.header.initial_length_size); + do_cleanups (back_to_inner); + return info_ptr; + } - beg_of_comp_unit = info_ptr; + /* Set the language we're debugging. */ + set_cu_language (comp_unit_die.language, &cu); - memset (&cu, 0, sizeof (cu)); + /* Allocate a new partial symbol table structure. */ + pst = start_psymtab_common (objfile, objfile->section_offsets, + comp_unit_die.name ? comp_unit_die.name : "", + /* TEXTLOW and TEXTHIGH are set below. */ + 0, + objfile->global_psymbols.next, + objfile->static_psymbols.next); - obstack_init (&cu.comp_unit_obstack); + if (comp_unit_die.dirname) + pst->dirname = obsavestring (comp_unit_die.dirname, + strlen (comp_unit_die.dirname), + &objfile->objfile_obstack); - back_to_inner = make_cleanup (free_stack_comp_unit, &cu); + pst->read_symtab_private = (char *) this_cu; - cu.objfile = objfile; - info_ptr = partial_read_comp_unit_head (&cu.header, info_ptr, abfd); + baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); - /* Complete the cu_header */ - cu.header.offset = beg_of_comp_unit - dwarf2_per_objfile->info.buffer; - cu.header.first_die_offset = info_ptr - beg_of_comp_unit; + /* Store the function that reads in the rest of the symbol table */ + pst->read_symtab = dwarf2_psymtab_to_symtab; - cu.list_in_scope = &file_symbols; + /* If this compilation unit was already read in, free the + cached copy in order to read it in again. This is + necessary because we skipped some symbols when we first + read in the compilation unit (see load_partial_dies). + This problem could be avoided, but the benefit is + unclear. */ + if (this_cu->cu != NULL) + free_one_cached_comp_unit (this_cu->cu); - /* Read the abbrevs for this compilation unit into a table */ - dwarf2_read_abbrevs (abfd, &cu); - make_cleanup (dwarf2_free_abbrev_table, &cu); + cu.per_cu = this_cu; - this_cu = dwarf2_find_comp_unit (cu.header.offset, objfile); + /* Note that this is a pointer to our stack frame, being + added to a global data structure. It will be cleaned up + in free_stack_comp_unit when we finish with this + compilation unit. */ + this_cu->cu = &cu; - /* Read the compilation unit die */ - abbrev = peek_die_abbrev (info_ptr, &bytes_read, &cu); - info_ptr = read_partial_die (&comp_unit_die, abbrev, bytes_read, - abfd, info_ptr, &cu); + this_cu->psymtab = pst; - if (comp_unit_die.tag == DW_TAG_partial_unit) - { - info_ptr = (beg_of_comp_unit + cu.header.length - + cu.header.initial_length_size); - do_cleanups (back_to_inner); - continue; - } + /* Possibly set the default values of LOWPC and HIGHPC from + `DW_AT_ranges'. */ + if (cu.has_ranges_offset) + { + if (dwarf2_ranges_read (cu.ranges_offset, &comp_unit_die.lowpc, + &comp_unit_die.highpc, &cu, pst)) + comp_unit_die.has_pc_info = 1; + } + else if (comp_unit_die.has_pc_info + && comp_unit_die.lowpc < comp_unit_die.highpc) + /* Store the contiguous range if it is not empty; it can be empty for + CUs with no code. */ + addrmap_set_empty (objfile->psymtabs_addrmap, + comp_unit_die.lowpc + baseaddr, + comp_unit_die.highpc + baseaddr - 1, pst); + + /* Check if comp unit has_children. + If so, read the rest of the partial symbols from this comp unit. + If not, there's no more debug_info for this comp unit. */ + if (comp_unit_die.has_children) + { + struct partial_die_info *first_die; + CORE_ADDR lowpc, highpc; - /* Set the language we're debugging */ - set_cu_language (comp_unit_die.language, &cu); + lowpc = ((CORE_ADDR) -1); + highpc = ((CORE_ADDR) 0); - /* Allocate a new partial symbol table structure */ - pst = start_psymtab_common (objfile, objfile->section_offsets, - comp_unit_die.name ? comp_unit_die.name : "", - /* TEXTLOW and TEXTHIGH are set below. */ - 0, - objfile->global_psymbols.next, - objfile->static_psymbols.next); + first_die = load_partial_dies (abfd, buffer, info_ptr, 1, &cu); - if (comp_unit_die.dirname) - pst->dirname = obsavestring (comp_unit_die.dirname, - strlen (comp_unit_die.dirname), - &objfile->objfile_obstack); + scan_partial_symbols (first_die, &lowpc, &highpc, + ! comp_unit_die.has_pc_info, &cu); - pst->read_symtab_private = (char *) this_cu; + /* If we didn't find a lowpc, set it to highpc to avoid + complaints from `maint check'. */ + if (lowpc == ((CORE_ADDR) -1)) + lowpc = highpc; - baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + /* If the compilation unit didn't have an explicit address range, + then use the information extracted from its child dies. */ + if (! comp_unit_die.has_pc_info) + { + comp_unit_die.lowpc = lowpc; + comp_unit_die.highpc = highpc; + } + } + pst->textlow = comp_unit_die.lowpc + baseaddr; + pst->texthigh = comp_unit_die.highpc + baseaddr; - /* Store the function that reads in the rest of the symbol table */ - pst->read_symtab = dwarf2_psymtab_to_symtab; + pst->n_global_syms = objfile->global_psymbols.next - + (objfile->global_psymbols.list + pst->globals_offset); + pst->n_static_syms = objfile->static_psymbols.next - + (objfile->static_psymbols.list + pst->statics_offset); + sort_pst_symbols (pst); - /* If this compilation unit was already read in, free the - cached copy in order to read it in again. This is - necessary because we skipped some symbols when we first - read in the compilation unit (see load_partial_dies). - This problem could be avoided, but the benefit is - unclear. */ - if (this_cu->cu != NULL) - free_one_cached_comp_unit (this_cu->cu); + /* If there is already a psymtab or symtab for a file of this + name, remove it. (If there is a symtab, more drastic things + also happen.) This happens in VxWorks. */ + free_named_symtabs (pst->filename); - cu.per_cu = this_cu; + info_ptr = (beg_of_comp_unit + cu.header.length + + cu.header.initial_length_size); - /* Note that this is a pointer to our stack frame, being - added to a global data structure. It will be cleaned up - in free_stack_comp_unit when we finish with this - compilation unit. */ - this_cu->cu = &cu; + if (comp_unit_die.has_stmt_list) + { + /* Get the list of files included in the current compilation unit, + and build a psymtab for each of them. */ + dwarf2_build_include_psymtabs (&cu, &comp_unit_die, pst); + } - this_cu->psymtab = pst; + do_cleanups (back_to_inner); - /* Possibly set the default values of LOWPC and HIGHPC from - `DW_AT_ranges'. */ - if (cu.has_ranges_offset) - { - if (dwarf2_ranges_read (cu.ranges_offset, &comp_unit_die.lowpc, - &comp_unit_die.highpc, &cu, pst)) - comp_unit_die.has_pc_info = 1; - } - else if (comp_unit_die.has_pc_info - && comp_unit_die.lowpc < comp_unit_die.highpc) - /* Store the contiguous range if it is not empty; it can be empty for - CUs with no code. */ - addrmap_set_empty (objfile->psymtabs_addrmap, - comp_unit_die.lowpc + baseaddr, - comp_unit_die.highpc + baseaddr - 1, pst); + return info_ptr; +} - /* Check if comp unit has_children. - If so, read the rest of the partial symbols from this comp unit. - If not, there's no more debug_info for this comp unit. */ - if (comp_unit_die.has_children) - { - struct partial_die_info *first_die; - CORE_ADDR lowpc, highpc; +/* Build the partial symbol table by doing a quick pass through the + .debug_info and .debug_abbrev sections. */ - lowpc = ((CORE_ADDR) -1); - highpc = ((CORE_ADDR) 0); +static void +dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline) +{ + /* Instead of reading this into a big buffer, we should probably use + mmap() on architectures that support it. (FIXME) */ + bfd *abfd = objfile->obfd; + gdb_byte *info_ptr; + struct cleanup *back_to; + + info_ptr = dwarf2_per_objfile->info.buffer; - first_die = load_partial_dies (abfd, info_ptr, 1, &cu); + /* Any cached compilation units will be linked by the per-objfile + read_in_chain. Make sure to free them when we're done. */ + back_to = make_cleanup (free_cached_comp_units, NULL); - scan_partial_symbols (first_die, &lowpc, &highpc, - ! comp_unit_die.has_pc_info, &cu); + create_all_comp_units (objfile); - /* If we didn't find a lowpc, set it to highpc to avoid - complaints from `maint check'. */ - if (lowpc == ((CORE_ADDR) -1)) - lowpc = highpc; + objfile->psymtabs_addrmap = + addrmap_create_mutable (&objfile->objfile_obstack); - /* If the compilation unit didn't have an explicit address range, - then use the information extracted from its child dies. */ - if (! comp_unit_die.has_pc_info) - { - comp_unit_die.lowpc = lowpc; - comp_unit_die.highpc = highpc; - } - } - pst->textlow = comp_unit_die.lowpc + baseaddr; - pst->texthigh = comp_unit_die.highpc + baseaddr; + /* Since the objects we're extracting from .debug_info vary in + length, only the individual functions to extract them (like + read_comp_unit_head and load_partial_die) can really know whether + the buffer is large enough to hold another complete object. - pst->n_global_syms = objfile->global_psymbols.next - - (objfile->global_psymbols.list + pst->globals_offset); - pst->n_static_syms = objfile->static_psymbols.next - - (objfile->static_psymbols.list + pst->statics_offset); - sort_pst_symbols (pst); + At the moment, they don't actually check that. If .debug_info + 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. - /* If there is already a psymtab or symtab for a file of this - name, remove it. (If there is a symtab, more drastic things - also happen.) This happens in VxWorks. */ - free_named_symtabs (pst->filename); + For this loop condition, simply checking whether there's any data + left at all should be sufficient. */ - info_ptr = beg_of_comp_unit + cu.header.length - + cu.header.initial_length_size; + while (info_ptr < (dwarf2_per_objfile->info.buffer + + dwarf2_per_objfile->info.size)) + { + struct dwarf2_per_cu_data *this_cu; - if (comp_unit_die.has_stmt_list) - { - /* Get the list of files included in the current compilation unit, - and build a psymtab for each of them. */ - dwarf2_build_include_psymtabs (&cu, &comp_unit_die, pst); - } + this_cu = dwarf2_find_comp_unit (info_ptr - dwarf2_per_objfile->info.buffer, + objfile); - do_cleanups (back_to_inner); + info_ptr = process_psymtab_comp_unit (objfile, this_cu, + dwarf2_per_objfile->info.buffer, + info_ptr, + dwarf2_per_objfile->info.size); } objfile->psymtabs_addrmap = addrmap_create_fixed (objfile->psymtabs_addrmap, @@ -1790,10 +1841,11 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline) do_cleanups (back_to); } -/* Load the DIEs for a secondary CU into memory. */ +/* Load the partial DIEs for a secondary CU into memory. */ static void -load_comp_unit (struct dwarf2_per_cu_data *this_cu, struct objfile *objfile) +load_partial_comp_unit (struct dwarf2_per_cu_data *this_cu, + struct objfile *objfile) { bfd *abfd = objfile->obfd; gdb_byte *info_ptr, *beg_of_comp_unit; @@ -1806,16 +1858,17 @@ load_comp_unit (struct dwarf2_per_cu_data *this_cu, struct objfile *objfile) info_ptr = dwarf2_per_objfile->info.buffer + this_cu->offset; beg_of_comp_unit = info_ptr; - cu = xmalloc (sizeof (struct dwarf2_cu)); - memset (cu, 0, sizeof (struct dwarf2_cu)); + cu = alloc_one_comp_unit (objfile); - obstack_init (&cu->comp_unit_obstack); + /* ??? Missing cleanup for CU? */ - cu->objfile = objfile; - info_ptr = partial_read_comp_unit_head (&cu->header, info_ptr, abfd); + info_ptr = partial_read_comp_unit_head (&cu->header, info_ptr, + dwarf2_per_objfile->info.buffer, + dwarf2_per_objfile->info.size, + abfd); /* Complete the cu_header. */ - cu->header.offset = beg_of_comp_unit - dwarf2_per_objfile->info.buffer; + cu->header.offset = this_cu->offset; cu->header.first_die_offset = info_ptr - beg_of_comp_unit; /* Read the abbrevs for this compilation unit into a table. */ @@ -1824,8 +1877,8 @@ load_comp_unit (struct dwarf2_per_cu_data *this_cu, struct objfile *objfile) /* Read the compilation unit die. */ abbrev = peek_die_abbrev (info_ptr, &bytes_read, cu); - info_ptr = read_partial_die (&comp_unit_die, abbrev, bytes_read, - abfd, info_ptr, cu); + info_ptr = read_partial_die (&comp_unit_die, abbrev, bytes_read, abfd, + dwarf2_per_objfile->info.buffer, info_ptr, cu); /* Set the language we're debugging. */ set_cu_language (comp_unit_die.language, cu); @@ -1833,13 +1886,13 @@ load_comp_unit (struct dwarf2_per_cu_data *this_cu, struct objfile *objfile) /* Link this compilation unit into the compilation unit tree. */ this_cu->cu = cu; cu->per_cu = this_cu; - cu->type_hash = cu->per_cu->type_hash; + cu->type_hash = this_cu->type_hash; /* Check if comp unit has_children. If so, read the rest of the partial symbols from this comp unit. If not, there's no more debug_info for this comp unit. */ if (comp_unit_die.has_children) - load_partial_dies (abfd, info_ptr, 0, cu); + load_partial_dies (abfd, dwarf2_per_objfile->info.buffer, info_ptr, 0, cu); do_cleanups (back_to); } @@ -2470,12 +2523,12 @@ peek_die_abbrev (gdb_byte *info_ptr, unsigned int *bytes_read, return abbrev; } -/* Scan the debug information for CU starting at INFO_PTR. Returns a - pointer to the end of a series of DIEs, terminated by an empty +/* Scan the debug information for CU starting at INFO_PTR in buffer BUFFER. + Returns a pointer to the end of a series of DIEs, terminated by an empty DIE. Any children of the skipped DIEs will also be skipped. */ static gdb_byte * -skip_children (gdb_byte *info_ptr, struct dwarf2_cu *cu) +skip_children (gdb_byte *buffer, gdb_byte *info_ptr, struct dwarf2_cu *cu) { struct abbrev_info *abbrev; unsigned int bytes_read; @@ -2486,19 +2539,19 @@ skip_children (gdb_byte *info_ptr, struct dwarf2_cu *cu) if (abbrev == NULL) return info_ptr + bytes_read; else - info_ptr = skip_one_die (info_ptr + bytes_read, abbrev, cu); + info_ptr = skip_one_die (buffer, info_ptr + bytes_read, abbrev, cu); } } -/* Scan the debug information for CU starting at INFO_PTR. INFO_PTR - should point just after the initial uleb128 of a DIE, and the +/* Scan the debug information for CU starting at INFO_PTR in buffer BUFFER. + INFO_PTR should point just after the initial uleb128 of a DIE, and the abbrev corresponding to that skipped uleb128 should be passed in ABBREV. Returns a pointer to this DIE's sibling, skipping any children. */ static gdb_byte * -skip_one_die (gdb_byte *info_ptr, struct abbrev_info *abbrev, - struct dwarf2_cu *cu) +skip_one_die (gdb_byte *buffer, gdb_byte *info_ptr, + struct abbrev_info *abbrev, struct dwarf2_cu *cu) { unsigned int bytes_read; struct attribute attr; @@ -2515,8 +2568,7 @@ skip_one_die (gdb_byte *info_ptr, struct abbrev_info *abbrev, if (attr.form == DW_FORM_ref_addr) complaint (&symfile_complaints, _("ignoring absolute DW_AT_sibling")); else - return dwarf2_per_objfile->info.buffer - + dwarf2_get_ref_die_offset (&attr); + return buffer + dwarf2_get_ref_die_offset (&attr); } /* If it isn't DW_AT_sibling, skip this attribute. */ @@ -2585,16 +2637,18 @@ skip_one_die (gdb_byte *info_ptr, struct abbrev_info *abbrev, } if (abbrev->has_children) - return skip_children (info_ptr, cu); + return skip_children (buffer, info_ptr, cu); else return info_ptr; } -/* Locate ORIG_PDI's sibling; INFO_PTR should point to the start of - the next DIE after ORIG_PDI. */ +/* Locate ORIG_PDI's sibling. + INFO_PTR should point to the start of the next DIE after ORIG_PDI + in BUFFER. */ static gdb_byte * -locate_pdi_sibling (struct partial_die_info *orig_pdi, gdb_byte *info_ptr, +locate_pdi_sibling (struct partial_die_info *orig_pdi, + gdb_byte *buffer, gdb_byte *info_ptr, bfd *abfd, struct dwarf2_cu *cu) { /* Do we know the sibling already? */ @@ -2609,7 +2663,7 @@ locate_pdi_sibling (struct partial_die_info *orig_pdi, gdb_byte *info_ptr, /* Skip the children the long way. */ - return skip_children (info_ptr, cu); + return skip_children (buffer, info_ptr, cu); } /* Expand this partial symbol table into a full symbol table. */ @@ -2785,15 +2839,15 @@ psymtab_to_symtab_1 (struct partial_symtab *pst) do_cleanups (back_to); } -/* Load the DIEs associated with PST and PER_CU into memory. */ +/* Load the DIEs associated with PER_CU into memory. */ -static struct dwarf2_cu * +static void load_full_comp_unit (struct dwarf2_per_cu_data *per_cu, struct objfile *objfile) { bfd *abfd = objfile->obfd; struct dwarf2_cu *cu; unsigned int offset; - gdb_byte *info_ptr; + gdb_byte *info_ptr, *beg_of_comp_unit; struct cleanup *back_to, *free_cu_cleanup; struct attribute *attr; CORE_ADDR baseaddr; @@ -2802,32 +2856,30 @@ load_full_comp_unit (struct dwarf2_per_cu_data *per_cu, struct objfile *objfile) offset = per_cu->offset; info_ptr = dwarf2_per_objfile->info.buffer + offset; + beg_of_comp_unit = info_ptr; - cu = xmalloc (sizeof (struct dwarf2_cu)); - memset (cu, 0, sizeof (struct dwarf2_cu)); + cu = alloc_one_comp_unit (objfile); /* If an error occurs while loading, release our storage. */ free_cu_cleanup = make_cleanup (free_one_comp_unit, cu); - cu->objfile = objfile; - - /* read in the comp_unit header */ + /* Read in the comp_unit header. */ info_ptr = read_comp_unit_head (&cu->header, info_ptr, abfd); - /* Read the abbrevs for this compilation unit */ + /* Complete the cu_header. */ + cu->header.offset = offset; + cu->header.first_die_offset = info_ptr - beg_of_comp_unit; + + /* Read the abbrevs for this compilation unit. */ dwarf2_read_abbrevs (abfd, cu); back_to = make_cleanup (dwarf2_free_abbrev_table, cu); - cu->header.offset = offset; - - cu->per_cu = per_cu; + /* Link this compilation unit into the compilation unit tree. */ per_cu->cu = cu; + cu->per_cu = per_cu; cu->type_hash = per_cu->type_hash; - /* We use this obstack for block values in dwarf_alloc_block. */ - obstack_init (&cu->comp_unit_obstack); - - cu->dies = read_comp_unit (info_ptr, abfd, cu); + cu->dies = read_comp_unit (info_ptr, cu); /* We try not to read any attributes in this function, because not all objfiles needed for references have been loaded yet, and symbol @@ -2844,8 +2896,6 @@ load_full_comp_unit (struct dwarf2_per_cu_data *per_cu, struct objfile *objfile) /* We've successfully allocated this compilation unit. Let our caller clean it up when finished with it. */ discard_cleanups (free_cu_cleanup); - - return cu; } /* Generate full symbol information for PST and CU, whose DIEs have @@ -4484,6 +4534,7 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu) type = alloc_type (objfile); INIT_CPLUS_SPECIFIC (type); + name = dwarf2_name (die, cu); if (name != NULL) { @@ -5606,11 +5657,24 @@ die_eq (const void *item_lhs, const void *item_rhs) return die_lhs->offset == die_rhs->offset; } +/* Initialize a die_reader_specs struct from a dwarf2_cu struct. */ + +static void +init_cu_die_reader (struct die_reader_specs *reader, + struct dwarf2_cu *cu) +{ + reader->abfd = cu->objfile->obfd; + reader->cu = cu; + reader->buffer = dwarf2_per_objfile->info.buffer; +} + /* Read a whole compilation unit into a linked list of dies. */ static struct die_info * -read_comp_unit (gdb_byte *info_ptr, bfd *abfd, struct dwarf2_cu *cu) +read_comp_unit (gdb_byte *info_ptr, struct dwarf2_cu *cu) { + struct die_reader_specs reader_specs; + cu->die_hash = htab_create_alloc_ex (cu->header.length / 12, die_hash, @@ -5620,19 +5684,21 @@ read_comp_unit (gdb_byte *info_ptr, bfd *abfd, struct dwarf2_cu *cu) hashtab_obstack_allocate, dummy_obstack_deallocate); - return read_die_and_children (info_ptr, abfd, cu, &info_ptr, NULL); + init_cu_die_reader (&reader_specs, cu); + + return read_die_and_children (&reader_specs, info_ptr, &info_ptr, NULL); } /* Main entry point for reading a DIE and all children. Read the DIE and dump it if requested. */ static struct die_info * -read_die_and_children (gdb_byte *info_ptr, bfd *abfd, - struct dwarf2_cu *cu, +read_die_and_children (const struct die_reader_specs *reader, + gdb_byte *info_ptr, gdb_byte **new_info_ptr, struct die_info *parent) { - struct die_info *result = read_die_and_children_1 (info_ptr, abfd, cu, + struct die_info *result = read_die_and_children_1 (reader, info_ptr, new_info_ptr, parent); if (dwarf2_die_debug) @@ -5651,8 +5717,8 @@ read_die_and_children (gdb_byte *info_ptr, bfd *abfd, is the parent of the die in question. */ static struct die_info * -read_die_and_children_1 (gdb_byte *info_ptr, bfd *abfd, - struct dwarf2_cu *cu, +read_die_and_children_1 (const struct die_reader_specs *reader, + gdb_byte *info_ptr, gdb_byte **new_info_ptr, struct die_info *parent) { @@ -5660,18 +5726,17 @@ read_die_and_children_1 (gdb_byte *info_ptr, bfd *abfd, gdb_byte *cur_ptr; int has_children; - cur_ptr = read_full_die (&die, abfd, info_ptr, cu, &has_children); + cur_ptr = read_full_die (reader, &die, info_ptr, &has_children); if (die == NULL) { *new_info_ptr = cur_ptr; return NULL; } - store_in_ref_table (die, cu); + store_in_ref_table (die, reader->cu); if (has_children) { - die->child = read_die_and_siblings (cur_ptr, abfd, cu, - new_info_ptr, die); + die->child = read_die_and_siblings (reader, cur_ptr, new_info_ptr, die); } else { @@ -5689,8 +5754,8 @@ read_die_and_children_1 (gdb_byte *info_ptr, bfd *abfd, in read_die_and_children. */ static struct die_info * -read_die_and_siblings (gdb_byte *info_ptr, bfd *abfd, - struct dwarf2_cu *cu, +read_die_and_siblings (const struct die_reader_specs *reader, + gdb_byte *info_ptr, gdb_byte **new_info_ptr, struct die_info *parent) { @@ -5703,7 +5768,7 @@ read_die_and_siblings (gdb_byte *info_ptr, bfd *abfd, while (1) { struct die_info *die - = read_die_and_children_1 (cur_ptr, abfd, cu, &cur_ptr, parent); + = read_die_and_children_1 (reader, cur_ptr, &cur_ptr, parent); if (die == NULL) { @@ -5720,6 +5785,55 @@ read_die_and_siblings (gdb_byte *info_ptr, bfd *abfd, } } +/* Read the die from the .debug_info section buffer. Set DIEP to + point to a newly allocated die with its information, except for its + child, sibling, and parent fields. Set HAS_CHILDREN to tell + whether the die has children or not. */ + +static gdb_byte * +read_full_die (const struct die_reader_specs *reader, + struct die_info **diep, gdb_byte *info_ptr, + int *has_children) +{ + unsigned int abbrev_number, bytes_read, i, offset; + struct abbrev_info *abbrev; + struct die_info *die; + struct dwarf2_cu *cu = reader->cu; + bfd *abfd = reader->abfd; + + offset = info_ptr - reader->buffer; + abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read); + info_ptr += bytes_read; + if (!abbrev_number) + { + *diep = NULL; + *has_children = 0; + return info_ptr; + } + + abbrev = dwarf2_lookup_abbrev (abbrev_number, cu); + if (!abbrev) + { + error (_("Dwarf Error: could not find abbrev number %d [in module %s]"), + abbrev_number, + bfd_get_filename (abfd)); + } + die = dwarf_alloc_die (cu, abbrev->num_attrs); + die->offset = offset; + die->tag = abbrev->tag; + die->abbrev = abbrev_number; + + die->num_attrs = abbrev->num_attrs; + + for (i = 0; i < abbrev->num_attrs; ++i) + info_ptr = read_attribute (&die->attrs[i], &abbrev->attrs[i], + abfd, info_ptr, cu); + + *diep = die; + *has_children = abbrev->has_children; + return info_ptr; +} + /* In DWARF version 2, the description of the debugging information is stored in a separate .debug_abbrev section. Before we read any dies from a section we read in all abbreviations and install them @@ -5896,8 +6010,8 @@ is_type_tag_for_partial (int tag) /* Load all DIEs that are interesting for partial symbols into memory. */ static struct partial_die_info * -load_partial_dies (bfd *abfd, gdb_byte *info_ptr, int building_psymtab, - struct dwarf2_cu *cu) +load_partial_dies (bfd *abfd, gdb_byte *buffer, gdb_byte *info_ptr, + int building_psymtab, struct dwarf2_cu *cu) { struct partial_die_info *part_die; struct partial_die_info *parent_die, *last_die, *first_die = NULL; @@ -5962,12 +6076,12 @@ load_partial_dies (bfd *abfd, gdb_byte *info_ptr, int building_psymtab, && abbrev->tag != DW_TAG_member) { /* Otherwise we skip to the next sibling, if any. */ - info_ptr = skip_one_die (info_ptr + bytes_read, abbrev, cu); + info_ptr = skip_one_die (buffer, info_ptr + bytes_read, abbrev, cu); continue; } - info_ptr = read_partial_die (part_die, abbrev, bytes_read, - abfd, info_ptr, cu); + info_ptr = read_partial_die (part_die, abbrev, bytes_read, abfd, + buffer, info_ptr, cu); /* This two-pass algorithm for processing partial symbols has a high cost in cache pressure. Thus, handle some simple cases @@ -5997,7 +6111,7 @@ load_partial_dies (bfd *abfd, gdb_byte *info_ptr, int building_psymtab, VAR_DOMAIN, LOC_TYPEDEF, &cu->objfile->static_psymbols, 0, (CORE_ADDR) 0, cu->language, cu->objfile); - info_ptr = locate_pdi_sibling (part_die, info_ptr, abfd, cu); + info_ptr = locate_pdi_sibling (part_die, buffer, info_ptr, abfd, cu); continue; } @@ -6022,7 +6136,7 @@ load_partial_dies (bfd *abfd, gdb_byte *info_ptr, int building_psymtab, : &cu->objfile->static_psymbols, 0, (CORE_ADDR) 0, cu->language, cu->objfile); - info_ptr = locate_pdi_sibling (part_die, info_ptr, abfd, cu); + info_ptr = locate_pdi_sibling (part_die, buffer, info_ptr, abfd, cu); continue; } @@ -6106,7 +6220,7 @@ load_partial_dies (bfd *abfd, gdb_byte *info_ptr, int building_psymtab, } /* Otherwise we skip to the next sibling, if any. */ - info_ptr = locate_pdi_sibling (last_die, info_ptr, abfd, cu); + info_ptr = locate_pdi_sibling (last_die, buffer, info_ptr, abfd, cu); /* Back to the top, do it again. */ } @@ -6118,7 +6232,8 @@ static gdb_byte * read_partial_die (struct partial_die_info *part_die, struct abbrev_info *abbrev, unsigned int abbrev_len, bfd *abfd, - gdb_byte *info_ptr, struct dwarf2_cu *cu) + gdb_byte *buffer, gdb_byte *info_ptr, + struct dwarf2_cu *cu) { unsigned int bytes_read, i; struct attribute attr; @@ -6136,7 +6251,7 @@ read_partial_die (struct partial_die_info *part_die, memset (part_die, 0, sizeof (struct partial_die_info)); - part_die->offset = info_ptr - dwarf2_per_objfile->info.buffer; + part_die->offset = info_ptr - buffer; info_ptr += abbrev_len; @@ -6249,8 +6364,7 @@ read_partial_die (struct partial_die_info *part_die, if (attr.form == DW_FORM_ref_addr) complaint (&symfile_complaints, _("ignoring absolute DW_AT_sibling")); else - part_die->sibling = dwarf2_per_objfile->info.buffer - + dwarf2_get_ref_die_offset (&attr); + part_die->sibling = buffer + dwarf2_get_ref_die_offset (&attr); break; case DW_AT_stmt_list: part_die->has_stmt_list = 1; @@ -6340,7 +6454,7 @@ find_partial_die (unsigned int offset, struct dwarf2_cu *cu) if (per_cu->cu == NULL) { - load_comp_unit (per_cu, cu->objfile); + load_partial_comp_unit (per_cu, cu->objfile); per_cu->cu->read_in_chain = dwarf2_per_objfile->read_in_chain; dwarf2_per_objfile->read_in_chain = per_cu; } @@ -6370,10 +6484,13 @@ find_partial_die (unsigned int offset, struct dwarf2_cu *cu) + per_cu->cu->header.first_die_offset); abbrev = peek_die_abbrev (info_ptr, &bytes_read, per_cu->cu); info_ptr = read_partial_die (&comp_unit_die, abbrev, bytes_read, - per_cu->cu->objfile->obfd, info_ptr, + per_cu->cu->objfile->obfd, + dwarf2_per_objfile->info.buffer, info_ptr, per_cu->cu); if (comp_unit_die.has_children) - load_partial_dies (per_cu->cu->objfile->obfd, info_ptr, 0, per_cu->cu); + load_partial_dies (per_cu->cu->objfile->obfd, + dwarf2_per_objfile->info.buffer, info_ptr, + 0, per_cu->cu); do_cleanups (back_to); pd = find_partial_die_in_comp_unit (offset, per_cu->cu); @@ -6428,52 +6545,6 @@ fixup_partial_die (struct partial_die_info *part_die, guess_structure_name (part_die, cu); } -/* Read the die from the .debug_info section buffer. Set DIEP to - point to a newly allocated die with its information, except for its - child, sibling, and parent fields. Set HAS_CHILDREN to tell - whether the die has children or not. */ - -static gdb_byte * -read_full_die (struct die_info **diep, bfd *abfd, gdb_byte *info_ptr, - struct dwarf2_cu *cu, int *has_children) -{ - unsigned int abbrev_number, bytes_read, i, offset; - struct abbrev_info *abbrev; - struct die_info *die; - - offset = info_ptr - dwarf2_per_objfile->info.buffer; - abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read); - info_ptr += bytes_read; - if (!abbrev_number) - { - *diep = NULL; - *has_children = 0; - return info_ptr; - } - - abbrev = dwarf2_lookup_abbrev (abbrev_number, cu); - if (!abbrev) - { - error (_("Dwarf Error: could not find abbrev number %d [in module %s]"), - abbrev_number, - bfd_get_filename (abfd)); - } - die = dwarf_alloc_die (cu, abbrev->num_attrs); - die->offset = offset; - die->tag = abbrev->tag; - die->abbrev = abbrev_number; - - die->num_attrs = abbrev->num_attrs; - - for (i = 0; i < abbrev->num_attrs; ++i) - info_ptr = read_attribute (&die->attrs[i], &abbrev->attrs[i], - abfd, info_ptr, cu); - - *diep = die; - *has_children = abbrev->has_children; - return info_ptr; -} - /* Read an attribute value described by an attribute form. */ static gdb_byte * @@ -6662,7 +6733,7 @@ read_4_signed_bytes (bfd *abfd, gdb_byte *buf) return bfd_get_signed_32 (abfd, buf); } -static unsigned long +static ULONGEST read_8_bytes (bfd *abfd, gdb_byte *buf) { return bfd_get_64 (abfd, buf); @@ -9643,11 +9714,9 @@ store_in_ref_table (struct die_info *die, struct dwarf2_cu *cu) *slot = die; } -static unsigned int -dwarf2_get_ref_die_offset (struct attribute *attr) +static int +is_ref_attr (struct attribute *attr) { - unsigned int result = 0; - switch (attr->form) { case DW_FORM_ref_addr: @@ -9656,14 +9725,22 @@ dwarf2_get_ref_die_offset (struct attribute *attr) case DW_FORM_ref4: case DW_FORM_ref8: case DW_FORM_ref_udata: - result = DW_ADDR (attr); - break; + return 1; default: - complaint (&symfile_complaints, - _("unsupported die ref attribute form: '%s'"), - dwarf_form_name (attr->form)); + return 0; } - return result; +} + +static unsigned int +dwarf2_get_ref_die_offset (struct attribute *attr) +{ + if (is_ref_attr (attr)) + return DW_ADDR (attr); + + complaint (&symfile_complaints, + _("unsupported die ref attribute form: '%s'"), + dwarf_form_name (attr->form)); + return 0; } /* Return the constant value held by the given attribute. Return -1 @@ -10742,9 +10819,22 @@ dwarf2_find_comp_unit (unsigned int offset, struct objfile *objfile) return this_cu; } +/* Malloc space for a dwarf2_cu for OBJFILE and initialize it. */ + +static struct dwarf2_cu * +alloc_one_comp_unit (struct objfile *objfile) +{ + struct dwarf2_cu *cu = xcalloc (1, sizeof (struct dwarf2_cu)); + cu->objfile = objfile; + obstack_init (&cu->comp_unit_obstack); + return cu; +} + /* Release one cached compilation unit, CU. We unlink it from the tree of compilation units, but we don't remove it from the read_in_chain; - the caller is responsible for that. */ + the caller is responsible for that. + NOTE: DATA is a void * because this function is also used as a + cleanup routine. */ static void free_one_comp_unit (void *data) |