/* DWARF 2 debugging format support for GDB.
Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
- 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+ 2004, 2005, 2006, 2007, 2008, 2009
+ Free Software Foundation, Inc.
Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology,
Inc. with support from Florida State University (under contract
}
_STATEMENT_PROLOGUE;
+/* When non-zero, dump DIEs after they are read in. */
+static int dwarf2_die_debug = 0;
+
/* When set, the file that we're processing is known to have debugging
info for C++ namespaces. GCC 3.3.x did not produce this information,
but later versions do. */
translation, looks like this. */
struct comp_unit_head
{
- unsigned long length;
+ unsigned int length;
short version;
- unsigned int abbrev_offset;
unsigned char addr_size;
unsigned char signed_addr_p;
+ unsigned int abbrev_offset;
/* Size of file offsets; either 4 or 8. */
unsigned int offset_size;
.debug_info section, for resolving relative reference dies. */
unsigned int offset;
- /* Pointer to this compilation unit header in the .debug_info
- section. */
- gdb_byte *cu_head_ptr;
-
- /* Pointer to the first die of this compilation unit. This will be
- the first byte following the compilation unit header. */
- gdb_byte *first_die_ptr;
-
- /* Pointer to the next compilation unit header in the program. */
- struct comp_unit_head *next;
-
- /* Base address of this compilation unit. */
- CORE_ADDR base_address;
-
- /* Non-zero if base_address has been set. */
- int base_known;
+ /* Offset to first die in this cu from the start of the cu.
+ This will be the first byte following the compilation unit header. */
+ unsigned int first_die_offset;
};
/* Internal state when decoding a particular compilation unit. */
/* The objfile containing this compilation unit. */
struct objfile *objfile;
- /* The header of the compilation unit.
-
- FIXME drow/2003-11-10: Some of the things from the comp_unit_head
- should logically be moved to the dwarf2_cu structure. */
+ /* The header of the compilation unit. */
struct comp_unit_head header;
+ /* Base address of this compilation unit. */
+ CORE_ADDR base_address;
+
+ /* Non-zero if base_address has been set. */
+ int base_known;
+
struct function_range *first_fn, *last_fn, *cached_fn;
/* The language we are debugging. */
htab_t partial_dies;
/* `.debug_ranges' offset for this `DW_TAG_compile_unit' DIE. */
- unsigned long ranges_offset;
+ unsigned int ranges_offset;
/* Storage for things with the same lifetime as this read-in compilation
unit, including partial DIEs. */
{
/* The start offset and length of this compilation unit. 2**30-1
bytes should suffice to store the length of any compilation unit
- - if it doesn't, GDB will fall over anyway. */
- unsigned long offset;
- unsigned long length : 30;
+ - if it doesn't, GDB will fall over anyway.
+ NOTE: Unlike comp_unit_head.length, this length includes
+ initial_length_size. */
+ unsigned int offset;
+ unsigned int length : 30;
/* Flag indicating this compilation unit will be read in before
any of the current compilation units are processed. */
- unsigned long queued : 1;
+ unsigned int queued : 1;
/* This flag will be set if we need to load absolutely all DIEs
for this compilation unit, instead of just the ones we think
struct attr_abbrev
{
- enum dwarf_attribute name;
- enum dwarf_form form;
+ ENUM_BITFIELD(dwarf_attribute) name : 16;
+ ENUM_BITFIELD(dwarf_form) form : 16;
};
/* Attributes have a name and a value */
struct attribute
{
- enum dwarf_attribute name;
- enum dwarf_form form;
+ ENUM_BITFIELD(dwarf_attribute) name : 16;
+ ENUM_BITFIELD(dwarf_form) form : 16;
union
{
char *str;
/* This data structure holds a complete die structure. */
struct die_info
{
- enum dwarf_tag tag; /* Tag indicating type of die */
- unsigned int abbrev; /* Abbrev number */
- unsigned int offset; /* Offset in .debug_info section */
- unsigned int num_attrs; /* Number of attributes */
+ /* DWARF-2 tag for this DIE. */
+ ENUM_BITFIELD(dwarf_tag) tag : 16;
+
+ /* Number of attributes */
+ unsigned short num_attrs;
+
+ /* Abbrev number */
+ unsigned int abbrev;
+
+ /* Offset in .debug_info section */
+ unsigned int offset;
/* The dies in a compilation unit form an n-ary tree. PARENT
points to this die's parent; CHILD points to the first child of
_(".debug_line section has line data without a file"));
}
+static void
+dwarf2_debug_line_missing_end_sequence_complaint (void)
+{
+ complaint (&symfile_complaints,
+ _(".debug_line section has line program sequence without an end"));
+}
+
static void
dwarf2_complex_location_expr_complaint (void)
{
static void add_partial_enumeration (struct partial_die_info *enum_pdi,
struct dwarf2_cu *cu);
+static void add_partial_subprogram (struct partial_die_info *pdi,
+ CORE_ADDR *lowpc, CORE_ADDR *highpc,
+ struct dwarf2_cu *cu);
+
static gdb_byte *locate_pdi_sibling (struct partial_die_info *orig_pdi,
gdb_byte *info_ptr,
bfd *abfd,
struct abbrev_info *abbrev, unsigned int,
bfd *, gdb_byte *, struct dwarf2_cu *);
-static struct partial_die_info *find_partial_die (unsigned long,
+static struct partial_die_info *find_partial_die (unsigned int,
struct dwarf2_cu *);
static void fixup_partial_die (struct partial_die_info *,
static CORE_ADDR read_address (bfd *, gdb_byte *ptr, struct dwarf2_cu *,
unsigned int *);
-static LONGEST read_initial_length (bfd *, gdb_byte *,
- struct comp_unit_head *, unsigned int *);
+static LONGEST read_initial_length (bfd *, gdb_byte *, unsigned int *);
+
+static LONGEST read_checked_initial_length_and_offset
+ (bfd *, gdb_byte *, const struct comp_unit_head *,
+ unsigned int *, unsigned int *);
static LONGEST read_offset (bfd *, gdb_byte *, const struct comp_unit_head *,
- unsigned int *);
+ unsigned int *);
+
+static LONGEST read_offset_1 (bfd *, gdb_byte *, unsigned int);
static gdb_byte *read_n_bytes (bfd *, gdb_byte *, unsigned int);
static struct die_info *read_comp_unit (gdb_byte *, bfd *, struct dwarf2_cu *);
+static struct die_info *read_die_and_children_1 (gdb_byte *info_ptr, bfd *abfd,
+ struct dwarf2_cu *,
+ 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 *,
gdb_byte **new_info_ptr,
static struct die_info *sibling_die (struct die_info *);
-static void dump_die (struct die_info *);
+static void dump_die_shallow (struct ui_file *, int indent, struct die_info *);
-static void dump_die_list (struct die_info *);
+static void dump_die_for_error (struct die_info *);
+
+static void dump_die_1 (struct ui_file *, int level, int max_level,
+ struct die_info *);
+
+/*static*/ void dump_die (struct die_info *, int max_level);
static void store_in_ref_table (struct die_info *,
struct dwarf2_cu *);
-static unsigned int dwarf2_get_ref_die_offset (struct attribute *,
- struct dwarf2_cu *);
+static unsigned int dwarf2_get_ref_die_offset (struct attribute *);
static int dwarf2_get_attr_constant_value (struct attribute *, int);
static int partial_die_eq (const void *item_lhs, const void *item_rhs);
static struct dwarf2_per_cu_data *dwarf2_find_containing_comp_unit
- (unsigned long offset, struct objfile *objfile);
+ (unsigned int offset, struct objfile *objfile);
static struct dwarf2_per_cu_data *dwarf2_find_comp_unit
- (unsigned long offset, struct objfile *objfile);
+ (unsigned int offset, struct objfile *objfile);
static void free_one_comp_unit (void *);
pubnames_ptr = pubnames_buffer;
while ((pubnames_ptr - pubnames_buffer) < dwarf2_per_objfile->pubnames_size)
{
- struct comp_unit_head cu_header;
unsigned int bytes_read;
- entry_length = read_initial_length (abfd, pubnames_ptr, &cu_header,
- &bytes_read);
+ entry_length = read_initial_length (abfd, pubnames_ptr, &bytes_read);
pubnames_ptr += bytes_read;
version = read_1_byte (abfd, pubnames_ptr);
pubnames_ptr += 1;
}
#endif
+/* Return TRUE if OFFSET is within CU_HEADER. */
+
+static inline int
+offset_in_cu_p (const struct comp_unit_head *cu_header, unsigned int offset)
+{
+ unsigned int bottom = cu_header->offset;
+ unsigned int top = (cu_header->offset
+ + cu_header->length
+ + cu_header->initial_length_size);
+ return (offset >= bottom && offset < top);
+}
+
/* Read in the comp unit header information from the debug_info at
info_ptr. */
{
int signed_addr;
unsigned int bytes_read;
- cu_header->length = read_initial_length (abfd, info_ptr, cu_header,
- &bytes_read);
+
+ cu_header->length = read_initial_length (abfd, info_ptr, &bytes_read);
+ cu_header->initial_length_size = bytes_read;
+ cu_header->offset_size = (bytes_read == 4) ? 4 : 8;
info_ptr += bytes_read;
cu_header->version = read_2_bytes (abfd, info_ptr);
info_ptr += 2;
cu_header->abbrev_offset = read_offset (abfd, info_ptr, cu_header,
- &bytes_read);
+ &bytes_read);
info_ptr += bytes_read;
cu_header->addr_size = read_1_byte (abfd, info_ptr);
info_ptr += 1;
internal_error (__FILE__, __LINE__,
_("read_comp_unit_head: dwarf from non elf file"));
cu_header->signed_addr_p = signed_addr;
+
return info_ptr;
}
/* Complete the cu_header */
cu.header.offset = beg_of_comp_unit - dwarf2_per_objfile->info_buffer;
- cu.header.first_die_ptr = info_ptr;
- cu.header.cu_head_ptr = beg_of_comp_unit;
+ cu.header.first_die_offset = info_ptr - beg_of_comp_unit;
cu.list_in_scope = &file_symbols;
objfile->static_psymbols.next);
if (comp_unit_die.dirname)
- pst->dirname = xstrdup (comp_unit_die.dirname);
+ pst->dirname = obsavestring (comp_unit_die.dirname,
+ strlen (comp_unit_die.dirname),
+ &objfile->objfile_obstack);
pst->read_symtab_private = (char *) this_cu;
/* Complete the cu_header. */
cu->header.offset = beg_of_comp_unit - dwarf2_per_objfile->info_buffer;
- cu->header.first_die_ptr = info_ptr;
- cu->header.cu_head_ptr = beg_of_comp_unit;
+ cu->header.first_die_offset = info_ptr - beg_of_comp_unit;
/* Read the abbrevs for this compilation unit into a table. */
dwarf2_read_abbrevs (abfd, cu);
while (info_ptr < dwarf2_per_objfile->info_buffer + dwarf2_per_objfile->info_size)
{
- struct comp_unit_head cu_header;
+ unsigned int length, initial_length_size;
gdb_byte *beg_of_comp_unit;
struct dwarf2_per_cu_data *this_cu;
- unsigned long offset;
- unsigned int bytes_read;
+ unsigned int offset;
offset = info_ptr - dwarf2_per_objfile->info_buffer;
/* Read just enough information to find out where the next
compilation unit is. */
- cu_header.initial_length_size = 0;
- cu_header.length = read_initial_length (objfile->obfd, info_ptr,
- &cu_header, &bytes_read);
+ length = read_initial_length (objfile->obfd, info_ptr,
+ &initial_length_size);
/* Save the compilation unit for later lookup. */
this_cu = obstack_alloc (&objfile->objfile_obstack,
sizeof (struct dwarf2_per_cu_data));
memset (this_cu, 0, sizeof (*this_cu));
this_cu->offset = offset;
- this_cu->length = cu_header.length + cu_header.initial_length_size;
+ this_cu->length = length + initial_length_size;
if (n_comp_units == n_allocated)
{
switch (pdi->tag)
{
case DW_TAG_subprogram:
- if (pdi->has_pc_info)
- {
- if (pdi->lowpc < *lowpc)
- {
- *lowpc = pdi->lowpc;
- }
- if (pdi->highpc > *highpc)
- {
- *highpc = pdi->highpc;
- }
- if (!pdi->is_declaration)
- {
- add_partial_symbol (pdi, cu);
- }
- }
+ add_partial_subprogram (pdi, lowpc, highpc, cu);
break;
case DW_TAG_variable:
case DW_TAG_typedef:
scan_partial_symbols (pdi->die_child, lowpc, highpc, cu);
}
+/* Read a partial die corresponding to a subprogram and create a partial
+ symbol for that subprogram. When the CU language allows it, this
+ routine also defines a partial symbol for each nested subprogram
+ that this subprogram contains.
+
+ DIE my also be a lexical block, in which case we simply search
+ recursively for suprograms defined inside that lexical block.
+ Again, this is only performed when the CU language allows this
+ type of definitions. */
+
+static void
+add_partial_subprogram (struct partial_die_info *pdi,
+ CORE_ADDR *lowpc, CORE_ADDR *highpc,
+ struct dwarf2_cu *cu)
+{
+ if (pdi->tag == DW_TAG_subprogram)
+ {
+ if (pdi->has_pc_info)
+ {
+ if (pdi->lowpc < *lowpc)
+ *lowpc = pdi->lowpc;
+ if (pdi->highpc > *highpc)
+ *highpc = pdi->highpc;
+ if (!pdi->is_declaration)
+ add_partial_symbol (pdi, cu);
+ }
+ }
+
+ if (! pdi->has_children)
+ return;
+
+ if (cu->language == language_ada)
+ {
+ pdi = pdi->die_child;
+ while (pdi != NULL)
+ {
+ fixup_partial_die (pdi, cu);
+ if (pdi->tag == DW_TAG_subprogram
+ || pdi->tag == DW_TAG_lexical_block)
+ add_partial_subprogram (pdi, lowpc, highpc, cu);
+ pdi = pdi->die_sibling;
+ }
+ }
+}
+
/* See if we can figure out if the class lives in a namespace. We do
this by looking for a member function; its demangled name will
contain namespace info, if there is any. */
complaint (&symfile_complaints, _("ignoring absolute DW_AT_sibling"));
else
return dwarf2_per_objfile->info_buffer
- + dwarf2_get_ref_die_offset (&attr, cu);
+ + dwarf2_get_ref_die_offset (&attr);
}
/* If it isn't DW_AT_sibling, skip this attribute. */
{
bfd *abfd = objfile->obfd;
struct dwarf2_cu *cu;
- unsigned long offset;
+ unsigned int offset;
gdb_byte *info_ptr;
struct cleanup *back_to, *free_cu_cleanup;
struct attribute *attr;
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;
+ cu->base_known = 0;
+ cu->base_address = 0;
attr = dwarf2_attr (cu->dies, DW_AT_entry_pc, cu);
if (attr)
{
- cu->header.base_address = DW_ADDR (attr);
- cu->header.base_known = 1;
+ cu->base_address = DW_ADDR (attr);
+ cu->base_known = 1;
}
else
{
attr = dwarf2_attr (cu->dies, DW_AT_low_pc, cu);
if (attr)
{
- cu->header.base_address = DW_ADDR (attr);
- cu->header.base_known = 1;
+ cu->base_address = DW_ADDR (attr);
+ cu->base_known = 1;
}
}
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. */
+ Fortran case. */
processing_has_namespace_info = 1;
- gdb_assert (die->child == NULL);
+ complaint (&symfile_complaints, _("unsupported tag: '%s'"),
+ dwarf_tag_name (die->tag));
break;
default:
new_symbol (die, NULL, cu);
CORE_ADDR high = 0;
CORE_ADDR baseaddr;
- found_base = cu_header->base_known;
- base = cu_header->base_address;
+ found_base = cu->base_known;
+ base = cu->base_address;
if (offset >= dwarf2_per_objfile->ranges_size)
{
return ret;
}
+/* Assuming that DIE represents a subprogram DIE or a lexical block, get
+ its low and high PC addresses. Do nothing if these addresses could not
+ be determined. Otherwise, set LOWPC to the low address if it is smaller,
+ and HIGHPC to the high address if greater than HIGHPC. */
+
+static void
+dwarf2_get_subprogram_pc_bounds (struct die_info *die,
+ CORE_ADDR *lowpc, CORE_ADDR *highpc,
+ struct dwarf2_cu *cu)
+{
+ CORE_ADDR low, high;
+ struct die_info *child = die->child;
+
+ if (dwarf2_get_pc_bounds (die, &low, &high, cu))
+ {
+ *lowpc = min (*lowpc, low);
+ *highpc = max (*highpc, high);
+ }
+
+ /* If the language does not allow nested subprograms (either inside
+ subprograms or lexical blocks), we're done. */
+ if (cu->language != language_ada)
+ return;
+
+ /* Check all the children of the given DIE. If it contains nested
+ subprograms, then check their pc bounds. Likewise, we need to
+ check lexical blocks as well, as they may also contain subprogram
+ definitions. */
+ while (child && child->tag)
+ {
+ if (child->tag == DW_TAG_subprogram
+ || child->tag == DW_TAG_lexical_block)
+ dwarf2_get_subprogram_pc_bounds (child, lowpc, highpc, cu);
+ child = sibling_die (child);
+ }
+}
+
/* Get the low and high pc's represented by the scope DIE, and store
them in *LOWPC and *HIGHPC. If the correct values can't be
determined, set *LOWPC to -1 and *HIGHPC to 0. */
{
switch (child->tag) {
case DW_TAG_subprogram:
- if (dwarf2_get_pc_bounds (child, ¤t_low, ¤t_high, cu))
- {
- best_low = min (best_low, current_low);
- best_high = max (best_high, current_high);
- }
+ dwarf2_get_subprogram_pc_bounds (child, &best_low, &best_high, cu);
break;
case DW_TAG_namespace:
/* FIXME: carlton/2004-01-16: Should we do this for
'baseaddr' argument, which GDB uses to relocate debugging
information from a shared library based on the address at
which the library was loaded. */
- CORE_ADDR base = cu->header.base_address;
- int base_known = cu->header.base_known;
+ CORE_ADDR base = cu->base_address;
+ int base_known = cu->base_known;
if (offset >= dwarf2_per_objfile->ranges_size)
{
/* Get type of field. */
fp->type = die_type (die, cu);
- FIELD_STATIC_KIND (*fp) = 0;
+ SET_FIELD_BITPOS (*fp, 0);
/* Get bit size of field (zero if none). */
attr = dwarf2_attr (die, DW_AT_bit_size, cu);
else
byte_offset = decode_locdesc (DW_BLOCK (attr), cu);
- FIELD_BITPOS (*fp) = byte_offset * bits_per_byte;
+ SET_FIELD_BITPOS (*fp, byte_offset * bits_per_byte);
}
- else
- FIELD_BITPOS (*fp) = 0;
attr = dwarf2_attr (die, DW_AT_bit_offset, cu);
if (attr)
{
/* C++ base class field. */
attr = dwarf2_attr (die, DW_AT_data_member_location, cu);
if (attr)
- FIELD_BITPOS (*fp) = (decode_locdesc (DW_BLOCK (attr), cu)
- * bits_per_byte);
+ SET_FIELD_BITPOS (*fp, decode_locdesc (DW_BLOCK (attr), cu)
+ * bits_per_byte);
FIELD_BITSIZE (*fp) = 0;
- FIELD_STATIC_KIND (*fp) = 0;
FIELD_TYPE (*fp) = die_type (die, cu);
FIELD_NAME (*fp) = type_name_no_tag (fp->type);
fip->nbaseclasses++;
TYPE_LENGTH (type) = 0;
}
- TYPE_FLAGS (type) |= TYPE_FLAG_STUB_SUPPORTED;
+ TYPE_STUB_SUPPORTED (type) = 1;
if (die_is_declaration (die, cu))
- TYPE_FLAGS (type) |= TYPE_FLAG_STUB;
+ TYPE_STUB (type) = 1;
/* We need to add the type field to the die immediately so we don't
infinitely recurse when dealing with pointers to the structure
Types. When another package uses such a type, an incomplete DIE
may be generated by the compiler. */
if (die_is_declaration (die, cu))
- TYPE_FLAGS (type) |= TYPE_FLAG_STUB;
+ TYPE_STUB (type) = 1;
return set_die_type (die, type, cu);
}
FIELD_NAME (fields[num_fields]) = SYMBOL_LINKAGE_NAME (sym);
FIELD_TYPE (fields[num_fields]) = NULL;
- FIELD_BITPOS (fields[num_fields]) = SYMBOL_VALUE (sym);
+ SET_FIELD_BITPOS (fields[num_fields], SYMBOL_VALUE (sym));
FIELD_BITSIZE (fields[num_fields]) = 0;
- FIELD_STATIC_KIND (fields[num_fields]) = 0;
num_fields++;
}
xfree (fields);
}
if (unsigned_enum)
- TYPE_FLAGS (this_type) |= TYPE_FLAG_UNSIGNED;
+ TYPE_UNSIGNED (this_type) = 1;
}
new_symbol (die, this_type, cu);
type_flags = gdbarch_address_class_type_flags
(gdbarch, byte_size, addr_class);
- gdb_assert ((type_flags & ~TYPE_FLAG_ADDRESS_CLASS_ALL) == 0);
+ gdb_assert ((type_flags & ~TYPE_INSTANCE_FLAG_ADDRESS_CLASS_ALL)
+ == 0);
type = make_type_with_address_space (type, type_flags);
}
else if (TYPE_LENGTH (type) != byte_size)
|| cu->language == language_cplus
|| cu->language == language_java
|| cu->language == language_pascal)
- TYPE_FLAGS (ftype) |= TYPE_FLAG_PROTOTYPED;
+ TYPE_PROTOTYPED (ftype) = 1;
/* Store the calling convention in the type if it's available in
the subroutine die. Otherwise set the calling convention to
if (child_die->tag == DW_TAG_formal_parameter)
nparams++;
else if (child_die->tag == DW_TAG_unspecified_parameters)
- TYPE_FLAGS (ftype) |= TYPE_FLAG_VARARGS;
+ TYPE_VARARGS (ftype) = 1;
child_die = sibling_die (child_die);
}
TYPE_TARGET_TYPE (type) = target_type;
if (name && strcmp (name, "char") == 0)
- TYPE_FLAGS (type) |= TYPE_FLAG_NOSIGN;
+ TYPE_NOSIGN (type) = 1;
return set_die_type (die, type, cu);
}
return read_die_and_children (info_ptr, abfd, cu, &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,
+ gdb_byte **new_info_ptr,
+ struct die_info *parent)
+{
+ struct die_info *result = read_die_and_children_1 (info_ptr, abfd, cu,
+ new_info_ptr, parent);
+
+ if (dwarf2_die_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog, "Read die from .debug_info:\n");
+ dump_die (result, dwarf2_die_debug);
+ }
+
+ return result;
+}
+
/* Read a single die and all its descendents. Set the die's sibling
field to NULL; set other fields in the die correctly, and set all
of the descendents' fields correctly. Set *NEW_INFO_PTR to the
is the parent of the die in question. */
static struct die_info *
-read_die_and_children (gdb_byte *info_ptr, bfd *abfd,
- struct dwarf2_cu *cu,
- gdb_byte **new_info_ptr,
- struct die_info *parent)
+read_die_and_children_1 (gdb_byte *info_ptr, bfd *abfd,
+ struct dwarf2_cu *cu,
+ gdb_byte **new_info_ptr,
+ struct die_info *parent)
{
struct die_info *die;
gdb_byte *cur_ptr;
while (1)
{
struct die_info *die
- = read_die_and_children (cur_ptr, abfd, cu, &cur_ptr, parent);
+ = read_die_and_children_1 (cur_ptr, abfd, cu, &cur_ptr, parent);
if (die == NULL)
{
&& !is_type_tag_for_partial (abbrev->tag)
&& abbrev->tag != DW_TAG_enumerator
&& abbrev->tag != DW_TAG_subprogram
+ && abbrev->tag != DW_TAG_lexical_block
&& abbrev->tag != DW_TAG_variable
&& abbrev->tag != DW_TAG_namespace
&& abbrev->tag != DW_TAG_member)
sizeof (struct partial_die_info));
/* For some DIEs we want to follow their children (if any). For C
- we have no reason to follow the children of structures; for other
+ we have no reason to follow the children of structures; for other
languages we have to, both so that we can get at method physnames
- to infer fully qualified class names, and for DW_AT_specification. */
+ to infer fully qualified class names, and for DW_AT_specification.
+
+ For Ada, we need to scan the children of subprograms and lexical
+ blocks as well because Ada allows the definition of nested
+ entities that could be interesting for the debugger, such as
+ nested subprograms for instance. */
if (last_die->has_children
&& (load_all
|| last_die->tag == DW_TAG_namespace
&& (last_die->tag == DW_TAG_class_type
|| last_die->tag == DW_TAG_interface_type
|| last_die->tag == DW_TAG_structure_type
- || last_die->tag == DW_TAG_union_type))))
+ || last_die->tag == DW_TAG_union_type))
+ || (cu->language == language_ada
+ && (last_die->tag == DW_TAG_subprogram
+ || last_die->tag == DW_TAG_lexical_block))))
{
nesting_level++;
parent_die = last_die;
case DW_AT_specification:
case DW_AT_extension:
part_die->has_specification = 1;
- part_die->spec_offset = dwarf2_get_ref_die_offset (&attr, cu);
+ part_die->spec_offset = dwarf2_get_ref_die_offset (&attr);
break;
case DW_AT_sibling:
/* Ignore absolute siblings, they might point outside of
complaint (&symfile_complaints, _("ignoring absolute DW_AT_sibling"));
else
part_die->sibling = dwarf2_per_objfile->info_buffer
- + dwarf2_get_ref_die_offset (&attr, cu);
+ + dwarf2_get_ref_die_offset (&attr);
break;
case DW_AT_stmt_list:
part_die->has_stmt_list = 1;
|| dwarf2_per_objfile->has_section_at_zero))
part_die->has_pc_info = 1;
- if (base_address_type != base_address_none && !cu->header.base_known)
+ if (base_address_type != base_address_none && !cu->base_known)
{
gdb_assert (part_die->tag == DW_TAG_compile_unit);
- cu->header.base_known = 1;
- cu->header.base_address = base_address;
+ cu->base_known = 1;
+ cu->base_address = base_address;
}
return info_ptr;
/* Find a cached partial DIE at OFFSET in CU. */
static struct partial_die_info *
-find_partial_die_in_comp_unit (unsigned long offset, struct dwarf2_cu *cu)
+find_partial_die_in_comp_unit (unsigned int offset, struct dwarf2_cu *cu)
{
struct partial_die_info *lookup_die = NULL;
struct partial_die_info part_die;
/* Find a partial DIE at OFFSET, which may or may not be in CU. */
static struct partial_die_info *
-find_partial_die (unsigned long offset, struct dwarf2_cu *cu)
+find_partial_die (unsigned int offset, struct dwarf2_cu *cu)
{
struct dwarf2_per_cu_data *per_cu = NULL;
struct partial_die_info *pd = NULL;
- if (offset >= cu->header.offset
- && offset < cu->header.offset + cu->header.length)
+ if (offset_in_cu_p (&cu->header, offset))
{
pd = find_partial_die_in_comp_unit (offset, cu);
if (pd != NULL)
dwarf2_read_abbrevs (per_cu->cu->objfile->obfd, per_cu->cu);
back_to = make_cleanup (dwarf2_free_abbrev_table, per_cu->cu);
}
- info_ptr = per_cu->cu->header.first_die_ptr;
+ info_ptr = (dwarf2_per_objfile->info_buffer
+ + per_cu->cu->header.offset
+ + 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,
if (pd == NULL)
internal_error (__FILE__, __LINE__,
- _("could not find partial DIE 0x%lx in cache [from module %s]\n"),
+ _("could not find partial DIE 0x%x in cache [from module %s]\n"),
offset, bfd_get_filename (cu->objfile->obfd));
return pd;
}
The value returned via bytes_read should be used to increment the
relevant pointer after calling read_initial_length().
-
- As a side effect, this function sets the fields initial_length_size
- and offset_size in cu_header to the values appropriate for the
- length field. (The format of the initial length field determines
- the width of file offsets to be fetched later with read_offset().)
-
+
[ Note: read_initial_length() and read_offset() are based on the
document entitled "DWARF Debugging Information Format", revision
3, draft 8, dated November 19, 2001. This document was obtained
] */
static LONGEST
-read_initial_length (bfd *abfd, gdb_byte *buf, struct comp_unit_head *cu_header,
- unsigned int *bytes_read)
+read_initial_length (bfd *abfd, gdb_byte *buf, unsigned int *bytes_read)
{
LONGEST length = bfd_get_32 (abfd, buf);
*bytes_read = 4;
}
- if (cu_header)
- {
- gdb_assert (cu_header->initial_length_size == 0
- || cu_header->initial_length_size == 4
- || cu_header->initial_length_size == 8
- || cu_header->initial_length_size == 12);
+ return length;
+}
- if (cu_header->initial_length_size != 0
- && cu_header->initial_length_size != *bytes_read)
- complaint (&symfile_complaints,
- _("intermixed 32-bit and 64-bit DWARF sections"));
+/* Cover function for read_initial_length.
+ Returns the length of the object at BUF, and stores the size of the
+ initial length in *BYTES_READ and stores the size that offsets will be in
+ *OFFSET_SIZE.
+ If the initial length size is not equivalent to that specified in
+ CU_HEADER then issue a complaint.
+ This is useful when reading non-comp-unit headers. */
- cu_header->initial_length_size = *bytes_read;
- cu_header->offset_size = (*bytes_read == 4) ? 4 : 8;
- }
+static LONGEST
+read_checked_initial_length_and_offset (bfd *abfd, gdb_byte *buf,
+ const struct comp_unit_head *cu_header,
+ unsigned int *bytes_read,
+ unsigned int *offset_size)
+{
+ LONGEST length = read_initial_length (abfd, buf, bytes_read);
+ gdb_assert (cu_header->initial_length_size == 4
+ || cu_header->initial_length_size == 8
+ || cu_header->initial_length_size == 12);
+
+ if (cu_header->initial_length_size != *bytes_read)
+ complaint (&symfile_complaints,
+ _("intermixed 32-bit and 64-bit DWARF sections"));
+
+ *offset_size = (*bytes_read == 4) ? 4 : 8;
return length;
}
static LONGEST
read_offset (bfd *abfd, gdb_byte *buf, const struct comp_unit_head *cu_header,
unsigned int *bytes_read)
+{
+ LONGEST offset = read_offset_1 (abfd, buf, cu_header->offset_size);
+ *bytes_read = cu_header->offset_size;
+ return offset;
+}
+
+/* Read an offset from the data stream. */
+
+static LONGEST
+read_offset_1 (bfd *abfd, gdb_byte *buf, unsigned int offset_size)
{
LONGEST retval = 0;
- switch (cu_header->offset_size)
+ switch (offset_size)
{
case 4:
retval = bfd_get_32 (abfd, buf);
- *bytes_read = 4;
break;
case 8:
retval = bfd_get_64 (abfd, buf);
- *bytes_read = 8;
break;
default:
internal_error (__FILE__, __LINE__,
- _("read_offset: bad switch [in module %s]"),
+ _("read_offset_1: bad switch [in module %s]"),
bfd_get_filename (abfd));
}
const struct comp_unit_head *cu_header,
unsigned int *bytes_read_ptr)
{
- LONGEST str_offset = read_offset (abfd, buf, cu_header,
- bytes_read_ptr);
+ LONGEST str_offset = read_offset (abfd, buf, cu_header, bytes_read_ptr);
if (dwarf2_per_objfile->str_buffer == NULL)
{
struct cleanup *back_to;
struct line_header *lh;
gdb_byte *line_ptr;
- unsigned int bytes_read;
+ unsigned int bytes_read, offset_size;
int i;
char *cur_dir, *cur_file;
/* Read in the header. */
lh->total_length =
- read_initial_length (abfd, line_ptr, &cu->header, &bytes_read);
+ read_checked_initial_length_and_offset (abfd, line_ptr, &cu->header,
+ &bytes_read, &offset_size);
line_ptr += bytes_read;
if (line_ptr + lh->total_length > (dwarf2_per_objfile->line_buffer
+ dwarf2_per_objfile->line_size))
lh->statement_program_end = line_ptr + lh->total_length;
lh->version = read_2_bytes (abfd, line_ptr);
line_ptr += 2;
- lh->header_length = read_offset (abfd, line_ptr, &cu->header, &bytes_read);
- line_ptr += bytes_read;
+ lh->header_length = read_offset_1 (abfd, line_ptr, offset_size);
+ line_ptr += offset_size;
lh->minimum_instruction_length = read_1_byte (abfd, line_ptr);
line_ptr += 1;
lh->default_is_stmt = read_1_byte (abfd, line_ptr);
{
op_code = read_1_byte (abfd, line_ptr);
line_ptr += 1;
+ if (line_ptr > line_end)
+ {
+ dwarf2_debug_line_missing_end_sequence_complaint ();
+ break;
+ }
if (op_code >= lh->opcode_base)
{
address += (adj_opcode / lh->line_range)
* lh->minimum_instruction_length;
line += lh->line_base + (adj_opcode % lh->line_range);
- if (lh->num_file_names < file)
+ if (lh->num_file_names < file || file == 0)
dwarf2_debug_line_missing_file_complaint ();
else
{
{
case DW_LNE_end_sequence:
end_sequence = 1;
-
- if (lh->num_file_names < file)
- dwarf2_debug_line_missing_file_complaint ();
- else
- {
- lh->file_names[file - 1].included_p = 1;
- if (!decode_for_pst_p)
- record_line (current_subfile, 0, address);
- }
break;
case DW_LNE_set_address:
address = read_address (abfd, line_ptr, cu, &bytes_read);
}
break;
case DW_LNS_copy:
- if (lh->num_file_names < file)
+ if (lh->num_file_names < file || file == 0)
dwarf2_debug_line_missing_file_complaint ();
else
{
file = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
line_ptr += bytes_read;
- if (lh->num_file_names < file)
+ if (lh->num_file_names < file || file == 0)
dwarf2_debug_line_missing_file_complaint ();
else
{
}
}
}
+ if (lh->num_file_names < file || file == 0)
+ dwarf2_debug_line_missing_file_complaint ();
+ else
+ {
+ lh->file_names[file - 1].included_p = 1;
+ if (!decode_for_pst_p)
+ record_line (current_subfile, 0, address);
+ }
}
if (decode_for_pst_p)
type = tag_type_to_type (type_die, cu);
if (!type)
{
- dump_die (type_die);
+ dump_die_for_error (type_die);
error (_("Dwarf Error: Problem turning type die at offset into gdb type [in module %s]"),
cu->objfile->name);
}
if (!type)
{
if (type_die)
- dump_die (type_die);
+ dump_die_for_error (type_die);
error (_("Dwarf Error: Problem turning containing type into gdb type [in module %s]"),
cu->objfile->name);
}
this_type = read_type_die (die, cu);
if (!this_type)
{
- dump_die (die);
+ dump_die_for_error (die);
error (_("Dwarf Error: Cannot find type of die [in module %s]"),
cu->objfile->name);
}
else
sep = "::";
+ if (prefix == NULL)
+ prefix = "";
+ if (suffix == NULL)
+ suffix = "";
+
if (obs == NULL)
{
char *retval = xmalloc (strlen (prefix) + MAX_SEP_LEN + strlen (suffix) + 1);
- retval[0] = '\0';
-
- if (prefix)
- {
- strcpy (retval, prefix);
- strcat (retval, sep);
- }
- if (suffix)
- strcat (retval, suffix);
-
+ strcpy (retval, prefix);
+ strcat (retval, sep);
+ strcat (retval, suffix);
return retval;
}
else
return "DW_AT_pure";
case DW_AT_recursive:
return "DW_AT_recursive";
-#ifdef MIPS
/* SGI/MIPS extensions. */
+#ifdef MIPS /* collides with DW_AT_HP_block_index */
case DW_AT_MIPS_fde:
return "DW_AT_MIPS_fde";
+#endif
case DW_AT_MIPS_loop_begin:
return "DW_AT_MIPS_loop_begin";
case DW_AT_MIPS_tail_loop_begin:
return "DW_AT_MIPS_clone_origin";
case DW_AT_MIPS_has_inlines:
return "DW_AT_MIPS_has_inlines";
-#endif
/* HP extensions. */
+#ifndef MIPS /* collides with DW_AT_MIPS_fde */
case DW_AT_HP_block_index:
return "DW_AT_HP_block_index";
+#endif
case DW_AT_HP_unmodifiable:
return "DW_AT_HP_unmodifiable";
case DW_AT_HP_actuals_stmt_list:
#endif
static void
-dump_die (struct die_info *die)
+dump_die_shallow (struct ui_file *f, int indent, struct die_info *die)
{
unsigned int i;
- fprintf_unfiltered (gdb_stderr, "Die: %s (abbrev = %d, offset = %d)\n",
+ print_spaces (indent, f);
+ fprintf_unfiltered (f, "Die: %s (abbrev %d, offset 0x%x)\n",
dwarf_tag_name (die->tag), die->abbrev, die->offset);
- fprintf_unfiltered (gdb_stderr, "\thas children: %s\n",
+
+ if (die->parent != NULL)
+ {
+ print_spaces (indent, f);
+ fprintf_unfiltered (f, " parent at offset: 0x%x\n",
+ die->parent->offset);
+ }
+
+ print_spaces (indent, f);
+ fprintf_unfiltered (f, " has children: %s\n",
dwarf_bool_name (die->child != NULL));
- fprintf_unfiltered (gdb_stderr, "\tattributes:\n");
+ print_spaces (indent, f);
+ fprintf_unfiltered (f, " attributes:\n");
+
for (i = 0; i < die->num_attrs; ++i)
{
- fprintf_unfiltered (gdb_stderr, "\t\t%s (%s) ",
+ print_spaces (indent, f);
+ fprintf_unfiltered (f, " %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_unfiltered (gdb_stderr, "address: ");
- fputs_filtered (paddress (DW_ADDR (&die->attrs[i])), gdb_stderr);
+ fprintf_unfiltered (f, "address: ");
+ fputs_filtered (paddress (DW_ADDR (&die->attrs[i])), f);
break;
case DW_FORM_block2:
case DW_FORM_block4:
case DW_FORM_block:
case DW_FORM_block1:
- fprintf_unfiltered (gdb_stderr, "block: size %d", DW_BLOCK (&die->attrs[i])->size);
+ fprintf_unfiltered (f, "block: size %d", DW_BLOCK (&die->attrs[i])->size);
break;
case DW_FORM_ref1:
case DW_FORM_ref2:
case DW_FORM_ref4:
- fprintf_unfiltered (gdb_stderr, "constant ref: %ld (adjusted)",
+ fprintf_unfiltered (f, "constant ref: 0x%lx (adjusted)",
(long) (DW_ADDR (&die->attrs[i])));
break;
case DW_FORM_data1:
case DW_FORM_data8:
case DW_FORM_udata:
case DW_FORM_sdata:
- fprintf_unfiltered (gdb_stderr, "constant: %ld", DW_UNSND (&die->attrs[i]));
+ fprintf_unfiltered (f, "constant: %ld", DW_UNSND (&die->attrs[i]));
break;
case DW_FORM_string:
case DW_FORM_strp:
- fprintf_unfiltered (gdb_stderr, "string: \"%s\"",
+ fprintf_unfiltered (f, "string: \"%s\"",
DW_STRING (&die->attrs[i])
? DW_STRING (&die->attrs[i]) : "");
break;
case DW_FORM_flag:
if (DW_UNSND (&die->attrs[i]))
- fprintf_unfiltered (gdb_stderr, "flag: TRUE");
+ fprintf_unfiltered (f, "flag: TRUE");
else
- fprintf_unfiltered (gdb_stderr, "flag: FALSE");
+ fprintf_unfiltered (f, "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");
+ fprintf_unfiltered (f, "unexpected attribute form: DW_FORM_indirect");
break;
default:
- fprintf_unfiltered (gdb_stderr, "unsupported attribute form: %d.",
+ fprintf_unfiltered (f, "unsupported attribute form: %d.",
die->attrs[i].form);
+ break;
}
- fprintf_unfiltered (gdb_stderr, "\n");
+ fprintf_unfiltered (f, "\n");
}
}
static void
-dump_die_list (struct die_info *die)
+dump_die_for_error (struct die_info *die)
+{
+ dump_die_shallow (gdb_stderr, 0, die);
+}
+
+static void
+dump_die_1 (struct ui_file *f, int level, int max_level, struct die_info *die)
{
- while (die)
+ int indent = level * 4;
+
+ gdb_assert (die != NULL);
+
+ if (level >= max_level)
+ return;
+
+ dump_die_shallow (f, indent, die);
+
+ if (die->child != NULL)
+ {
+ print_spaces (indent, f);
+ fprintf_unfiltered (f, " Children:");
+ if (level + 1 < max_level)
+ {
+ fprintf_unfiltered (f, "\n");
+ dump_die_1 (f, level + 1, max_level, die->child);
+ }
+ else
+ {
+ fprintf_unfiltered (f, " [not printed, max nesting level reached]\n");
+ }
+ }
+
+ if (die->sibling != NULL && level > 0)
{
- dump_die (die);
- if (die->child != NULL)
- dump_die_list (die->child);
- if (die->sibling != NULL)
- dump_die_list (die->sibling);
+ dump_die_1 (f, level, max_level, die->sibling);
}
}
+/* This is called from the pdie macro in gdbinit.in.
+ It's not static so gcc will keep a copy callable from gdb. */
+
+void
+dump_die (struct die_info *die, int max_level)
+{
+ dump_die_1 (gdb_stdlog, 0, max_level, die);
+}
+
static void
store_in_ref_table (struct die_info *die, struct dwarf2_cu *cu)
{
}
static unsigned int
-dwarf2_get_ref_die_offset (struct attribute *attr, struct dwarf2_cu *cu)
+dwarf2_get_ref_die_offset (struct attribute *attr)
{
unsigned int result = 0;
struct die_info temp_die;
struct dwarf2_cu *target_cu, *cu = *ref_cu;
- offset = dwarf2_get_ref_die_offset (attr, cu);
+ offset = dwarf2_get_ref_die_offset (attr);
- if (DW_ADDR (attr) < cu->header.offset
- || DW_ADDR (attr) >= cu->header.offset + cu->header.length)
+ if (! offset_in_cu_p (&cu->header, offset))
{
struct dwarf2_per_cu_data *per_cu;
- per_cu = dwarf2_find_containing_comp_unit (DW_ADDR (attr),
- cu->objfile);
+ per_cu = dwarf2_find_containing_comp_unit (offset, cu->objfile);
/* If necessary, add it to the queue and load its DIEs. */
maybe_queue_comp_unit (cu, per_cu);
don't run off the edge of the section. */
baton->size = dwarf2_per_objfile->loc_size - DW_UNSND (attr);
baton->data = dwarf2_per_objfile->loc_buffer + DW_UNSND (attr);
- baton->base_address = cu->header.base_address;
- if (cu->header.base_known == 0)
+ baton->base_address = cu->base_address;
+ if (cu->base_known == 0)
complaint (&symfile_complaints,
_("Location list used without specifying the CU base address."));
DIE at OFFSET. Raises an error on failure. */
static struct dwarf2_per_cu_data *
-dwarf2_find_containing_comp_unit (unsigned long offset,
+dwarf2_find_containing_comp_unit (unsigned int offset,
struct objfile *objfile)
{
struct dwarf2_per_cu_data *this_cu;
this_cu = dwarf2_per_objfile->all_comp_units[low];
if (low == dwarf2_per_objfile->n_comp_units - 1
&& offset >= this_cu->offset + this_cu->length)
- error (_("invalid dwarf2 offset %ld"), offset);
+ error (_("invalid dwarf2 offset %u"), offset);
gdb_assert (offset < this_cu->offset + this_cu->length);
return this_cu;
}
OFFSET. Raises an error on failure. */
static struct dwarf2_per_cu_data *
-dwarf2_find_comp_unit (unsigned long offset, struct objfile *objfile)
+dwarf2_find_comp_unit (unsigned int offset, struct objfile *objfile)
{
struct dwarf2_per_cu_data *this_cu;
this_cu = dwarf2_find_containing_comp_unit (offset, objfile);
if (this_cu->offset != offset)
- error (_("no compilation unit with offset %ld."), offset);
+ error (_("no compilation unit with offset %u."), offset);
return this_cu;
}
show_dwarf2_max_cache_age,
&set_dwarf2_cmdlist,
&show_dwarf2_cmdlist);
+
+ add_setshow_zinteger_cmd ("dwarf2-die", no_class, &dwarf2_die_debug, _("\
+Set debugging of the dwarf2 DIE reader."), _("\
+Show debugging of the dwarf2 DIE reader."), _("\
+When enabled (non-zero), DIEs are dumped after they are read in.\n\
+The value is the maximum depth to print."),
+ NULL,
+ NULL,
+ &setdebuglist, &showdebuglist);
}