{
unsigned long 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. */
{
/* 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. */
+ - if it doesn't, GDB will fall over anyway.
+ NOTE: Unlike comp_unit_head.length, this length includes
+ initial_length_size. */
unsigned long offset;
unsigned long length : 30;
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
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,
}
#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. */
/* 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;
/* 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);
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. */
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)
{
&& !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;
|| 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;
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,
offset = dwarf2_get_ref_die_offset (attr, cu);
- 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."));