this function, so we can't say
which register it's relative to;
use LOC_LOCAL. */
-static int is_thread_local; /* Variable is at a constant offset in the
- thread-local storage block for the
- current thread and the dynamic linker
- module containing this expression.
- decode_locdesc returns the offset from
- that base. */
/* DW_AT_frame_base values for the current function.
frame_base_reg is -1 if DW_AT_frame_base is missing, otherwise it
static char *scan_partial_symbols (char *, struct objfile *,
CORE_ADDR *, CORE_ADDR *,
- const struct comp_unit_head *);
+ const struct comp_unit_head *,
+ const char *namespace);
static void add_partial_symbol (struct partial_die_info *, struct objfile *,
- const struct comp_unit_head *);
+ const struct comp_unit_head *,
+ const char *namespace);
+
+static char *add_partial_namespace (struct partial_die_info *pdi,
+ char *info_ptr,
+ struct objfile *objfile,
+ CORE_ADDR *lowpc, CORE_ADDR *highpc,
+ const struct comp_unit_head *cu_header,
+ const char *namespace);
+
+static char *add_partial_enumeration (struct partial_die_info *enum_pdi,
+ char *info_ptr,
+ struct objfile *objfile,
+ const struct comp_unit_head *cu_header,
+ const char *namespace);
+
+static char *locate_pdi_sibling (struct partial_die_info *orig_pdi,
+ char *info_ptr,
+ bfd *abfd,
+ const struct comp_unit_head *cu_header);
static void dwarf2_psymtab_to_symtab (struct partial_symtab *);
}
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;
+ flagword aflag = bfd_get_section_flags (ignore_abfd, sectp);
+ if (aflag & SEC_HAS_CONTENTS)
+ {
+ 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))
{
If not, there's no more debug_info for this comp unit. */
if (comp_unit_die.has_children)
{
+ lowpc = ((CORE_ADDR) -1);
+ highpc = ((CORE_ADDR) 0);
+
info_ptr = scan_partial_symbols (info_ptr, objfile, &lowpc, &highpc,
- &cu_header);
+ &cu_header, NULL);
+ /* If we didn't find a lowpc, set it to highpc to avoid
+ complaints from `maint check'. */
+ if (lowpc == ((CORE_ADDR) -1))
+ lowpc = highpc;
+
/* If the compilation unit didn't have an explicit address range,
then use the information extracted from its child dies. */
if (! comp_unit_die.has_pc_info)
do_cleanups (back_to);
}
-/* Read in all interesting dies to the end of the compilation unit. */
+/* Read in all interesting dies to the end of the compilation unit or
+ to the end of the current namespace. NAMESPACE is NULL if we
+ haven't yet encountered any DW_TAG_namespace entries; otherwise,
+ it's the name of the current namespace. In particular, it's the
+ empty string if we're currently in the global namespace but have
+ previously encountered a DW_TAG_namespace. */
static char *
scan_partial_symbols (char *info_ptr, struct objfile *objfile,
CORE_ADDR *lowpc, CORE_ADDR *highpc,
- const struct comp_unit_head *cu_header)
+ const struct comp_unit_head *cu_header,
+ const char *namespace)
{
bfd *abfd = objfile->obfd;
struct partial_die_info pdi;
- /* This function is called after we've read in the comp_unit_die in
- order to read its children. We start the nesting level at 1 since
- we have pushed 1 level down in order to read the comp unit's children.
- The comp unit itself is at level 0, so we stop reading when we pop
- back to that level. */
-
- int nesting_level = 1;
-
- /* We only want to read in symbols corresponding to variables or
- other similar objects that are global or static. Normally, these
- are all children of the DW_TAG_compile_unit die, so are all at
- level 1. But C++ namespaces give ries to DW_TAG_namespace dies
- whose children are global objects. So we keep track of what
- level we currently think of as referring to file scope; this
- should always equal 1 plus the number of namespaces that we are
- currently nested within. */
-
- int file_scope_level = 1;
-
- *lowpc = ((CORE_ADDR) -1);
- *highpc = ((CORE_ADDR) 0);
+ /* Now, march along the PDI's, descending into ones which have
+ interesting children but skipping the children of the other ones,
+ until we reach the end of the compilation unit. */
- while (nesting_level)
+ while (1)
{
+ /* This flag tells whether or not info_ptr has gotten updated
+ inside the loop. */
+ int info_ptr_updated = 0;
+
info_ptr = read_partial_die (&pdi, abfd, info_ptr, cu_header);
- /* Anonymous namespaces have no name but are interesting. */
+ /* Anonymous namespaces have no name but have interesting
+ children, so we need to look at them. Ditto for anonymous
+ enums. */
- if (pdi.name != NULL || pdi.tag == DW_TAG_namespace)
+ if (pdi.name != NULL || pdi.tag == DW_TAG_namespace
+ || pdi.tag == DW_TAG_enumeration_type)
{
switch (pdi.tag)
{
{
*highpc = pdi.highpc;
}
- if ((pdi.is_external || nesting_level == file_scope_level)
- && !pdi.is_declaration)
+ if (!pdi.is_declaration)
{
- add_partial_symbol (&pdi, objfile, cu_header);
+ add_partial_symbol (&pdi, objfile, cu_header, namespace);
}
}
break;
case DW_TAG_variable:
case DW_TAG_typedef:
+ case DW_TAG_union_type:
case DW_TAG_class_type:
case DW_TAG_structure_type:
- case DW_TAG_union_type:
- case DW_TAG_enumeration_type:
- if ((pdi.is_external || nesting_level == file_scope_level)
- && !pdi.is_declaration)
+ if (!pdi.is_declaration)
{
- add_partial_symbol (&pdi, objfile, cu_header);
+ add_partial_symbol (&pdi, objfile, cu_header, namespace);
}
break;
- case DW_TAG_enumerator:
- /* File scope enumerators are added to the partial
- symbol table. They're children of the enumeration
- type die, so they occur at a level one higher than we
- normally look for. */
- if (nesting_level == file_scope_level + 1)
- add_partial_symbol (&pdi, objfile, cu_header);
+ case DW_TAG_enumeration_type:
+ if (!pdi.is_declaration)
+ {
+ info_ptr = add_partial_enumeration (&pdi, info_ptr,
+ objfile, cu_header,
+ namespace);
+ info_ptr_updated = 1;
+ }
break;
case DW_TAG_base_type:
/* File scope base type definitions are added to the partial
symbol table. */
- if (nesting_level == file_scope_level)
- add_partial_symbol (&pdi, objfile, cu_header);
+ add_partial_symbol (&pdi, objfile, cu_header, namespace);
break;
case DW_TAG_namespace:
- /* FIXME: carlton/2002-10-16: we're not yet doing
- anything useful with this, but for now make sure that
- these tags at least don't cause us to miss any
- important symbols. */
- if (pdi.has_children)
- file_scope_level++;
+ /* We've hit a DW_TAG_namespace entry, so we know this
+ file has been compiled using a compiler that
+ generates them; update NAMESPACE to reflect that. */
+ if (namespace == NULL)
+ namespace = "";
+ info_ptr = add_partial_namespace (&pdi, info_ptr, objfile,
+ lowpc, highpc, cu_header,
+ namespace);
+ info_ptr_updated = 1;
+ break;
default:
break;
}
}
- /* If the die has a sibling, skip to the sibling. Do not skip
- enumeration types, we want to record their enumerators. Do
- not skip namespaces, we want to record symbols inside
- them. */
- if (pdi.sibling
- && pdi.tag != DW_TAG_enumeration_type
- && pdi.tag != DW_TAG_namespace)
- {
- info_ptr = pdi.sibling;
- }
- else if (pdi.has_children)
- {
- /* Die has children, but either the optional DW_AT_sibling
- attribute is missing or we want to look at them. */
- nesting_level++;
- }
-
if (pdi.tag == 0)
- {
- nesting_level--;
- /* If this is the end of a DW_TAG_namespace entry, then
- decrease the file_scope_level, too. */
- if (nesting_level < file_scope_level)
- {
- file_scope_level--;
- gdb_assert (nesting_level == file_scope_level);
- }
- }
+ break;
+
+ /* If the die has a sibling, skip to the sibling, unless another
+ function has already updated info_ptr for us. */
+
+ /* NOTE: carlton/2003-06-16: This is a bit hackish, but whether
+ or not we want to update this depends on enough stuff (not
+ only pdi.tag but also whether or not pdi.name is NULL) that
+ this seems like the easiest way to handle the issue. */
+
+ if (!info_ptr_updated)
+ info_ptr = locate_pdi_sibling (&pdi, info_ptr, abfd, cu_header);
}
- /* If we didn't find a lowpc, set it to highpc to avoid complaints
- from `maint check'. */
- if (*lowpc == ((CORE_ADDR) -1))
- *lowpc = *highpc;
return info_ptr;
}
static void
add_partial_symbol (struct partial_die_info *pdi, struct objfile *objfile,
- const struct comp_unit_head *cu_header)
+ const struct comp_unit_head *cu_header,
+ const char *namespace)
{
CORE_ADDR addr = 0;
+ const struct partial_symbol *psym = NULL;
switch (pdi->tag)
{
{
/*prim_record_minimal_symbol (pdi->name, pdi->lowpc + baseaddr,
mst_text, objfile); */
- add_psymbol_to_list (pdi->name, strlen (pdi->name),
- VAR_DOMAIN, LOC_BLOCK,
- &objfile->global_psymbols,
- 0, pdi->lowpc + baseaddr, cu_language, objfile);
+ psym = add_psymbol_to_list (pdi->name, strlen (pdi->name),
+ VAR_DOMAIN, LOC_BLOCK,
+ &objfile->global_psymbols,
+ 0, pdi->lowpc + baseaddr,
+ cu_language, objfile);
}
else
{
/*prim_record_minimal_symbol (pdi->name, pdi->lowpc + baseaddr,
mst_file_text, objfile); */
- add_psymbol_to_list (pdi->name, strlen (pdi->name),
- VAR_DOMAIN, LOC_BLOCK,
- &objfile->static_psymbols,
- 0, pdi->lowpc + baseaddr, cu_language, objfile);
+ psym = add_psymbol_to_list (pdi->name, strlen (pdi->name),
+ VAR_DOMAIN, LOC_BLOCK,
+ &objfile->static_psymbols,
+ 0, pdi->lowpc + baseaddr,
+ cu_language, objfile);
}
break;
case DW_TAG_variable:
if (pdi->locdesc)
addr = decode_locdesc (pdi->locdesc, objfile, cu_header);
if (pdi->locdesc || pdi->has_type)
- add_psymbol_to_list (pdi->name, strlen (pdi->name),
- VAR_DOMAIN, LOC_STATIC,
- &objfile->global_psymbols,
- 0, addr + baseaddr, cu_language, objfile);
+ psym = add_psymbol_to_list (pdi->name, strlen (pdi->name),
+ VAR_DOMAIN, LOC_STATIC,
+ &objfile->global_psymbols,
+ 0, addr + baseaddr,
+ cu_language, objfile);
}
else
{
addr = decode_locdesc (pdi->locdesc, objfile, cu_header);
/*prim_record_minimal_symbol (pdi->name, addr + baseaddr,
mst_file_data, objfile); */
- add_psymbol_to_list (pdi->name, strlen (pdi->name),
- VAR_DOMAIN, LOC_STATIC,
- &objfile->static_psymbols,
- 0, addr + baseaddr, cu_language, objfile);
+ psym = add_psymbol_to_list (pdi->name, strlen (pdi->name),
+ VAR_DOMAIN, LOC_STATIC,
+ &objfile->static_psymbols,
+ 0, addr + baseaddr,
+ cu_language, objfile);
}
break;
case DW_TAG_typedef:
default:
break;
}
+
+ /* Check to see if we should scan the name for possible namespace
+ info. Only do this if this is C++, if we don't have namespace
+ debugging info in the file, if the psym is of an appropriate type
+ (otherwise we'll have psym == NULL), and if we actually had a
+ mangled name to begin with. */
+
+ if (cu_language == language_cplus
+ && namespace == NULL
+ && psym != NULL
+ && SYMBOL_CPLUS_DEMANGLED_NAME (psym) != NULL)
+ cp_check_possible_namespace_symbols (SYMBOL_CPLUS_DEMANGLED_NAME (psym),
+ objfile);
+}
+
+/* Read a partial die corresponding to a namespace; also, add a symbol
+ corresponding to that namespace to the symbol table. NAMESPACE is
+ the name of the enclosing namespace. */
+
+static char *
+add_partial_namespace (struct partial_die_info *pdi, char *info_ptr,
+ struct objfile *objfile,
+ CORE_ADDR *lowpc, CORE_ADDR *highpc,
+ const struct comp_unit_head *cu_header,
+ const char *namespace)
+{
+ /* Calculate the full name of the namespace that we just entered. */
+
+ const char *new_name = pdi->name;
+ char *full_name;
+
+ if (new_name == NULL)
+ new_name = "(anonymous namespace)";
+ full_name = alloca (strlen (namespace) + 2 + strlen (new_name) + 1);
+ strcpy (full_name, namespace);
+ if (*namespace != '\0')
+ strcat (full_name, "::");
+ strcat (full_name, new_name);
+
+ /* FIXME: carlton/2003-06-27: Once we build qualified names for more
+ symbols than just namespaces, we should replace this by a call to
+ add_partial_symbol. */
+
+ add_psymbol_to_list (full_name, strlen (full_name),
+ VAR_DOMAIN, LOC_TYPEDEF,
+ &objfile->global_psymbols,
+ 0, 0, cu_language, objfile);
+
+ /* Now scan partial symbols in that namespace. */
+
+ if (pdi->has_children)
+ info_ptr = scan_partial_symbols (info_ptr, objfile,
+ lowpc, highpc,
+ cu_header, full_name);
+
+ return info_ptr;
+}
+
+/* Read a partial die corresponding to an enumeration type. */
+
+static char *
+add_partial_enumeration (struct partial_die_info *enum_pdi, char *info_ptr,
+ struct objfile *objfile,
+ const struct comp_unit_head *cu_header,
+ const char *namespace)
+{
+ bfd *abfd = objfile->obfd;
+ struct partial_die_info pdi;
+
+ if (enum_pdi->name != NULL)
+ add_partial_symbol (enum_pdi, objfile, cu_header, namespace);
+
+ while (1)
+ {
+ info_ptr = read_partial_die (&pdi, abfd, info_ptr, cu_header);
+ if (pdi.tag == 0)
+ break;
+ if (pdi.tag != DW_TAG_enumerator || pdi.name == NULL)
+ complaint (&symfile_complaints, "malformed enumerator DIE ignored");
+ else
+ add_partial_symbol (&pdi, objfile, cu_header, namespace);
+ }
+
+ return info_ptr;
+}
+
+/* Locate ORIG_PDI's sibling; INFO_PTR should point to the next DIE
+ after ORIG_PDI. */
+
+static char *
+locate_pdi_sibling (struct partial_die_info *orig_pdi, char *info_ptr,
+ bfd *abfd, const struct comp_unit_head *cu_header)
+{
+ /* Do we know the sibling already? */
+
+ if (orig_pdi->sibling)
+ return orig_pdi->sibling;
+
+ /* Are there any children to deal with? */
+
+ if (!orig_pdi->has_children)
+ return info_ptr;
+
+ /* Okay, we don't know the sibling, but we have children that we
+ want to skip. So read children until we run into one without a
+ tag; return whatever follows it. */
+
+ while (1)
+ {
+ struct partial_die_info pdi;
+
+ info_ptr = read_partial_die (&pdi, abfd, info_ptr, cu_header);
+
+ if (pdi.tag == 0)
+ return info_ptr;
+ else
+ info_ptr = locate_pdi_sibling (&pdi, info_ptr, abfd, cu_header);
+ }
}
/* Expand this partial symbol table into a full symbol table. */
if (objfile->ei.entry_point >= lowpc &&
objfile->ei.entry_point < highpc)
{
- objfile->ei.entry_file_lowpc = lowpc;
- objfile->ei.entry_file_highpc = highpc;
+ objfile->ei.deprecated_entry_file_lowpc = lowpc;
+ objfile->ei.deprecated_entry_file_highpc = highpc;
}
attr = dwarf_attr (die, DW_AT_language);
read_func_scope (struct die_info *die, struct objfile *objfile,
const struct comp_unit_head *cu_header)
{
- register struct context_stack *new;
+ struct context_stack *new;
CORE_ADDR lowpc;
CORE_ADDR highpc;
struct die_info *child_die;
read_lexical_block_scope (struct die_info *die, struct objfile *objfile,
const struct comp_unit_head *cu_header)
{
- register struct context_stack *new;
+ struct context_stack *new;
CORE_ADDR lowpc, highpc;
struct die_info *child_die;
unsigned int addr_size = cu_header->addr_size;
CORE_ADDR mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1));
/* Value of the DW_AT_ranges attribute is the offset in the
- .debug_renges section. */
+ .debug_ranges section. */
unsigned int offset = DW_UNSND (attr);
/* Base address selection entry. */
CORE_ADDR base;
found_base = cu_header->base_known;
base = cu_header->base_address;
+
+ if (offset >= dwarf_ranges_size)
+ {
+ complaint (&symfile_complaints,
+ "Offset %d out of bounds for DW_AT_ranges attribute",
+ offset);
+ return 0;
+ }
buffer = dwarf_ranges_buffer + offset;
/* Read in the largest possible address. */
processing_current_namespace = temp_name;
}
- /* If it's an anonymous namespace that we're seeing for the first
- time, add a using directive. */
+ /* Add a symbol associated to this if we haven't seen the namespace
+ before. Also, add a using directive if it's an anonymous
+ namespace. */
+
+ if (dwarf2_extension (die) == NULL)
+ {
+ struct type *type;
- if (is_anonymous && dwarf_attr (die, DW_AT_extension) == NULL)
- cp_add_using_directive (processing_current_namespace,
- strlen (previous_namespace),
- strlen (processing_current_namespace));
+ /* FIXME: carlton/2003-06-27: Once GDB is more const-correct,
+ this cast will hopefully become unnecessary. */
+ type = init_type (TYPE_CODE_NAMESPACE, 0, 0,
+ (char *) processing_current_namespace,
+ objfile);
+ TYPE_TAG_NAME (type) = TYPE_NAME (type);
+
+ new_symbol (die, type, objfile, cu_header);
+
+ if (is_anonymous)
+ cp_add_using_directive (processing_current_namespace,
+ strlen (previous_namespace),
+ strlen (processing_current_namespace));
+ }
if (die->has_children)
{
struct attribute *attr2 = NULL;
CORE_ADDR addr = 0;
- name = dwarf2_linkage_name (die);
+ if (die->tag != DW_TAG_namespace)
+ name = dwarf2_linkage_name (die);
+ else
+ name = TYPE_NAME (type);
+
if (name)
{
sym = (struct symbol *) obstack_alloc (&objfile->symbol_obstack,
attr = dwarf_attr (die, DW_AT_location);
if (attr)
{
- SYMBOL_VALUE (sym) =
- decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
- if (isreg)
- {
- SYMBOL_CLASS (sym) = LOC_REGPARM;
- SYMBOL_VALUE (sym) =
- DWARF2_REG_TO_REGNUM (SYMBOL_VALUE (sym));
- }
- else if (offreg)
- {
- if (isderef)
- {
- if (basereg != frame_base_reg)
- dwarf2_complex_location_expr_complaint ();
- SYMBOL_CLASS (sym) = LOC_REF_ARG;
- }
- else
- {
- SYMBOL_CLASS (sym) = LOC_BASEREG_ARG;
- SYMBOL_BASEREG (sym) = DWARF2_REG_TO_REGNUM (basereg);
- }
- }
- else
- {
- SYMBOL_CLASS (sym) = LOC_ARG;
- }
+ var_decode_location (attr, sym, objfile, cu_header);
+ /* FIXME drow/2003-07-31: Is LOC_COMPUTED_ARG necessary? */
+ if (SYMBOL_CLASS (sym) == LOC_COMPUTED)
+ SYMBOL_CLASS (sym) = LOC_COMPUTED_ARG;
}
attr = dwarf_attr (die, DW_AT_const_value);
if (attr)
}
add_symbol_to_list (sym, list_in_scope);
break;
+ case DW_TAG_namespace:
+ SYMBOL_CLASS (sym) = LOC_TYPEDEF;
+ add_symbol_to_list (sym, &global_symbols);
+ break;
default:
/* Not a tag we recognize. Hopefully we aren't processing
trash data, but since we must specifically ignore things
/* Convert a DIE tag into its string name. */
static char *
-dwarf_tag_name (register unsigned tag)
+dwarf_tag_name (unsigned tag)
{
switch (tag)
{
/* Convert a DWARF attribute code into its string name. */
static char *
-dwarf_attr_name (register unsigned attr)
+dwarf_attr_name (unsigned attr)
{
switch (attr)
{
return "DW_AT_MIPS_loop_unroll_factor";
case DW_AT_MIPS_software_pipeline_depth:
return "DW_AT_MIPS_software_pipeline_depth";
+#endif
case DW_AT_MIPS_linkage_name:
return "DW_AT_MIPS_linkage_name";
-#endif
case DW_AT_sf_names:
return "DW_AT_sf_names";
/* Convert a DWARF value form code into its string name. */
static char *
-dwarf_form_name (register unsigned form)
+dwarf_form_name (unsigned form)
{
switch (form)
{
/* Convert a DWARF stack opcode into its string name. */
static char *
-dwarf_stack_op_name (register unsigned op)
+dwarf_stack_op_name (unsigned op)
{
switch (op)
{
/* Convert a DWARF type code into its string name. */
static char *
-dwarf_type_encoding_name (register unsigned enc)
+dwarf_type_encoding_name (unsigned enc)
{
switch (enc)
{
#if 0
static char *
-dwarf_cfi_name (register unsigned cfi_opc)
+dwarf_cfi_name (unsigned cfi_opc)
{
switch (cfi_opc)
{
offreg = 0;
isderef = 0;
islocal = 0;
- is_thread_local = 0;
optimized_out = 1;
while (i < size)
break;
case DW_OP_GNU_push_tls_address:
- is_thread_local = 1;
/* The top of the stack has the offset from the beginning
of the thread control block at which the variable is located. */
/* Nothing should follow this operator, so the top of stack would