struct dwarf2_per_cu_data
{
unsigned long offset, length;
-#if 0
+
+ /* Only set during full symbol reading. */
struct partial_symtab *psymtab;
-#endif
/* Set iff currently read in. */
struct dwarf2_cu *cu;
struct dwarf2_pinfo
{
+ /* If this partial symbol table has been read in, a map of DIE
+ offsets to types. */
+ htab_t type_hash;
+
+ /* Offset in dwarf_info_buffer for this compilation unit. */
+
+ unsigned long dwarf_info_offset;
+
+ /* FIXME: All the rest is actually per-objfile. */
+
/* Pointer to start of dwarf info buffer for the objfile. */
char *dwarf_info_buffer;
- /* Offset in dwarf_info_buffer for this compilation unit. */
+ /* Size of dwarf info section for the objfile. */
- unsigned long dwarf_info_offset;
+ unsigned int dwarf_info_size;
/* Pointer to start of dwarf abbreviation buffer for the objfile. */
#define PST_PRIVATE(p) ((struct dwarf2_pinfo *)(p)->read_symtab_private)
#define DWARF_INFO_BUFFER(p) (PST_PRIVATE(p)->dwarf_info_buffer)
+#define DWARF_INFO_SIZE(p) (PST_PRIVATE(p)->dwarf_info_size)
#define DWARF_INFO_OFFSET(p) (PST_PRIVATE(p)->dwarf_info_offset)
#define DWARF_ABBREV_BUFFER(p) (PST_PRIVATE(p)->dwarf_abbrev_buffer)
#define DWARF_ABBREV_SIZE(p) (PST_PRIVATE(p)->dwarf_abbrev_size)
static void free_one_cached_comp_unit (struct dwarf2_cu *, struct dwarf2_cu *);
+static void set_die_type (struct die_info *, struct type *,
+ struct dwarf2_cu *);
+
+static void reset_die_and_siblings_types (struct die_info *,
+ struct dwarf2_cu *);
+
/* Allocation function for the libiberty splay tree which uses an obstack. */
static void *
splay_tree_obstack_allocate (int size, void *data)
pst->read_symtab_private = (char *)
obstack_alloc (&objfile->objfile_obstack, sizeof (struct dwarf2_pinfo));
- DWARF_INFO_BUFFER (pst) = dwarf_info_buffer;
DWARF_INFO_OFFSET (pst) = beg_of_comp_unit - dwarf_info_buffer;
+ DWARF_INFO_BUFFER (pst) = dwarf_info_buffer;
+ DWARF_INFO_SIZE (pst) = dwarf_info_size;
DWARF_ABBREV_BUFFER (pst) = dwarf_abbrev_buffer;
DWARF_ABBREV_SIZE (pst) = dwarf_abbrev_size;
DWARF_LINE_BUFFER (pst) = dwarf_line_buffer;
DWARF_RANGES_SIZE (pst) = dwarf_ranges_size;
DWARF_LOC_BUFFER (pst) = dwarf_loc_buffer;
DWARF_LOC_SIZE (pst) = dwarf_loc_size;
+ PST_PRIVATE (pst)->type_hash = NULL;
baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
/* Store the function that reads in the rest of the symbol table */
/* Set local variables from the partial symbol table info. */
offset = DWARF_INFO_OFFSET (pst);
dwarf_info_buffer = DWARF_INFO_BUFFER (pst);
+ dwarf_info_size = DWARF_INFO_SIZE (pst);
dwarf_abbrev_buffer = DWARF_ABBREV_BUFFER (pst);
dwarf_abbrev_size = DWARF_ABBREV_SIZE (pst);
dwarf_line_buffer = DWARF_LINE_BUFFER (pst);
cu.header.offset = offset;
+ /* NOTE drow/2004-02-23: this reads in the comp_unit_tree that we went to
+ so much trouble to keep lazy during partial symbol reading. If this
+ proves to be unavoidable then we may want to strip out the lazy code
+ during partial symbol reading also. */
+ cu.per_cu = dwarf2_find_containing_comp_unit (offset + 1, &cu);
+ /* As in partial symbol table building, this leaks a pointer to our stack
+ frame into a global data structure. Be sure to clear it before we
+ return. */
+ cu.per_cu->cu = &cu;
+ make_cleanup (clear_per_cu_pointer, &cu);
+ cu.read_in_chain = NULL;
+
+ cu.per_cu->psymtab = pst;
+
cu.list_in_scope = &file_symbols;
dies = read_comp_unit (info_ptr, abfd, &cu);
/* We need to add the type field to the die immediately so we don't
infinitely recurse when dealing with pointers to the structure
type within the structure itself. */
- die->type = type;
+ set_die_type (die, type, cu);
if (die->child != NULL && ! die_is_declaration (die, cu))
{
TYPE_LENGTH (type) = 0;
}
- die->type = type;
+ set_die_type (die, type, cu);
}
/* Given a pointer to a die which begins an enumeration, process all
{
index_type = dwarf2_fundamental_type (objfile, FT_INTEGER, cu);
range_type = create_range_type (NULL, index_type, 0, -1);
- die->type = create_array_type (NULL, element_type, range_type);
+ set_die_type (die, create_array_type (NULL, element_type, range_type),
+ cu);
return;
}
do_cleanups (back_to);
/* Install the type in the die. */
- die->type = type;
+ set_die_type (die, type, cu);
}
/* First cut: install each common block member as a global variable. */
}
TYPE_LENGTH (type) = byte_size;
- die->type = type;
+ set_die_type (die, type, cu);
}
/* Extract all information from a DW_TAG_ptr_to_member_type DIE and add to
domain = die_containing_type (die, cu);
smash_to_member_type (type, domain, to_type);
- die->type = type;
+ set_die_type (die, type, cu);
}
/* Extract all information from a DW_TAG_reference_type DIE and add to
{
TYPE_LENGTH (type) = cu_header->addr_size;
}
- die->type = type;
+ set_die_type (die, type, cu);
}
static void
}
base_type = die_type (die, cu);
- die->type = make_cv_type (1, TYPE_VOLATILE (base_type), base_type, 0);
+ set_die_type (die, make_cv_type (1, TYPE_VOLATILE (base_type), base_type, 0),
+ cu);
}
static void
}
base_type = die_type (die, cu);
- die->type = make_cv_type (TYPE_CONST (base_type), 1, base_type, 0);
+ set_die_type (die, make_cv_type (TYPE_CONST (base_type), 1, base_type, 0),
+ cu);
}
/* Extract all information from a DW_TAG_string_type DIE and add to
char_type = dwarf2_fundamental_type (objfile, FT_CHAR, cu);
type = create_string_type (char_type, range_type);
}
- die->type = type;
+ set_die_type (die, type, cu);
}
/* Handle DIES due to C code like:
}
}
- die->type = ftype;
+ set_die_type (die, ftype, cu);
}
static void
{
name = DW_STRING (attr);
}
- die->type = init_type (TYPE_CODE_TYPEDEF, 0, TYPE_FLAG_TARGET_STUB, name, objfile);
+ set_die_type (die, init_type (TYPE_CODE_TYPEDEF, 0,
+ TYPE_FLAG_TARGET_STUB, name, objfile), cu);
TYPE_TARGET_TYPE (die->type) = die_type (die, cu);
}
}
{
type = dwarf_base_type (encoding, size, cu);
}
- die->type = type;
+ set_die_type (die, type, cu);
}
/* Read the given DW_AT_subrange DIE. */
struct attribute *attr;
int low = 0;
int high = -1;
+ struct dwarf2_cu *spec_cu;
/* If we have already decoded this die, then nothing more to do. */
if (die->type)
low = 1;
}
- attr = dwarf2_attr (die, DW_AT_lower_bound, cu);
+ /* FIXME: For variable sized arrays either of these could be
+ a variable rather than a constant value. We'll allow it,
+ but we don't know how to handle it. */
+ attr = dwarf2_attr_with_cu (die, DW_AT_lower_bound, cu, &spec_cu);
if (attr)
low = dwarf2_get_attr_constant_value (attr, 0);
- attr = dwarf2_attr (die, DW_AT_upper_bound, cu);
+ attr = dwarf2_attr_with_cu (die, DW_AT_upper_bound, cu, &spec_cu);
if (attr)
{
if (attr->form == DW_FORM_block1)
if (attr)
TYPE_LENGTH (range_type) = DW_UNSND (attr);
- die->type = range_type;
+ set_die_type (die, range_type, cu);
}
free_comp_units_worker (cu, 0, target_cu);
}
+struct dwarf2_offset_and_type
+{
+ unsigned int offset;
+ struct type *type;
+};
+
+static hashval_t
+offset_and_type_hash (const void *item)
+{
+ const struct dwarf2_offset_and_type *ofs = item;
+ return ofs->offset;
+}
+
+static int
+offset_and_type_eq (const void *item_lhs, const void *item_rhs)
+{
+ const struct dwarf2_offset_and_type *ofs_lhs = item_lhs;
+ const struct dwarf2_offset_and_type *ofs_rhs = item_rhs;
+ return ofs_lhs->offset == ofs_rhs->offset;
+}
+
+/* Functions used to regenerate die->type, given a tree of DIEs and an
+ already completed symtab. Types without names can't necessarily be
+ reconstituted, so we save them. */
+static void
+set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
+{
+ htab_t type_hash;
+ struct dwarf2_offset_and_type **slot, ofs;
+
+ die->type = type;
+
+ type_hash = PST_PRIVATE (cu->per_cu->psymtab)->type_hash;
+ if (type_hash == NULL)
+ {
+ type_hash = htab_create_alloc_ex (cu->header.length / 24,
+ offset_and_type_hash,
+ offset_and_type_eq,
+ NULL,
+ &cu->objfile->objfile_obstack,
+ hash_obstack_allocate,
+ splay_tree_obstack_deallocate);
+ PST_PRIVATE (cu->per_cu->psymtab)->type_hash = type_hash;
+ }
+ ofs.offset = die->offset;
+ ofs.type = type;
+ slot = (struct dwarf2_offset_and_type **)
+ htab_find_slot_with_hash (type_hash, &ofs, ofs.offset, INSERT);
+ *slot = obstack_alloc (&cu->objfile->objfile_obstack, sizeof (**slot));
+ **slot = ofs;
+}
+
+static struct type *
+get_die_type (struct die_info *die, struct dwarf2_cu *cu)
+{
+ htab_t type_hash;
+ struct dwarf2_offset_and_type *slot, ofs;
+
+ type_hash = PST_PRIVATE (cu->per_cu->psymtab)->type_hash;
+ ofs.offset = die->offset;
+ slot = htab_find_with_hash (type_hash, &ofs, ofs.offset);
+ if (slot)
+ return slot->type;
+ else
+ return NULL;
+}
+
+static void
+reset_die_and_siblings_types (struct die_info *start_die, struct dwarf2_cu *cu)
+{
+ struct die_info *die;
+
+ for (die = start_die; die != NULL; die = die->sibling)
+ {
+ die->type = get_die_type (die, cu);
+ if (die->child != NULL)
+ reset_die_and_siblings_types (die->child, cu);
+ }
+}
+
void _initialize_dwarf2_read (void);
void