/* DWARF 2 debugging format support for GDB.
- Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
+ Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
Free Software Foundation, Inc.
Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology,
#include "expression.h"
#include "filenames.h" /* for DOSish file names */
#include "macrotab.h"
-
#include "language.h"
#include "complaints.h"
#include "bcache.h"
+#include "dwarf2expr.h"
+#include "dwarf2loc.h"
+#include "cp-support.h"
+
#include <fcntl.h>
#include "gdb_string.h"
#include "gdb_assert.h"
unsigned int dwarf_frame_size;
unsigned int dwarf_eh_frame_size;
+static asection *dwarf_info_section;
+static asection *dwarf_abbrev_section;
+static asection *dwarf_line_section;
+static asection *dwarf_pubnames_section;
+static asection *dwarf_aranges_section;
+static asection *dwarf_loc_section;
+static asection *dwarf_macinfo_section;
+static asection *dwarf_str_section;
+static asection *dwarf_ranges_section;
+asection *dwarf_frame_section;
+asection *dwarf_eh_frame_section;
+
/* names of the debugging sections */
#define INFO_SECTION ".debug_info"
struct abbrev_info *dwarf2_abbrevs[ABBREV_HASH_SIZE];
- /* Pointer to the DIE associated with the compilation unit. */
+ /* Base address of this compilation unit. */
- struct die_info *die;
+ CORE_ADDR base_address;
+
+ /* Non-zero if base_address has been set. */
+
+ int base_known;
};
/* The line number information for a compilation unit (found in the
static char *dwarf_str_buffer;
static char *dwarf_macinfo_buffer;
static char *dwarf_ranges_buffer;
+static char *dwarf_loc_buffer;
/* A zeroed version of a partial die for initialization purposes. */
static struct partial_die_info zeroed_partial_die;
unsigned int dwarf_ranges_size;
+ /* Pointer to start of dwarf locations buffer for the objfile. */
+
+ char *dwarf_loc_buffer;
+
+ /* Size of dwarf locations buffer for the objfile. */
+
+ unsigned int dwarf_loc_size;
};
#define PST_PRIVATE(p) ((struct dwarf2_pinfo *)(p)->read_symtab_private)
#define DWARF_MACINFO_SIZE(p) (PST_PRIVATE(p)->dwarf_macinfo_size)
#define DWARF_RANGES_BUFFER(p) (PST_PRIVATE(p)->dwarf_ranges_buffer)
#define DWARF_RANGES_SIZE(p) (PST_PRIVATE(p)->dwarf_ranges_size)
+#define DWARF_LOC_BUFFER(p) (PST_PRIVATE(p)->dwarf_loc_buffer)
+#define DWARF_LOC_SIZE(p) (PST_PRIVATE(p)->dwarf_loc_size)
/* Maintain an array of referenced fundamental types for the current
compilation unit being read. For DWARF version 1, we have to construct
static void psymtab_to_symtab_1 (struct partial_symtab *);
-char *dwarf2_read_section (struct objfile *, file_ptr, unsigned int);
+char *dwarf2_read_section (struct objfile *, file_ptr, unsigned int,
+ asection *);
static void dwarf2_read_abbrevs (bfd *abfd, struct comp_unit_head *cu_header);
static char *dwarf2_linkage_name (struct die_info *);
+static char *dwarf2_name (struct die_info *die);
+
+static struct die_info *dwarf2_extension (struct die_info *die);
+
static char *dwarf_tag_name (unsigned int);
static char *dwarf_attr_name (unsigned int);
static int attr_form_is_block (struct attribute *);
+static void
+dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym,
+ const struct comp_unit_head *,
+ struct objfile *objfile);
+
/* Try to locate the sections we need for DWARF 2 debugging
information and return true if we have enough to do something. */
dwarf_frame_offset = 0;
dwarf_eh_frame_offset = 0;
dwarf_ranges_offset = 0;
+ dwarf_loc_offset = 0;
bfd_map_over_sections (abfd, dwarf2_locate_sections, NULL);
if (dwarf_info_offset && dwarf_abbrev_offset)
{
dwarf_info_offset = sectp->filepos;
dwarf_info_size = bfd_get_section_size_before_reloc (sectp);
+ dwarf_info_section = sectp;
}
else if (STREQ (sectp->name, ABBREV_SECTION))
{
dwarf_abbrev_offset = sectp->filepos;
dwarf_abbrev_size = bfd_get_section_size_before_reloc (sectp);
+ dwarf_abbrev_section = sectp;
}
else if (STREQ (sectp->name, LINE_SECTION))
{
dwarf_line_offset = sectp->filepos;
dwarf_line_size = bfd_get_section_size_before_reloc (sectp);
+ dwarf_line_section = sectp;
}
else if (STREQ (sectp->name, PUBNAMES_SECTION))
{
dwarf_pubnames_offset = sectp->filepos;
dwarf_pubnames_size = bfd_get_section_size_before_reloc (sectp);
+ dwarf_pubnames_section = sectp;
}
else if (STREQ (sectp->name, ARANGES_SECTION))
{
dwarf_aranges_offset = sectp->filepos;
dwarf_aranges_size = bfd_get_section_size_before_reloc (sectp);
+ dwarf_aranges_section = sectp;
}
else if (STREQ (sectp->name, LOC_SECTION))
{
dwarf_loc_offset = sectp->filepos;
dwarf_loc_size = bfd_get_section_size_before_reloc (sectp);
+ dwarf_loc_section = sectp;
}
else if (STREQ (sectp->name, MACINFO_SECTION))
{
dwarf_macinfo_offset = sectp->filepos;
dwarf_macinfo_size = bfd_get_section_size_before_reloc (sectp);
+ dwarf_macinfo_section = sectp;
}
else if (STREQ (sectp->name, STR_SECTION))
{
dwarf_str_offset = sectp->filepos;
dwarf_str_size = bfd_get_section_size_before_reloc (sectp);
+ dwarf_str_section = sectp;
}
else if (STREQ (sectp->name, FRAME_SECTION))
{
dwarf_frame_offset = sectp->filepos;
dwarf_frame_size = bfd_get_section_size_before_reloc (sectp);
+ dwarf_frame_section = sectp;
}
else if (STREQ (sectp->name, EH_FRAME_SECTION))
{
dwarf_eh_frame_offset = sectp->filepos;
dwarf_eh_frame_size = bfd_get_section_size_before_reloc (sectp);
+ dwarf_eh_frame_section = sectp;
}
else if (STREQ (sectp->name, RANGES_SECTION))
{
dwarf_ranges_offset = sectp->filepos;
dwarf_ranges_size = bfd_get_section_size_before_reloc (sectp);
+ dwarf_ranges_section = sectp;
}
}
dwarf_info_buffer = dwarf2_read_section (objfile,
dwarf_info_offset,
- dwarf_info_size);
+ dwarf_info_size,
+ dwarf_info_section);
dwarf_abbrev_buffer = dwarf2_read_section (objfile,
dwarf_abbrev_offset,
- dwarf_abbrev_size);
+ dwarf_abbrev_size,
+ dwarf_abbrev_section);
if (dwarf_line_offset)
dwarf_line_buffer = dwarf2_read_section (objfile,
dwarf_line_offset,
- dwarf_line_size);
+ dwarf_line_size,
+ dwarf_line_section);
else
dwarf_line_buffer = NULL;
if (dwarf_str_offset)
dwarf_str_buffer = dwarf2_read_section (objfile,
dwarf_str_offset,
- dwarf_str_size);
+ dwarf_str_size,
+ dwarf_str_section);
else
dwarf_str_buffer = NULL;
if (dwarf_macinfo_offset)
dwarf_macinfo_buffer = dwarf2_read_section (objfile,
dwarf_macinfo_offset,
- dwarf_macinfo_size);
+ dwarf_macinfo_size,
+ dwarf_macinfo_section);
else
dwarf_macinfo_buffer = NULL;
if (dwarf_ranges_offset)
dwarf_ranges_buffer = dwarf2_read_section (objfile,
dwarf_ranges_offset,
- dwarf_ranges_size);
+ dwarf_ranges_size,
+ dwarf_ranges_section);
else
dwarf_ranges_buffer = NULL;
+ if (dwarf_loc_offset)
+ dwarf_loc_buffer = dwarf2_read_section (objfile,
+ dwarf_loc_offset,
+ dwarf_loc_size,
+ dwarf_loc_section);
+ else
+ dwarf_loc_buffer = NULL;
+
if (mainline
|| (objfile->global_psymbols.size == 0
&& objfile->static_psymbols.size == 0))
pubnames_buffer = dwarf2_read_section (objfile,
dwarf_pubnames_offset,
- dwarf_pubnames_size);
+ dwarf_pubnames_size,
+ dwarf_pubnames_section);
pubnames_ptr = pubnames_buffer;
while ((pubnames_ptr - pubnames_buffer) < dwarf_pubnames_size)
{
aranges_buffer = dwarf2_read_section (objfile,
dwarf_aranges_offset,
- dwarf_aranges_size);
+ dwarf_aranges_size,
+ dwarf_aranges_section);
}
#endif
if (cu_header.version != 2)
{
- error ("Dwarf Error: wrong version in compilation unit header.");
+ error ("Dwarf Error: wrong version in compilation unit header (is %d, should be %d) [in module %s]", cu_header.version, 2, bfd_get_filename (abfd));
return;
}
if (cu_header.abbrev_offset >= dwarf_abbrev_size)
{
- error ("Dwarf Error: bad offset (0x%lx) in compilation unit header (offset 0x%lx + 6).",
+ error ("Dwarf Error: bad offset (0x%lx) in compilation unit header (offset 0x%lx + 6) [in module %s]",
(long) cu_header.abbrev_offset,
- (long) (beg_of_comp_unit - dwarf_info_buffer));
+ (long) (beg_of_comp_unit - dwarf_info_buffer),
+ bfd_get_filename (abfd));
return;
}
if (beg_of_comp_unit + cu_header.length + cu_header.initial_length_size
> dwarf_info_buffer + dwarf_info_size)
{
- error ("Dwarf Error: bad length (0x%lx) in compilation unit header (offset 0x%lx + 0).",
+ error ("Dwarf Error: bad length (0x%lx) in compilation unit header (offset 0x%lx + 0) [in module %s]",
(long) cu_header.length,
- (long) (beg_of_comp_unit - dwarf_info_buffer));
+ (long) (beg_of_comp_unit - dwarf_info_buffer),
+ bfd_get_filename (abfd));
return;
}
/* Complete the cu_header */
DWARF_MACINFO_SIZE (pst) = dwarf_macinfo_size;
DWARF_RANGES_BUFFER (pst) = dwarf_ranges_buffer;
DWARF_RANGES_SIZE (pst) = dwarf_ranges_size;
+ DWARF_LOC_BUFFER (pst) = dwarf_loc_buffer;
+ DWARF_LOC_SIZE (pst) = dwarf_loc_size;
baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
/* Store the function that reads in the rest of the symbol table */
/*prim_record_minimal_symbol (pdi->name, pdi->lowpc + baseaddr,
mst_text, objfile); */
add_psymbol_to_list (pdi->name, strlen (pdi->name),
- VAR_NAMESPACE, LOC_BLOCK,
+ VAR_DOMAIN, LOC_BLOCK,
&objfile->global_psymbols,
0, pdi->lowpc + baseaddr, cu_language, objfile);
}
/*prim_record_minimal_symbol (pdi->name, pdi->lowpc + baseaddr,
mst_file_text, objfile); */
add_psymbol_to_list (pdi->name, strlen (pdi->name),
- VAR_NAMESPACE, LOC_BLOCK,
+ VAR_DOMAIN, LOC_BLOCK,
&objfile->static_psymbols,
0, pdi->lowpc + baseaddr, cu_language, objfile);
}
addr = decode_locdesc (pdi->locdesc, objfile, cu_header);
if (pdi->locdesc || pdi->has_type)
add_psymbol_to_list (pdi->name, strlen (pdi->name),
- VAR_NAMESPACE, LOC_STATIC,
+ VAR_DOMAIN, LOC_STATIC,
&objfile->global_psymbols,
0, addr + baseaddr, cu_language, objfile);
}
/*prim_record_minimal_symbol (pdi->name, addr + baseaddr,
mst_file_data, objfile); */
add_psymbol_to_list (pdi->name, strlen (pdi->name),
- VAR_NAMESPACE, LOC_STATIC,
+ VAR_DOMAIN, LOC_STATIC,
&objfile->static_psymbols,
0, addr + baseaddr, cu_language, objfile);
}
case DW_TAG_typedef:
case DW_TAG_base_type:
add_psymbol_to_list (pdi->name, strlen (pdi->name),
- VAR_NAMESPACE, LOC_TYPEDEF,
+ VAR_DOMAIN, LOC_TYPEDEF,
&objfile->static_psymbols,
0, (CORE_ADDR) 0, cu_language, objfile);
break;
if (pdi->has_children == 0)
return;
add_psymbol_to_list (pdi->name, strlen (pdi->name),
- STRUCT_NAMESPACE, LOC_TYPEDEF,
+ STRUCT_DOMAIN, LOC_TYPEDEF,
&objfile->static_psymbols,
0, (CORE_ADDR) 0, cu_language, objfile);
{
/* For C++, these implicitly act as typedefs as well. */
add_psymbol_to_list (pdi->name, strlen (pdi->name),
- VAR_NAMESPACE, LOC_TYPEDEF,
+ VAR_DOMAIN, LOC_TYPEDEF,
&objfile->static_psymbols,
0, (CORE_ADDR) 0, cu_language, objfile);
}
break;
case DW_TAG_enumerator:
add_psymbol_to_list (pdi->name, strlen (pdi->name),
- VAR_NAMESPACE, LOC_CONST,
+ VAR_DOMAIN, LOC_CONST,
&objfile->static_psymbols,
0, (CORE_ADDR) 0, cu_language, objfile);
break;
char *info_ptr;
struct symtab *symtab;
struct cleanup *back_to;
+ struct attribute *attr;
/* Set local variables from the partial symbol table info. */
offset = DWARF_INFO_OFFSET (pst);
dwarf_macinfo_size = DWARF_MACINFO_SIZE (pst);
dwarf_ranges_buffer = DWARF_RANGES_BUFFER (pst);
dwarf_ranges_size = DWARF_RANGES_SIZE (pst);
+ dwarf_loc_buffer = DWARF_LOC_BUFFER (pst);
+ dwarf_loc_size = DWARF_LOC_SIZE (pst);
baseaddr = ANOFFSET (pst->section_offsets, SECT_OFF_TEXT (objfile));
cu_header_offset = offset;
info_ptr = dwarf_info_buffer + offset;
make_cleanup_free_die_list (dies);
+ /* Find the base address of the compilation unit for range lists and
+ location lists. It will normally be specified by DW_AT_low_pc.
+ In DWARF-3 draft 4, the base address could be overridden by
+ 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;
+
+ attr = dwarf_attr (dies, DW_AT_entry_pc);
+ if (attr)
+ {
+ cu_header.base_address = DW_ADDR (attr);
+ cu_header.base_known = 1;
+ }
+ else
+ {
+ attr = dwarf_attr (dies, DW_AT_low_pc);
+ if (attr)
+ {
+ cu_header.base_address = DW_ADDR (attr);
+ cu_header.base_known = 1;
+ }
+ }
+
/* Do line number decoding in read_file_scope () */
- cu_header.die = dies;
process_die (dies, objfile, &cu_header);
if (!dwarf2_get_pc_bounds (dies, &lowpc, &highpc, objfile, &cu_header))
of a function and make GDB `next' properly over inlined functions. */
break;
case DW_TAG_lexical_block:
+ case DW_TAG_try_block:
+ case DW_TAG_catch_block:
read_lexical_block_scope (die, objfile, cu_header);
break;
case DW_TAG_class_type:
case DW_TAG_common_inclusion:
break;
case DW_TAG_namespace:
+ if (!processing_has_namespace_info)
+ {
+ processing_has_namespace_info = 1;
+ processing_current_namespace = "";
+ }
read_namespace (die, objfile, cu_header);
break;
case DW_TAG_imported_declaration:
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. */
+ if (!processing_has_namespace_info)
+ {
+ processing_has_namespace_info = 1;
+ processing_current_namespace = "";
+ }
gdb_assert (!die->has_children);
break;
default:
new = push_context (0, lowpc);
new->name = new_symbol (die, die->type, objfile, cu_header);
+
+ /* If there was a location expression for DW_AT_frame_base above,
+ record it. We still need to decode it above because not all
+ symbols use location expressions exclusively. */
+ if (attr)
+ dwarf2_symbol_mark_computed (attr, new->name, cu_header, objfile);
+
list_in_scope = &local_symbols;
if (die->has_children)
.debug_renges section. */
unsigned int offset = DW_UNSND (attr);
/* Base address selection entry. */
- CORE_ADDR base = 0;
- int found_base = 0;
+ CORE_ADDR base;
+ int found_base;
int dummy;
unsigned int i;
char *buffer;
CORE_ADDR marker;
int low_set;
- /* The applicable base address is determined by (1) the closest
- preceding base address selection entry in the range list or
- (2) the DW_AT_low_pc of the compilation unit. */
-
- /* ??? Was in dwarf3 draft4, and has since been removed.
- GCC still uses it though. */
- attr = dwarf_attr (cu_header->die, DW_AT_entry_pc);
- if (attr)
- {
- base = DW_ADDR (attr);
- found_base = 1;
- }
-
- if (!found_base)
- {
- attr = dwarf_attr (cu_header->die, DW_AT_low_pc);
- if (attr)
- {
- base = DW_ADDR (attr);
- found_base = 1;
- }
- }
-
+ found_base = cu_header->base_known;
+ base = cu_header->base_address;
buffer = dwarf_ranges_buffer + offset;
-
/* Read in the largest possible address. */
marker = read_address (obfd, buffer, cu_header, &dummy);
if ((marker & mask) == mask)
return 0;
}
+ range_beginning += base;
+ range_end += base;
+
/* FIXME: This is recording everything as a low-high
segment of consecutive addresses. We should have a
data structure for discontiguous block ranges
* sizeof (struct field));
}
- FIELD_NAME (fields[num_fields]) = SYMBOL_NAME (sym);
+ FIELD_NAME (fields[num_fields]) = DEPRECATED_SYMBOL_NAME (sym);
FIELD_TYPE (fields[num_fields]) = NULL;
FIELD_BITPOS (fields[num_fields]) = SYMBOL_VALUE (sym);
FIELD_BITSIZE (fields[num_fields]) = 0;
/* Read a C++ namespace. */
-/* FIXME: carlton/2002-10-16: For now, we don't actually do anything
- useful with the namespace data: we just process its children. */
-
static void
read_namespace (struct die_info *die, struct objfile *objfile,
const struct comp_unit_head *cu_header)
{
+ const char *previous_namespace = processing_current_namespace;
+ const char *name = NULL;
+ int is_anonymous;
+ struct die_info *current_die;
+
+ /* Loop through the extensions until we find a name. */
+
+ for (current_die = die;
+ current_die != NULL;
+ current_die = dwarf2_extension (die))
+ {
+ name = dwarf2_name (current_die);
+ if (name != NULL)
+ break;
+ }
+
+ /* Is it an anonymous namespace? */
+
+ is_anonymous = (name == NULL);
+ if (is_anonymous)
+ name = "(anonymous namespace)";
+
+ /* Now build the name of the current namespace. */
+
+ if (previous_namespace[0] == '\0')
+ {
+ processing_current_namespace = name;
+ }
+ else
+ {
+ /* We need temp_name around because processing_current_namespace
+ is a const char *. */
+ char *temp_name = alloca (strlen (previous_namespace)
+ + 2 + strlen(name) + 1);
+ strcpy (temp_name, previous_namespace);
+ strcat (temp_name, "::");
+ strcat (temp_name, name);
+
+ processing_current_namespace = temp_name;
+ }
+
+ /* If it's an anonymous namespace that we're seeing for the first
+ time, add a using directive. */
+
+ if (is_anonymous && dwarf_attr (die, DW_AT_extension) == NULL)
+ cp_add_using_directive (processing_current_namespace,
+ strlen (previous_namespace),
+ strlen (processing_current_namespace));
+
if (die->has_children)
{
struct die_info *child_die = die->next;
child_die = sibling_die (child_die);
}
}
+
+ processing_current_namespace = previous_namespace;
}
/* Extract all information from a DW_TAG_pointer_type DIE and add to
char *
dwarf2_read_section (struct objfile *objfile, file_ptr offset,
- unsigned int size)
+ unsigned int size, asection *sectp)
{
bfd *abfd = objfile->obfd;
- char *buf;
+ char *buf, *retbuf;
if (size == 0)
return NULL;
buf = (char *) obstack_alloc (&objfile->psymbol_obstack, size);
+ retbuf
+ = (char *) symfile_relocate_debug_section (abfd, sectp, (bfd_byte *) buf);
+ if (retbuf != NULL)
+ return retbuf;
+
if ((bfd_seek (abfd, offset, SEEK_SET) != 0) ||
(bfd_bread (buf, size, abfd) != size))
{
abbrev = dwarf2_lookup_abbrev (abbrev_number, cu_header);
if (!abbrev)
{
- error ("Dwarf Error: Could not find abbrev number %d.", abbrev_number);
+ error ("Dwarf Error: Could not find abbrev number %d [in module %s]", abbrev_number,
+ bfd_get_filename (abfd));
}
part_die->offset = info_ptr - dwarf_info_buffer;
part_die->tag = abbrev->tag;
abbrev = dwarf2_lookup_abbrev (abbrev_number, cu_header);
if (!abbrev)
{
- error ("Dwarf Error: could not find abbrev number %d.", abbrev_number);
+ error ("Dwarf Error: could not find abbrev number %d [in module %s]", abbrev_number,
+ bfd_get_filename (abfd));
}
die = dwarf_alloc_die ();
die->offset = offset;
info_ptr = read_attribute_value (attr, form, abfd, info_ptr, cu_header);
break;
default:
- error ("Dwarf Error: Cannot handle %s in DWARF reader.",
- dwarf_form_name (form));
+ error ("Dwarf Error: Cannot handle %s in DWARF reader [in module %s]",
+ dwarf_form_name (form),
+ bfd_get_filename (abfd));
}
return info_ptr;
}
break;
default:
internal_error (__FILE__, __LINE__,
- "read_address: bad switch, signed");
+ "read_address: bad switch, signed [in module %s]",
+ bfd_get_filename (abfd));
}
}
else
break;
default:
internal_error (__FILE__, __LINE__,
- "read_address: bad switch, unsigned");
+ "read_address: bad switch, unsigned [in module %s]",
+ bfd_get_filename (abfd));
}
}
break;
default:
internal_error (__FILE__, __LINE__,
- "read_offset: bad switch");
+ "read_offset: bad switch [in module %s]",
+ bfd_get_filename (abfd));
}
return retval;
if (dwarf_str_buffer == NULL)
{
- error ("DW_FORM_strp used without .debug_str section");
+ error ("DW_FORM_strp used without .debug_str section [in module %s]",
+ bfd_get_filename (abfd));
return NULL;
}
if (str_offset >= dwarf_str_size)
{
- error ("DW_FORM_strp pointing outside of .debug_str section");
+ error ("DW_FORM_strp pointing outside of .debug_str section [in module %s]",
+ bfd_get_filename (abfd));
return NULL;
}
gdb_assert (HOST_CHAR_BIT == 8);
case DW_LANG_Pascal83:
case DW_LANG_Modula2:
default:
- cu_language = language_unknown;
+ cu_language = language_minimal;
break;
}
cu_language_defn = language_def (cu_language);
* lh->minimum_instruction_length;
line += lh->line_base + (adj_opcode % lh->line_range);
/* append row to matrix using current values */
- address = check_cu_functions (address);
- record_line (current_subfile, line, address);
+ record_line (current_subfile, line,
+ check_cu_functions (address));
basic_block = 1;
}
else switch (op_code)
}
break;
case DW_LNS_copy:
- address = check_cu_functions (address);
- record_line (current_subfile, line, address);
+ record_line (current_subfile, line,
+ check_cu_functions (address));
basic_block = 0;
break;
case DW_LNS_advance_pc:
start_subfile (filename, dirname);
}
+static void
+var_decode_location (struct attribute *attr, struct symbol *sym,
+ struct objfile *objfile,
+ const struct comp_unit_head *cu_header)
+{
+ /* NOTE drow/2003-01-30: There used to be a comment and some special
+ code here to turn a symbol with DW_AT_external and a
+ SYMBOL_VALUE_ADDRESS of 0 into a LOC_UNRESOLVED symbol. This was
+ necessary for platforms (maybe Alpha, certainly PowerPC GNU/Linux
+ with some versions of binutils) where shared libraries could have
+ relocations against symbols in their debug information - the
+ minimal symbol would have the right address, but the debug info
+ would not. It's no longer necessary, because we will explicitly
+ apply relocations when we read in the debug information now. */
+
+ /* A DW_AT_location attribute with no contents indicates that a
+ variable has been optimized away. */
+ if (attr_form_is_block (attr) && DW_BLOCK (attr)->size == 0)
+ {
+ SYMBOL_CLASS (sym) = LOC_OPTIMIZED_OUT;
+ return;
+ }
+
+ /* Handle one degenerate form of location expression specially, to
+ preserve GDB's previous behavior when section offsets are
+ specified. If this is just a DW_OP_addr then mark this symbol
+ as LOC_STATIC. */
+
+ if (attr_form_is_block (attr)
+ && DW_BLOCK (attr)->size == 1 + cu_header->addr_size
+ && DW_BLOCK (attr)->data[0] == DW_OP_addr)
+ {
+ int dummy;
+
+ SYMBOL_VALUE_ADDRESS (sym) =
+ read_address (objfile->obfd, DW_BLOCK (attr)->data + 1, cu_header,
+ &dummy);
+ fixup_symbol_section (sym, objfile);
+ SYMBOL_VALUE_ADDRESS (sym) += ANOFFSET (objfile->section_offsets,
+ SYMBOL_SECTION (sym));
+ SYMBOL_CLASS (sym) = LOC_STATIC;
+ return;
+ }
+
+ /* NOTE drow/2002-01-30: It might be worthwhile to have a static
+ expression evaluator, and use LOC_COMPUTED only when necessary
+ (i.e. when the value of a register or memory location is
+ referenced, or a thread-local block, etc.). Then again, it might
+ not be worthwhile. I'm assuming that it isn't unless performance
+ or memory numbers show me otherwise. */
+
+ dwarf2_symbol_mark_computed (attr, sym, cu_header, objfile);
+ SYMBOL_CLASS (sym) = LOC_COMPUTED;
+}
+
/* Given a pointer to a DWARF information entry, figure out if we need
to make a symbol table entry for it, and if so, create a new entry
and return a pointer to it.
sizeof (struct symbol));
OBJSTAT (objfile, n_syms++);
memset (sym, 0, sizeof (struct symbol));
- SYMBOL_NAME (sym) = obsavestring (name, strlen (name),
- &objfile->symbol_obstack);
+
+ /* Cache this symbol's name and the name's demangled form (if any). */
+ SYMBOL_LANGUAGE (sym) = cu_language;
+ SYMBOL_SET_NAMES (sym, name, strlen (name), objfile);
/* Default assumptions.
Use the passed type or decode it from the die. */
- SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
SYMBOL_CLASS (sym) = LOC_STATIC;
if (type != NULL)
SYMBOL_TYPE (sym) = type;
{
SYMBOL_LINE (sym) = DW_UNSND (attr);
}
-
- /* If this symbol is from a C++ compilation, then attempt to
- cache the demangled form for future reference. This is a
- typical time versus space tradeoff, that was decided in favor
- of time because it sped up C++ symbol lookups by a factor of
- about 20. */
-
- SYMBOL_LANGUAGE (sym) = cu_language;
- SYMBOL_INIT_DEMANGLED_NAME (sym, &objfile->symbol_obstack);
switch (die->tag)
{
case DW_TAG_label:
attr = dwarf_attr (die, DW_AT_location);
if (attr)
{
+ var_decode_location (attr, sym, objfile, cu_header);
attr2 = dwarf_attr (die, DW_AT_external);
if (attr2 && (DW_UNSND (attr2) != 0))
- {
- /* Support the .debug_loc offsets */
- if (attr_form_is_block (attr))
- {
- SYMBOL_VALUE_ADDRESS (sym) =
- decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
- }
- else if (attr->form == DW_FORM_data4
- || attr->form == DW_FORM_data8)
- {
- dwarf2_complex_location_expr_complaint ();
- }
- else
- {
- dwarf2_invalid_attrib_class_complaint ("DW_AT_location",
- "external variable");
- }
- add_symbol_to_list (sym, &global_symbols);
- if (is_thread_local)
- {
- /* SYMBOL_VALUE_ADDRESS contains at this point the
- offset of the variable within the thread local
- storage. */
- SYMBOL_CLASS (sym) = LOC_THREAD_LOCAL_STATIC;
- SYMBOL_OBJFILE (sym) = objfile;
- }
-
- /* In shared libraries the address of the variable
- in the location descriptor might still be relocatable,
- so its value could be zero.
- Enter the symbol as a LOC_UNRESOLVED symbol, if its
- value is zero, the address of the variable will then
- be determined from the minimal symbol table whenever
- the variable is referenced. */
- else if (SYMBOL_VALUE_ADDRESS (sym))
- {
- fixup_symbol_section (sym, objfile);
- SYMBOL_VALUE_ADDRESS (sym) +=
- ANOFFSET (objfile->section_offsets,
- SYMBOL_SECTION (sym));
- SYMBOL_CLASS (sym) = LOC_STATIC;
- }
- else
- SYMBOL_CLASS (sym) = LOC_UNRESOLVED;
- }
+ add_symbol_to_list (sym, &global_symbols);
else
- {
- /* Support the .debug_loc offsets */
- if (attr_form_is_block (attr))
- {
- SYMBOL_VALUE (sym) = addr =
- decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
- }
- else if (attr->form == DW_FORM_data4
- || attr->form == DW_FORM_data8)
- {
- dwarf2_complex_location_expr_complaint ();
- }
- else
- {
- dwarf2_invalid_attrib_class_complaint ("DW_AT_location",
- "external variable");
- addr = 0;
- }
- add_symbol_to_list (sym, list_in_scope);
- if (optimized_out)
- {
- SYMBOL_CLASS (sym) = LOC_OPTIMIZED_OUT;
- }
- else if (isreg)
- {
- SYMBOL_CLASS (sym) = LOC_REGISTER;
- SYMBOL_VALUE (sym) =
- DWARF2_REG_TO_REGNUM (SYMBOL_VALUE (sym));
- }
- else if (offreg)
- {
- SYMBOL_CLASS (sym) = LOC_BASEREG;
- SYMBOL_BASEREG (sym) = DWARF2_REG_TO_REGNUM (basereg);
- }
- else if (islocal)
- {
- SYMBOL_CLASS (sym) = LOC_LOCAL;
- }
- else if (is_thread_local)
- {
- SYMBOL_CLASS (sym) = LOC_THREAD_LOCAL_STATIC;
- SYMBOL_OBJFILE (sym) = objfile;
- }
- else
- {
- fixup_symbol_section (sym, objfile);
- SYMBOL_VALUE_ADDRESS (sym) =
- addr + ANOFFSET (objfile->section_offsets,
- SYMBOL_SECTION (sym));
- SYMBOL_CLASS (sym) = LOC_STATIC;
- }
- }
+ add_symbol_to_list (sym, list_in_scope);
}
else
{
case DW_TAG_union_type:
case DW_TAG_enumeration_type:
SYMBOL_CLASS (sym) = LOC_TYPEDEF;
- SYMBOL_NAMESPACE (sym) = STRUCT_NAMESPACE;
+ SYMBOL_DOMAIN (sym) = STRUCT_DOMAIN;
add_symbol_to_list (sym, list_in_scope);
/* The semantics of C++ state that "struct foo { ... }" also
obstack_alloc (&objfile->symbol_obstack,
sizeof (struct symbol));
*typedef_sym = *sym;
- SYMBOL_NAMESPACE (typedef_sym) = VAR_NAMESPACE;
+ SYMBOL_DOMAIN (typedef_sym) = VAR_DOMAIN;
if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0)
TYPE_NAME (SYMBOL_TYPE (sym)) =
- obsavestring (SYMBOL_NAME (sym),
- strlen (SYMBOL_NAME (sym)),
+ obsavestring (DEPRECATED_SYMBOL_NAME (sym),
+ strlen (DEPRECATED_SYMBOL_NAME (sym)),
&objfile->type_obstack);
add_symbol_to_list (typedef_sym, list_in_scope);
}
case DW_TAG_typedef:
case DW_TAG_base_type:
SYMBOL_CLASS (sym) = LOC_TYPEDEF;
- SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
add_symbol_to_list (sym, list_in_scope);
break;
case DW_TAG_enumerator:
{
case DW_FORM_addr:
if (TYPE_LENGTH (SYMBOL_TYPE (sym)) != cu_header->addr_size)
- dwarf2_const_value_length_mismatch_complaint (SYMBOL_NAME (sym),
+ dwarf2_const_value_length_mismatch_complaint (DEPRECATED_SYMBOL_NAME (sym),
cu_header->addr_size,
TYPE_LENGTH (SYMBOL_TYPE
(sym)));
SYMBOL_VALUE_BYTES (sym) = (char *)
obstack_alloc (&objfile->symbol_obstack, cu_header->addr_size);
- store_address (SYMBOL_VALUE_BYTES (sym), cu_header->addr_size,
- DW_ADDR (attr));
+ /* NOTE: cagney/2003-05-09: In-lined store_address call with
+ it's body - store_unsigned_integer. */
+ store_unsigned_integer (SYMBOL_VALUE_BYTES (sym), cu_header->addr_size,
+ DW_ADDR (attr));
SYMBOL_CLASS (sym) = LOC_CONST_BYTES;
break;
case DW_FORM_block1:
case DW_FORM_block:
blk = DW_BLOCK (attr);
if (TYPE_LENGTH (SYMBOL_TYPE (sym)) != blk->size)
- dwarf2_const_value_length_mismatch_complaint (SYMBOL_NAME (sym),
+ dwarf2_const_value_length_mismatch_complaint (DEPRECATED_SYMBOL_NAME (sym),
blk->size,
TYPE_LENGTH (SYMBOL_TYPE
(sym)));
type_die = follow_die_ref (ref);
if (!type_die)
{
- error ("Dwarf Error: Cannot find referent at offset %d.", ref);
+ error ("Dwarf Error: Cannot find referent at offset %d [in module %s]",
+ ref, objfile->name);
return NULL;
}
}
if (!type)
{
dump_die (type_die);
- error ("Dwarf Error: Problem turning type die at offset into gdb type.");
+ error ("Dwarf Error: Problem turning type die at offset into gdb type [in module %s]",
+ objfile->name);
}
return type;
}
type_die = follow_die_ref (ref);
if (!type_die)
{
- error ("Dwarf Error: Cannot find referent at offset %d.", ref);
+ error ("Dwarf Error: Cannot find referent at offset %d [in module %s]", ref,
+ objfile->name);
return NULL;
}
type = tag_type_to_type (type_die, objfile, cu_header);
{
if (type_die)
dump_die (type_die);
- error ("Dwarf Error: Problem turning containing type into gdb type.");
+ error ("Dwarf Error: Problem turning containing type into gdb type [in module %s]",
+ objfile->name);
}
return type;
}
if (!die->type)
{
dump_die (die);
- error ("Dwarf Error: Cannot find type of die.");
+ error ("Dwarf Error: Cannot find type of die [in module %s]",
+ objfile->name);
}
return die->type;
}
return NULL;
}
+/* Get name of a die, return NULL if not found. */
+
+static char *
+dwarf2_name (struct die_info *die)
+{
+ struct attribute *attr;
+
+ attr = dwarf_attr (die, DW_AT_name);
+ if (attr && DW_STRING (attr))
+ return DW_STRING (attr);
+ return NULL;
+}
+
+/* Return the die that this die in an extension of, or NULL if there
+ is none. */
+
+static struct die_info *
+dwarf2_extension (struct die_info *die)
+{
+ struct attribute *attr;
+ struct die_info *extension_die;
+ unsigned int ref;
+
+ attr = dwarf_attr (die, DW_AT_extension);
+ if (attr == NULL)
+ return NULL;
+
+ ref = dwarf2_get_ref_die_offset (attr);
+ extension_die = follow_die_ref (ref);
+ if (!extension_die)
+ {
+ error ("Dwarf Error: Cannot find referent at offset %d.", ref);
+ }
+
+ return extension_die;
+}
+
/* Convert a DIE tag into its string name. */
static char *
{
if (typeid < 0 || typeid >= FT_NUM_MEMBERS)
{
- error ("Dwarf Error: internal error - invalid fundamental type id %d.",
- typeid);
+ error ("Dwarf Error: internal error - invalid fundamental type id %d [in module %s]",
+ typeid, objfile->name);
}
/* Look for this particular type in the fundamental type vector. If
|| attr->form == DW_FORM_block4
|| attr->form == DW_FORM_block);
}
+
+static void
+dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym,
+ const struct comp_unit_head *cu_header,
+ struct objfile *objfile)
+{
+ if (attr->form == DW_FORM_data4 || attr->form == DW_FORM_data8)
+ {
+ struct dwarf2_loclist_baton *baton;
+
+ baton = obstack_alloc (&objfile->symbol_obstack,
+ sizeof (struct dwarf2_loclist_baton));
+ baton->objfile = objfile;
+
+ /* We don't know how long the location list is, but make sure we
+ don't run off the edge of the section. */
+ baton->size = dwarf_loc_size - DW_UNSND (attr);
+ baton->data = dwarf_loc_buffer + DW_UNSND (attr);
+ baton->base_address = cu_header->base_address;
+ if (cu_header->base_known == 0)
+ complaint (&symfile_complaints,
+ "Location list used without specifying the CU base address.");
+
+ SYMBOL_LOCATION_FUNCS (sym) = &dwarf2_loclist_funcs;
+ SYMBOL_LOCATION_BATON (sym) = baton;
+ }
+ else
+ {
+ struct dwarf2_locexpr_baton *baton;
+
+ baton = obstack_alloc (&objfile->symbol_obstack,
+ sizeof (struct dwarf2_locexpr_baton));
+ baton->objfile = objfile;
+
+ if (attr_form_is_block (attr))
+ {
+ /* Note that we're just copying the block's data pointer
+ here, not the actual data. We're still pointing into the
+ dwarf_info_buffer for SYM's objfile; right now we never
+ release that buffer, but when we do clean up properly
+ this may need to change. */
+ baton->size = DW_BLOCK (attr)->size;
+ baton->data = DW_BLOCK (attr)->data;
+ }
+ else
+ {
+ dwarf2_invalid_attrib_class_complaint ("location description",
+ SYMBOL_NATURAL_NAME (sym));
+ baton->size = 0;
+ baton->data = NULL;
+ }
+
+ SYMBOL_LOCATION_FUNCS (sym) = &dwarf2_locexpr_funcs;
+ SYMBOL_LOCATION_BATON (sym) = baton;
+ }
+}