/* DWARF 2 debugging format support for GDB.
- Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
- 2002, 2003, 2004, 2005, 2006
- Free Software Foundation, Inc.
+ Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
+ 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology,
Inc. with support from Florida State University (under contract
partial symbol tables do not have dependencies. */
htab_t dependencies;
+ /* Header data from the line table, during full symbol processing. */
+ struct line_header *line_header;
+
/* Mark used when releasing cached dies. */
unsigned int mark : 1;
it. */
htab_t type_hash;
- /* The partial symbol table associated with this compilation unit. */
+ /* The partial symbol table associated with this compilation unit,
+ or NULL for partial units (which do not have an associated
+ symtab). */
struct partial_symtab *psymtab;
};
unsigned int mod_time;
unsigned int length;
int included_p; /* Non-zero if referenced by the Line Number Program. */
+ struct symtab *symtab; /* The associated symbol table, if any. */
} *file_names;
/* The start and end of the statement program following this
computed. */
unsigned int scope_set : 1;
+ /* Flag set if the DIE has a byte_size attribute. */
+ unsigned int has_byte_size : 1;
+
/* The name of this DIE. Normally the value of DW_AT_name, but
sometimes DW_TAG_MIPS_linkage_name or a string computed in some
other fashion. */
static void create_all_comp_units (struct objfile *);
-static struct dwarf2_cu *load_full_comp_unit (struct dwarf2_per_cu_data *);
+static struct dwarf2_cu *load_full_comp_unit (struct dwarf2_per_cu_data *,
+ struct objfile *);
static void process_full_comp_unit (struct dwarf2_per_cu_data *);
info_ptr = read_partial_die (&comp_unit_die, abbrev, bytes_read,
abfd, info_ptr, &cu);
+ if (comp_unit_die.tag == DW_TAG_partial_unit)
+ {
+ info_ptr = (beg_of_comp_unit + cu.header.length
+ + cu.header.initial_length_size);
+ do_cleanups (back_to_inner);
+ continue;
+ }
+
/* Set the language we're debugging */
set_cu_language (comp_unit_die.language, &cu);
case DW_TAG_structure_type:
case DW_TAG_union_type:
case DW_TAG_enumeration_type:
- /* Skip aggregate types without children, these are external
- references. */
+ /* Skip external references. The DWARF standard says in the section
+ about "Structure, Union, and Class Type Entries": "An incomplete
+ structure, union or class type is represented by a structure,
+ union or class entry that does not have a byte size attribute
+ and that has a DW_AT_declaration attribute." */
+ if (!pdi->has_byte_size && pdi->is_declaration)
+ return;
+
/* NOTE: carlton/2003-10-07: See comment in new_symbol about
static vs. global. */
- if (pdi->has_children == 0)
- return;
add_psymbol_to_list (actual_name, strlen (actual_name),
STRUCT_DOMAIN, LOC_TYPEDEF,
(cu->language == language_cplus
0, (CORE_ADDR) 0, cu->language, objfile);
if (cu->language == language_cplus
- || cu->language == language_java)
+ || cu->language == language_java
+ || cu->language == language_ada)
{
/* For C++ and Java, these implicitly act as typedefs as well. */
add_psymbol_to_list (actual_name, strlen (actual_name),
{
/* Read in this compilation unit. This may add new items to
the end of the queue. */
- load_full_comp_unit (item->per_cu);
+ load_full_comp_unit (item->per_cu, objfile);
item->per_cu->cu->read_in_chain = dwarf2_per_objfile->read_in_chain;
dwarf2_per_objfile->read_in_chain = item->per_cu;
/* If this compilation unit has already had full symbols created,
reset the TYPE fields in each DIE. */
- if (item->per_cu->psymtab->readin)
+ if (item->per_cu->type_hash)
reset_die_and_siblings_types (item->per_cu->cu->dies,
item->per_cu->cu);
}
them, one at a time, removing from the queue as we finish. */
for (item = dwarf2_queue; item != NULL; dwarf2_queue = item = next_item)
{
- if (!item->per_cu->psymtab->readin)
+ if (item->per_cu->psymtab && !item->per_cu->psymtab->readin)
process_full_comp_unit (item->per_cu);
item->per_cu->queued = 0;
/* Load the DIEs associated with PST and PER_CU into memory. */
static struct dwarf2_cu *
-load_full_comp_unit (struct dwarf2_per_cu_data *per_cu)
+load_full_comp_unit (struct dwarf2_per_cu_data *per_cu, struct objfile *objfile)
{
- struct partial_symtab *pst = per_cu->psymtab;
- bfd *abfd = pst->objfile->obfd;
+ bfd *abfd = objfile->obfd;
struct dwarf2_cu *cu;
unsigned long offset;
gdb_byte *info_ptr;
/* If an error occurs while loading, release our storage. */
free_cu_cleanup = make_cleanup (free_one_comp_unit, cu);
- cu->objfile = pst->objfile;
+ cu->objfile = objfile;
/* read in the comp_unit header */
info_ptr = read_comp_unit_head (&cu->header, info_ptr, abfd);
cu->first_fn = cu->last_fn = cu->cached_fn = NULL;
}
+static void
+free_cu_line_header (void *arg)
+{
+ struct dwarf2_cu *cu = arg;
+
+ free_line_header (cu->line_header);
+ cu->line_header = NULL;
+}
+
static void
read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
{
attr = dwarf2_attr (die, DW_AT_producer, cu);
if (attr)
cu->producer = DW_STRING (attr);
-
+
/* We assume that we're processing GCC output. */
processing_gcc_compilation = 2;
-#if 0
- /* FIXME:Do something here. */
- if (dip->at_producer != NULL)
- {
- handle_producer (dip->at_producer);
- }
-#endif
/* The compilation unit may be in a different language or objfile,
zero out all remembered fundamental types. */
start_symtab (name, comp_dir, lowpc);
record_debugformat ("DWARF 2");
+ record_producer (cu->producer);
initialize_cu_func_list (cu);
- /* Process all dies in compilation unit. */
- if (die->child != NULL)
- {
- child_die = die->child;
- while (child_die && child_die->tag)
- {
- process_die (child_die, cu);
- child_die = sibling_die (child_die);
- }
- }
-
- /* Decode line number information if present. */
+ /* Decode line number information if present. We do this before
+ processing child DIEs, so that the line header table is available
+ for DW_AT_decl_file. */
attr = dwarf2_attr (die, DW_AT_stmt_list, cu);
if (attr)
{
line_header = dwarf_decode_line_header (line_offset, abfd, cu);
if (line_header)
{
- make_cleanup ((make_cleanup_ftype *) free_line_header,
- (void *) line_header);
+ cu->line_header = line_header;
+ make_cleanup (free_cu_line_header, cu);
dwarf_decode_lines (line_header, comp_dir, abfd, cu, NULL);
}
}
+ /* Process all dies in compilation unit. */
+ if (die->child != NULL)
+ {
+ child_die = die->child;
+ while (child_die && child_die->tag)
+ {
+ process_die (child_die, cu);
+ child_die = sibling_die (child_die);
+ }
+ }
+
/* Decode macro information, if present. Dwarf 2 macro information
refers to information in the line number info statement program
header, so we can only read it if we've read the header
TYPE_NFN_FIELDS_TOTAL (type) = total_length;
}
-
/* Returns non-zero if NAME is the name of a vtable member in CU's
language, zero otherwise. */
static int
/* GCC outputs unnamed structures that are really pointers to member
functions, with the ABI-specified layout. If DIE (from CU) describes
such a structure, set its type, and return nonzero. Otherwise return
- zero. */
+ zero.
+
+ GCC shouldn't do this; it should just output pointer to member DIEs.
+ This is GCC PR debug/28767. */
static int
quirk_gcc_member_function_pointer (struct die_info *die, struct dwarf2_cu *cu)
smash_to_method_type (type, domain_type, TYPE_TARGET_TYPE (pfn_type),
TYPE_FIELDS (pfn_type), TYPE_NFIELDS (pfn_type),
TYPE_VARARGS (pfn_type));
- type = lookup_pointer_type (type);
+ type = lookup_methodptr_type (type);
set_die_type (die, type, cu);
return 1;
child_die = sibling_die (child_die);
}
- if (die->child != NULL && ! die_is_declaration (die, cu))
+ /* Do not consider external references. According to the DWARF standard,
+ these DIEs are identified by the fact that they have no byte_size
+ attribute, and a declaration attribute. */
+ if (dwarf2_attr (die, DW_AT_byte_size, cu) != NULL
+ || !die_is_declaration (die, cu))
new_symbol (die, die->type, cu);
processing_current_prefix = previous_prefix;
if (attr)
TYPE_FLAGS (type) |= TYPE_FLAG_VECTOR;
+ attr = dwarf2_attr (die, DW_AT_name, cu);
+ if (attr && DW_STRING (attr))
+ TYPE_NAME (type) = DW_STRING (attr);
+
do_cleanups (back_to);
/* Install the type in the die. */
return;
}
- type = alloc_type (objfile);
to_type = die_type (die, cu);
domain = die_containing_type (die, cu);
- smash_to_member_type (type, domain, to_type);
+
+ if (TYPE_CODE (check_typedef (to_type)) == TYPE_CODE_METHOD)
+ type = lookup_methodptr_type (to_type);
+ else
+ type = lookup_memberptr_type (to_type, domain);
set_die_type (die, type, cu);
}
part_die->has_stmt_list = 1;
part_die->line_offset = DW_UNSND (&attr);
break;
+ case DW_AT_byte_size:
+ part_die->has_byte_size = 1;
+ break;
default:
break;
}
case DW_LANG_Modula2:
cu->language = language_m2;
break;
+ case DW_LANG_Pascal83:
+ cu->language = language_pascal;
+ break;
case DW_LANG_Cobol74:
case DW_LANG_Cobol85:
- case DW_LANG_Pascal83:
default:
cu->language = language_minimal;
break;
fe->mod_time = mod_time;
fe->length = length;
fe->included_p = 0;
+ fe->symtab = NULL;
}
CORE_ADDR baseaddr;
struct objfile *objfile = cu->objfile;
const int decode_for_pst_p = (pst != NULL);
+ struct subfile *last_subfile = NULL, *first_subfile = current_subfile;
baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
lh->file_names[file - 1].included_p = 1;
if (!decode_for_pst_p)
{
+ if (last_subfile != current_subfile)
+ {
+ if (last_subfile)
+ record_line (last_subfile, 0, address);
+ last_subfile = current_subfile;
+ }
/* Append row to matrix using current values. */
record_line (current_subfile, line,
check_cu_functions (address, cu));
case DW_LNS_copy:
lh->file_names[file - 1].included_p = 1;
if (!decode_for_pst_p)
- record_line (current_subfile, line,
- check_cu_functions (address, cu));
+ {
+ if (last_subfile != current_subfile)
+ {
+ if (last_subfile)
+ record_line (last_subfile, 0, address);
+ last_subfile = current_subfile;
+ }
+ record_line (current_subfile, line,
+ check_cu_functions (address, cu));
+ }
basic_block = 0;
break;
case DW_LNS_advance_pc:
dir = lh->include_dirs[fe->dir_index - 1];
if (!decode_for_pst_p)
- dwarf2_start_subfile (fe->name, dir, comp_dir);
+ {
+ last_subfile = current_subfile;
+ dwarf2_start_subfile (fe->name, dir, comp_dir);
+ }
}
break;
case DW_LNS_set_column:
dwarf2_create_include_psymtab (include_name, pst, objfile);
}
}
+ else
+ {
+ /* Make sure a symtab is created for every file, even files
+ which contain only variables (i.e. no code with associated
+ line numbers). */
+
+ int i;
+ struct file_entry *fe;
+
+ for (i = 0; i < lh->num_file_names; i++)
+ {
+ char *dir = NULL;
+ fe = &lh->file_names[i];
+ if (fe->dir_index)
+ dir = lh->include_dirs[fe->dir_index - 1];
+ dwarf2_start_subfile (fe->name, dir, comp_dir);
+
+ /* Skip the main file; we don't need it, and it must be
+ allocated last, so that it will show up before the
+ non-primary symtabs in the objfile's symtab list. */
+ if (current_subfile == first_subfile)
+ continue;
+
+ if (current_subfile->symtab == NULL)
+ current_subfile->symtab = allocate_symtab (current_subfile->name,
+ cu->objfile);
+ fe->symtab = current_subfile->symtab;
+ }
+ }
}
/* Start a subfile for DWARF. FILENAME is the name of the file and
{
SYMBOL_LINE (sym) = DW_UNSND (attr);
}
+
+ attr = dwarf2_attr (die, DW_AT_decl_file, cu);
+ if (attr)
+ {
+ int file_index = DW_UNSND (attr);
+ if (cu->line_header == NULL
+ || file_index > cu->line_header->num_file_names)
+ complaint (&symfile_complaints,
+ _("file index out of range"));
+ else if (file_index > 0)
+ {
+ struct file_entry *fe;
+ fe = &cu->line_header->file_names[file_index - 1];
+ SYMBOL_SYMTAB (sym) = fe->symtab;
+ }
+ }
+
switch (die->tag)
{
case DW_TAG_label:
defines a typedef for the class. Synthesize a typedef symbol
so that "ptype foo" works as expected. */
if (cu->language == language_cplus
- || cu->language == language_java)
+ || cu->language == language_java
+ || cu->language == language_ada)
{
struct symbol *typedef_sym = (struct symbol *)
obstack_alloc (&objfile->objfile_obstack,
return "DW_TAG_partial_unit";
case DW_TAG_imported_unit:
return "DW_TAG_imported_unit";
+ case DW_TAG_condition:
+ return "DW_TAG_condition";
+ case DW_TAG_shared_type:
+ return "DW_TAG_shared_type";
case DW_TAG_MIPS_loop:
return "DW_TAG_MIPS_loop";
+ case DW_TAG_HP_array_descriptor:
+ return "DW_TAG_HP_array_descriptor";
case DW_TAG_format_label:
return "DW_TAG_format_label";
case DW_TAG_function_template:
return "DW_TAG_function_template";
case DW_TAG_class_template:
return "DW_TAG_class_template";
+ case DW_TAG_GNU_BINCL:
+ return "DW_TAG_GNU_BINCL";
+ case DW_TAG_GNU_EINCL:
+ return "DW_TAG_GNU_EINCL";
+ case DW_TAG_upc_shared_type:
+ return "DW_TAG_upc_shared_type";
+ case DW_TAG_upc_strict_type:
+ return "DW_TAG_upc_strict_type";
+ case DW_TAG_upc_relaxed_type:
+ return "DW_TAG_upc_relaxed_type";
+ case DW_TAG_PGI_kanji_type:
+ return "DW_TAG_PGI_kanji_type";
+ case DW_TAG_PGI_interface_block:
+ return "DW_TAG_PGI_interface_block";
default:
return "DW_TAG_<unknown>";
}
return "DW_AT_virtuality";
case DW_AT_vtable_elem_location:
return "DW_AT_vtable_elem_location";
+ /* DWARF 3 values. */
case DW_AT_allocated:
return "DW_AT_allocated";
case DW_AT_associated:
return "DW_AT_call_file";
case DW_AT_call_line:
return "DW_AT_call_line";
+ case DW_AT_description:
+ return "DW_AT_description";
+ case DW_AT_binary_scale:
+ return "DW_AT_binary_scale";
+ case DW_AT_decimal_scale:
+ return "DW_AT_decimal_scale";
+ case DW_AT_small:
+ return "DW_AT_small";
+ case DW_AT_decimal_sign:
+ return "DW_AT_decimal_sign";
+ case DW_AT_digit_count:
+ return "DW_AT_digit_count";
+ case DW_AT_picture_string:
+ return "DW_AT_picture_string";
+ case DW_AT_mutable:
+ return "DW_AT_mutable";
+ case DW_AT_threads_scaled:
+ return "DW_AT_threads_scaled";
+ case DW_AT_explicit:
+ return "DW_AT_explicit";
+ case DW_AT_object_pointer:
+ return "DW_AT_object_pointer";
+ case DW_AT_endianity:
+ return "DW_AT_endianity";
+ case DW_AT_elemental:
+ return "DW_AT_elemental";
+ case DW_AT_pure:
+ return "DW_AT_pure";
+ case DW_AT_recursive:
+ return "DW_AT_recursive";
#ifdef MIPS
+ /* SGI/MIPS extensions. */
case DW_AT_MIPS_fde:
return "DW_AT_MIPS_fde";
case DW_AT_MIPS_loop_begin:
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";
-
+ case DW_AT_MIPS_stride:
+ return "DW_AT_MIPS_stride";
+ case DW_AT_MIPS_abstract_name:
+ return "DW_AT_MIPS_abstract_name";
+ case DW_AT_MIPS_clone_origin:
+ return "DW_AT_MIPS_clone_origin";
+ case DW_AT_MIPS_has_inlines:
+ return "DW_AT_MIPS_has_inlines";
+#endif
+ /* HP extensions. */
+ case DW_AT_HP_block_index:
+ return "DW_AT_HP_block_index";
+ case DW_AT_HP_unmodifiable:
+ return "DW_AT_HP_unmodifiable";
+ case DW_AT_HP_actuals_stmt_list:
+ return "DW_AT_HP_actuals_stmt_list";
+ case DW_AT_HP_proc_per_section:
+ return "DW_AT_HP_proc_per_section";
+ case DW_AT_HP_raw_data_ptr:
+ return "DW_AT_HP_raw_data_ptr";
+ case DW_AT_HP_pass_by_reference:
+ return "DW_AT_HP_pass_by_reference";
+ case DW_AT_HP_opt_level:
+ return "DW_AT_HP_opt_level";
+ case DW_AT_HP_prof_version_id:
+ return "DW_AT_HP_prof_version_id";
+ case DW_AT_HP_opt_flags:
+ return "DW_AT_HP_opt_flags";
+ case DW_AT_HP_cold_region_low_pc:
+ return "DW_AT_HP_cold_region_low_pc";
+ case DW_AT_HP_cold_region_high_pc:
+ return "DW_AT_HP_cold_region_high_pc";
+ case DW_AT_HP_all_variables_modifiable:
+ return "DW_AT_HP_all_variables_modifiable";
+ case DW_AT_HP_linkage_name:
+ return "DW_AT_HP_linkage_name";
+ case DW_AT_HP_prof_flags:
+ return "DW_AT_HP_prof_flags";
+ /* GNU extensions. */
case DW_AT_sf_names:
return "DW_AT_sf_names";
case DW_AT_src_info:
return "DW_AT_body_end";
case DW_AT_GNU_vector:
return "DW_AT_GNU_vector";
+ /* VMS extensions. */
+ case DW_AT_VMS_rtnbeg_pd_address:
+ return "DW_AT_VMS_rtnbeg_pd_address";
+ /* UPC extension. */
+ case DW_AT_upc_threads_scaled:
+ return "DW_AT_upc_threads_scaled";
+ /* PGI (STMicroelectronics) extensions. */
+ case DW_AT_PGI_lbase:
+ return "DW_AT_PGI_lbase";
+ case DW_AT_PGI_soffset:
+ return "DW_AT_PGI_soffset";
+ case DW_AT_PGI_lstride:
+ return "DW_AT_PGI_lstride";
default:
return "DW_AT_<unknown>";
}
return "DW_OP_xderef_size";
case DW_OP_nop:
return "DW_OP_nop";
- /* DWARF 3 extensions. */
+ /* DWARF 3 extensions. */
case DW_OP_push_object_address:
return "DW_OP_push_object_address";
case DW_OP_call2:
return "DW_OP_call4";
case DW_OP_call_ref:
return "DW_OP_call_ref";
- /* GNU extensions. */
+ /* GNU extensions. */
+ case DW_OP_form_tls_address:
+ return "DW_OP_form_tls_address";
+ case DW_OP_call_frame_cfa:
+ return "DW_OP_call_frame_cfa";
+ case DW_OP_bit_piece:
+ return "DW_OP_bit_piece";
case DW_OP_GNU_push_tls_address:
return "DW_OP_GNU_push_tls_address";
+ /* HP extensions. */
+ case DW_OP_HP_is_value:
+ return "DW_OP_HP_is_value";
+ case DW_OP_HP_fltconst4:
+ return "DW_OP_HP_fltconst4";
+ case DW_OP_HP_fltconst8:
+ return "DW_OP_HP_fltconst8";
+ case DW_OP_HP_mod_range:
+ return "DW_OP_HP_mod_range";
+ case DW_OP_HP_unmod_range:
+ return "DW_OP_HP_unmod_range";
+ case DW_OP_HP_tls:
+ return "DW_OP_HP_tls";
default:
return "OP_<unknown>";
}
{
switch (enc)
{
+ case DW_ATE_void:
+ return "DW_ATE_void";
case DW_ATE_address:
return "DW_ATE_address";
case DW_ATE_boolean:
return "DW_ATE_unsigned";
case DW_ATE_unsigned_char:
return "DW_ATE_unsigned_char";
+ /* DWARF 3. */
case DW_ATE_imaginary_float:
return "DW_ATE_imaginary_float";
+ case DW_ATE_packed_decimal:
+ return "DW_ATE_packed_decimal";
+ case DW_ATE_numeric_string:
+ return "DW_ATE_numeric_string";
+ case DW_ATE_edited:
+ return "DW_ATE_edited";
+ case DW_ATE_signed_fixed:
+ return "DW_ATE_signed_fixed";
+ case DW_ATE_unsigned_fixed:
+ return "DW_ATE_unsigned_fixed";
+ case DW_ATE_decimal_float:
+ return "DW_ATE_decimal_float";
+ /* HP extensions. */
+ case DW_ATE_HP_float80:
+ return "DW_ATE_HP_float80";
+ case DW_ATE_HP_complex_float80:
+ return "DW_ATE_HP_complex_float80";
+ case DW_ATE_HP_float128:
+ return "DW_ATE_HP_float128";
+ case DW_ATE_HP_complex_float128:
+ return "DW_ATE_HP_complex_float128";
+ case DW_ATE_HP_floathpintel:
+ return "DW_ATE_HP_floathpintel";
+ case DW_ATE_HP_imaginary_float80:
+ return "DW_ATE_HP_imaginary_float80";
+ case DW_ATE_HP_imaginary_float128:
+ return "DW_ATE_HP_imaginary_float128";
default:
return "DW_ATE_<unknown>";
}
return "DW_CFA_def_cfa_register";
case DW_CFA_def_cfa_offset:
return "DW_CFA_def_cfa_offset";
-
- /* DWARF 3 */
+ /* DWARF 3. */
case DW_CFA_def_cfa_expression:
return "DW_CFA_def_cfa_expression";
case DW_CFA_expression:
return "DW_CFA_def_cfa_sf";
case DW_CFA_def_cfa_offset_sf:
return "DW_CFA_def_cfa_offset_sf";
-
- /* SGI/MIPS specific */
+ case DW_CFA_val_offset:
+ return "DW_CFA_val_offset";
+ case DW_CFA_val_offset_sf:
+ return "DW_CFA_val_offset_sf";
+ case DW_CFA_val_expression:
+ return "DW_CFA_val_expression";
+ /* SGI/MIPS specific. */
case DW_CFA_MIPS_advance_loc8:
return "DW_CFA_MIPS_advance_loc8";
-
- /* GNU extensions */
+ /* GNU extensions. */
case DW_CFA_GNU_window_save:
return "DW_CFA_GNU_window_save";
case DW_CFA_GNU_args_size:
return "DW_CFA_GNU_args_size";
case DW_CFA_GNU_negative_offset_extended:
return "DW_CFA_GNU_negative_offset_extended";
-
default:
return "DW_CFA_<unknown>";
}