/* DWARF 2 debugging format support for GDB.
- Copyright 1994, 1995, 1996, 1997, 1998, 2001
+ Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
Free Software Foundation, Inc.
Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology,
#include "buildsym.h"
#include "demangle.h"
#include "expression.h"
+#include "filenames.h" /* for DOSish file names */
#include "language.h"
#include "complaints.h"
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 *,
static void read_subroutine_type (struct die_info *, struct objfile *,
const struct comp_unit_head *);
-struct die_info *read_comp_unit (char *, bfd *, const struct comp_unit_head *);
+static struct die_info *read_comp_unit (char *, bfd *,
+ const struct comp_unit_head *);
static void free_die_list (struct die_info *);
struct die_info *copy_die (struct die_info *);
#endif
-struct die_info *sibling_die (struct die_info *);
+static struct die_info *sibling_die (struct die_info *);
-void dump_die (struct die_info *);
+static void dump_die (struct die_info *);
-void dump_die_list (struct die_info *);
+static void dump_die_list (struct die_info *);
-void store_in_ref_table (unsigned int, struct die_info *);
+static void store_in_ref_table (unsigned int, struct die_info *);
static void dwarf2_empty_hash_tables (void);
static unsigned int dwarf2_get_ref_die_offset (struct attribute *);
-struct die_info *follow_die_ref (unsigned int);
+static struct die_info *follow_die_ref (unsigned int);
static struct type *dwarf2_fundamental_type (struct objfile *, int);
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);
- while ((unsigned int) (info_ptr - dwarf_info_buffer)
- + ((info_ptr - dwarf_info_buffer) % 4) < dwarf_info_size)
+ /* 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;
beg_of_comp_unit = info_ptr;
/* 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)
{
/* Read a whole compilation unit into a linked list of dies. */
-struct die_info *
+static struct die_info *
read_comp_unit (char *info_ptr, bfd *abfd,
const struct comp_unit_head *cu_header)
{
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;
}
case DW_LANG_Mips_Assembler:
cu_language = language_asm;
break;
+ case DW_LANG_Java:
+ cu_language = language_java;
+ break;
case DW_LANG_Ada83:
case DW_LANG_Cobol74:
case DW_LANG_Cobol85:
/* If the filename isn't absolute, try to match an existing subfile
with the full pathname. */
- if (*filename != '/' && dirname != NULL)
+ if (!IS_ABSOLUTE_PATH (filename) && dirname != NULL)
{
struct subfile *subfile;
char *fullname = concat (dirname, "/", filename, NULL);
for (subfile = subfiles; subfile; subfile = subfile->next)
{
- if (STREQ (subfile->name, fullname))
+ if (FILENAME_CMP (subfile->name, fullname) == 0)
{
current_subfile = subfile;
xfree (fullname);
/* Return sibling of die, NULL if no sibling. */
-struct die_info *
+static struct die_info *
sibling_die (struct die_info *die)
{
int nesting_level = 0;
}
#endif
-void
+static void
dump_die (struct die_info *die)
{
unsigned int i;
}
}
-void
+static void
dump_die_list (struct die_info *die)
{
while (die)
}
}
-void
+static void
store_in_ref_table (unsigned int offset, struct die_info *die)
{
int h;
return result;
}
-struct die_info *
+static struct die_info *
follow_die_ref (unsigned int offset)
{
struct die_info *die;