unsigned int offset;
unsigned int abbrev;
char *name;
+ int has_pc_info;
CORE_ADDR lowpc;
CORE_ADDR highpc;
struct dwarf_block *locdesc;
"unsupported const value attribute form: '%s'", 0, 0
};
-/* Externals references. */
-extern int info_verbose; /* From main.c; nonzero => verbose */
-
/* local function prototypes */
static void dwarf2_locate_sections (bfd *, asection *, PTR);
static struct abbrev_info *dwarf2_lookup_abbrev (unsigned int);
static char *read_partial_die (struct partial_die_info *,
- bfd *, char *, int *,
+ bfd *, char *,
const struct comp_unit_head *);
static char *read_full_die (struct die_info **, bfd *, char *,
dwarf_line_offset,
dwarf_line_size);
- if (mainline || objfile->global_psymbols.size == 0 ||
- objfile->static_psymbols.size == 0)
+ if (mainline
+ || (objfile->global_psymbols.size == 0
+ && objfile->static_psymbols.size == 0))
{
init_psymbol_list (objfile, 1024);
}
struct partial_die_info comp_unit_die;
struct partial_symtab *pst;
struct cleanup *back_to;
- int comp_unit_has_pc_info;
CORE_ADDR lowpc, highpc;
info_ptr = dwarf_info_buffer;
abbrev_ptr = dwarf_abbrev_buffer;
+ /* We use dwarf2_tmp_obstack for objects that don't need to survive
+ the partial symbol scan, like attribute values.
+
+ We could reduce our peak memory consumption during partial symbol
+ table construction by freeing stuff from this obstack more often
+ --- say, after processing each compilation unit, or each die ---
+ but it turns out that this saves almost nothing. For an
+ executable with 11Mb of Dwarf 2 data, I found about 64k allocated
+ on dwarf2_tmp_obstack. Some investigation showed:
+
+ 1) 69% of the attributes used forms DW_FORM_addr, DW_FORM_data*,
+ DW_FORM_flag, DW_FORM_[su]data, and DW_FORM_ref*. These are
+ all fixed-length values not requiring dynamic allocation.
+
+ 2) 30% of the attributes used the form DW_FORM_string. For
+ DW_FORM_string, read_attribute simply hands back a pointer to
+ the null-terminated string in dwarf_info_buffer, so no dynamic
+ allocation is needed there either.
+
+ 3) The remaining 1% of the attributes all used DW_FORM_block1.
+ 75% of those were DW_AT_frame_base location lists for
+ functions; the rest were DW_AT_location attributes, probably
+ for the global variables.
+
+ Anyway, what this all means is that the memory the dwarf2
+ reader uses as temporary space reading partial symbols is about
+ 0.5% as much as we use for dwarf_*_buffer. That's noise. */
+
obstack_init (&dwarf2_tmp_obstack);
back_to = make_cleanup (dwarf2_free_tmp_obstack, NULL);
+ /* Since the objects we're extracting from dwarf_info_buffer vary in
+ length, only the individual functions to extract them (like
+ read_comp_unit_head and read_partial_die) can really know whether
+ the buffer is large enough to hold another complete object.
+
+ At the moment, they don't actually check that. If
+ dwarf_info_buffer 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.
+
+ For this loop condition, simply checking whether there's any data
+ left at all should be sufficient. */
while (info_ptr < dwarf_info_buffer + dwarf_info_size)
{
struct comp_unit_head cu_header;
/* Read the compilation unit die */
info_ptr = read_partial_die (&comp_unit_die, abfd, info_ptr,
- &comp_unit_has_pc_info, &cu_header);
+ &cu_header);
/* Set the language we're debugging */
set_cu_language (comp_unit_die.language);
/* If the compilation unit didn't have an explicit address range,
then use the information extracted from its child dies. */
- if (!comp_unit_has_pc_info)
+ if (! comp_unit_die.has_pc_info)
{
comp_unit_die.lowpc = lowpc;
comp_unit_die.highpc = highpc;
back to that level. */
int nesting_level = 1;
- int has_pc_info;
*lowpc = ((CORE_ADDR) -1);
*highpc = ((CORE_ADDR) 0);
while (nesting_level)
{
- info_ptr = read_partial_die (&pdi, abfd, info_ptr,
- &has_pc_info, cu_header);
+ info_ptr = read_partial_die (&pdi, abfd, info_ptr, cu_header);
if (pdi.name)
{
switch (pdi.tag)
{
case DW_TAG_subprogram:
- if (has_pc_info)
+ if (pdi.has_pc_info)
{
if (pdi.lowpc < *lowpc)
{
buf = (char *) obstack_alloc (&objfile->psymbol_obstack, size);
if ((bfd_seek (abfd, offset, SEEK_SET) != 0) ||
- (bfd_read (buf, size, 1, abfd) != size))
+ (bfd_bread (buf, size, abfd) != size))
{
buf = NULL;
error ("Dwarf Error: Can't read DWARF data from '%s'",
static char *
read_partial_die (struct partial_die_info *part_die, bfd *abfd,
- char *info_ptr, int *has_pc_info,
- const struct comp_unit_head *cu_header)
+ char *info_ptr, const struct comp_unit_head *cu_header)
{
unsigned int abbrev_number, bytes_read, i;
struct abbrev_info *abbrev;
int has_high_pc_attr = 0;
*part_die = zeroed_partial_die;
- *has_pc_info = 0;
abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
info_ptr += bytes_read;
if (!abbrev_number)
int dummy;
spec_ptr = dwarf_info_buffer + dwarf2_get_ref_die_offset (&spec_attr);
- read_partial_die (&spec_die, abfd, spec_ptr, &dummy, cu_header);
+ read_partial_die (&spec_die, abfd, spec_ptr, cu_header);
if (spec_die.name)
{
part_die->name = spec_die.name;
&& part_die->lowpc < part_die->highpc
&& (part_die->lowpc != 0
|| (bfd_get_file_flags (abfd) & HAS_RELOC)))
- *has_pc_info = 1;
+ part_die->has_pc_info = 1;
return info_ptr;
}