X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fdwarf2read.c;h=945a387463d6c7375fe4c9b55ad0d2bdec5f0a39;hb=b9ff3018cd573e009421f7aa357ebba6345adf42;hp=e0f6eb27fb5a9e0eb8ba73bda57ced8acc7bcac8;hpb=4d3c225097b42b1df5e5b703c8e7c3cf9a15c4c3;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index e0f6eb27fb..945a387463 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -1,5 +1,5 @@ /* 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, @@ -38,10 +38,13 @@ #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 #include "gdb_string.h" #include "gdb_assert.h" @@ -133,6 +136,7 @@ static file_ptr dwarf_aranges_offset; static file_ptr dwarf_loc_offset; static file_ptr dwarf_macinfo_offset; static file_ptr dwarf_str_offset; +static file_ptr dwarf_ranges_offset; file_ptr dwarf_frame_offset; file_ptr dwarf_eh_frame_offset; @@ -144,9 +148,22 @@ static unsigned int dwarf_aranges_size; static unsigned int dwarf_loc_size; static unsigned int dwarf_macinfo_size; static unsigned int dwarf_str_size; +static unsigned int dwarf_ranges_size; 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" @@ -157,6 +174,7 @@ unsigned int dwarf_eh_frame_size; #define LOC_SECTION ".debug_loc" #define MACINFO_SECTION ".debug_macinfo" #define STR_SECTION ".debug_str" +#define RANGES_SECTION ".debug_ranges" #define FRAME_SECTION ".debug_frame" #define EH_FRAME_SECTION ".eh_frame" @@ -202,6 +220,14 @@ struct comp_unit_head /* DWARF abbreviation table associated with this compilation unit */ struct abbrev_info *dwarf2_abbrevs[ABBREV_HASH_SIZE]; + + /* Base address of this compilation unit. */ + + 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 @@ -373,6 +399,8 @@ static char *dwarf_abbrev_buffer; static char *dwarf_line_buffer; 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; @@ -410,12 +438,6 @@ static int islocal; /* Variable is at the returned offset 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 @@ -481,6 +503,21 @@ struct dwarf2_pinfo unsigned int dwarf_macinfo_size; + /* Pointer to start of dwarf ranges buffer for the objfile. */ + + char *dwarf_ranges_buffer; + + /* Size of dwarf ranges buffer for the objfile. */ + + 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) @@ -494,6 +531,10 @@ struct dwarf2_pinfo #define DWARF_STR_SIZE(p) (PST_PRIVATE(p)->dwarf_str_size) #define DWARF_MACINFO_BUFFER(p) (PST_PRIVATE(p)->dwarf_macinfo_buffer) #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 @@ -621,7 +662,7 @@ dwarf2_invalid_attrib_class_complaint (const char *arg1, const char *arg2) /* local function prototypes */ -static void dwarf2_locate_sections (bfd *, asection *, PTR); +static void dwarf2_locate_sections (bfd *, asection *, void *); #if 0 static void dwarf2_build_psymtabs_easy (struct objfile *, int); @@ -631,20 +672,41 @@ static void dwarf2_build_psymtabs_hard (struct objfile *, int); 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 *); 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 void dwarf2_empty_abbrev_table (PTR); +static void dwarf2_empty_abbrev_table (void *); static struct abbrev_info *dwarf2_lookup_abbrev (unsigned int, const struct comp_unit_head *cu_header); @@ -751,7 +813,8 @@ static void read_lexical_block_scope (struct die_info *, struct objfile *, const struct comp_unit_head *); static int dwarf2_get_pc_bounds (struct die_info *, - CORE_ADDR *, CORE_ADDR *, struct objfile *); + CORE_ADDR *, CORE_ADDR *, struct objfile *, + const struct comp_unit_head *); static void dwarf2_add_field (struct field_info *, struct die_info *, struct objfile *, const struct comp_unit_head *); @@ -819,6 +882,10 @@ static void process_die (struct die_info *, struct objfile *, 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); @@ -855,7 +922,7 @@ static struct type *dwarf2_fundamental_type (struct objfile *, int); /* memory allocation interface */ -static void dwarf2_free_tmp_obstack (PTR); +static void dwarf2_free_tmp_obstack (void *); static struct dwarf_block *dwarf_alloc_block (void); @@ -873,6 +940,11 @@ static void dwarf_decode_macros (struct line_header *, 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. */ @@ -886,6 +958,9 @@ dwarf2_has_info (bfd *abfd) dwarf_macinfo_offset = 0; 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) { @@ -902,57 +977,77 @@ dwarf2_has_info (bfd *abfd) in. */ static void -dwarf2_locate_sections (bfd *ignore_abfd, asection *sectp, PTR ignore_ptr) +dwarf2_locate_sections (bfd *ignore_abfd, asection *sectp, void *ignore_ptr) { if (STREQ (sectp->name, INFO_SECTION)) { 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); + 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)) + { + dwarf_ranges_offset = sectp->filepos; + dwarf_ranges_size = bfd_get_section_size_before_reloc (sectp); + dwarf_ranges_section = sectp; } } @@ -966,32 +1061,53 @@ dwarf2_build_psymtabs (struct objfile *objfile, int mainline) 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_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)) @@ -1030,7 +1146,8 @@ dwarf2_build_psymtabs_easy (struct objfile *objfile, int mainline) 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) { @@ -1050,7 +1167,8 @@ dwarf2_build_psymtabs_easy (struct objfile *objfile, int mainline) aranges_buffer = dwarf2_read_section (objfile, dwarf_aranges_offset, - dwarf_aranges_size); + dwarf_aranges_size, + dwarf_aranges_section); } #endif @@ -1153,22 +1271,24 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline) 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 */ @@ -1207,6 +1327,10 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline) DWARF_STR_SIZE (pst) = dwarf_str_size; DWARF_MACINFO_BUFFER (pst) = dwarf_macinfo_buffer; 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 */ @@ -1217,9 +1341,17 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline) 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) @@ -1248,45 +1380,40 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline) 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) { @@ -1301,93 +1428,77 @@ scan_partial_symbols (char *info_ptr, struct objfile *objfile, { *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) { @@ -1396,19 +1507,21 @@ add_partial_symbol (struct partial_die_info *pdi, struct objfile *objfile, { /*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, - &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_NAMESPACE, 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: @@ -1430,10 +1543,11 @@ add_partial_symbol (struct partial_die_info *pdi, struct objfile *objfile, 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_NAMESPACE, 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 { @@ -1443,16 +1557,17 @@ add_partial_symbol (struct partial_die_info *pdi, struct objfile *objfile, 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_NAMESPACE, 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: 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; @@ -1465,7 +1580,7 @@ add_partial_symbol (struct partial_die_info *pdi, struct objfile *objfile, 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); @@ -1473,20 +1588,138 @@ add_partial_symbol (struct partial_die_info *pdi, struct objfile *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; 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. */ @@ -1531,6 +1764,7 @@ psymtab_to_symtab_1 (struct partial_symtab *pst) 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); @@ -1543,6 +1777,10 @@ psymtab_to_symtab_1 (struct partial_symtab *pst) dwarf_str_size = DWARF_STR_SIZE (pst); dwarf_macinfo_buffer = DWARF_MACINFO_BUFFER (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; @@ -1564,10 +1802,35 @@ psymtab_to_symtab_1 (struct partial_symtab *pst) 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 () */ process_die (dies, objfile, &cu_header); - if (!dwarf2_get_pc_bounds (dies, &lowpc, &highpc, objfile)) + if (!dwarf2_get_pc_bounds (dies, &lowpc, &highpc, objfile, &cu_header)) { /* Some compilers don't define a DW_AT_high_pc attribute for the compilation unit. If the DW_AT_high_pc is missing, @@ -1582,7 +1845,8 @@ psymtab_to_symtab_1 (struct partial_symtab *pst) { CORE_ADDR low, high; - if (dwarf2_get_pc_bounds (child_die, &low, &high, objfile)) + if (dwarf2_get_pc_bounds (child_die, &low, &high, + objfile, &cu_header)) { highpc = max (highpc, high); } @@ -1603,7 +1867,6 @@ psymtab_to_symtab_1 (struct partial_symtab *pst) } pst->symtab = symtab; pst->readin = 1; - sort_symtab_syms (pst->symtab); do_cleanups (back_to); } @@ -1631,6 +1894,8 @@ process_die (struct die_info *die, struct objfile *objfile, 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: @@ -1673,6 +1938,11 @@ process_die (struct die_info *die, struct objfile *objfile, 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: @@ -1683,6 +1953,11 @@ process_die (struct die_info *die, struct objfile *objfile, 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: @@ -1711,7 +1986,7 @@ read_file_scope (struct die_info *die, struct objfile *objfile, bfd *abfd = objfile->obfd; struct line_header *line_header = 0; - if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile)) + if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile, cu_header)) { if (die->has_children) { @@ -1722,7 +1997,8 @@ read_file_scope (struct die_info *die, struct objfile *objfile, { CORE_ADDR low, high; - if (dwarf2_get_pc_bounds (child_die, &low, &high, objfile)) + if (dwarf2_get_pc_bounds (child_die, &low, &high, + objfile, cu_header)) { lowpc = min (lowpc, low); highpc = max (highpc, high); @@ -1763,8 +2039,8 @@ read_file_scope (struct die_info *die, struct objfile *objfile, 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); @@ -1857,7 +2133,7 @@ static void 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; @@ -1868,7 +2144,7 @@ read_func_scope (struct die_info *die, struct objfile *objfile, /* Ignore functions with missing or empty names and functions with missing or invalid low and high pc attributes. */ - if (name == NULL || !dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile)) + if (name == NULL || !dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile, cu_header)) return; lowpc += baseaddr; @@ -1924,6 +2200,13 @@ read_func_scope (struct die_info *die, struct objfile *objfile, 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) @@ -1961,12 +2244,16 @@ static void 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; /* Ignore blocks with missing or invalid low and high pc attributes. */ - if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile)) + /* ??? Perhaps consider discontiguous blocks defined by DW_AT_ranges + as multiple lexical blocks? Handling children in a sane way would + be nasty. Might be easier to properly extend generic blocks to + describe ranges. */ + if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile, cu_header)) return; lowpc += baseaddr; highpc += baseaddr; @@ -1991,27 +2278,148 @@ read_lexical_block_scope (struct die_info *die, struct objfile *objfile, local_symbols = new->locals; } -/* Get low and high pc attributes from a die. - Return 1 if the attributes are present and valid, otherwise, return 0. */ - +/* Get low and high pc attributes from a die. Return 1 if the attributes + are present and valid, otherwise, return 0. Return -1 if the range is + discontinuous, i.e. derived from DW_AT_ranges information. */ static int -dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc, CORE_ADDR *highpc, - struct objfile *objfile) +dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc, + CORE_ADDR *highpc, struct objfile *objfile, + const struct comp_unit_head *cu_header) { struct attribute *attr; - CORE_ADDR low; - CORE_ADDR high; + bfd *obfd = objfile->obfd; + CORE_ADDR low = 0; + CORE_ADDR high = 0; + int ret = 0; - attr = dwarf_attr (die, DW_AT_low_pc); - if (attr) - low = DW_ADDR (attr); - else - return 0; attr = dwarf_attr (die, DW_AT_high_pc); if (attr) - high = DW_ADDR (attr); + { + high = DW_ADDR (attr); + attr = dwarf_attr (die, DW_AT_low_pc); + if (attr) + low = DW_ADDR (attr); + else + /* Found high w/o low attribute. */ + return 0; + + /* Found consecutive range of addresses. */ + ret = 1; + } else - return 0; + { + attr = dwarf_attr (die, DW_AT_ranges); + if (attr != NULL) + { + 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_ranges section. */ + unsigned int offset = DW_UNSND (attr); + /* Base address selection entry. */ + CORE_ADDR base; + int found_base; + int dummy; + unsigned int i; + char *buffer; + CORE_ADDR marker; + int low_set; + + 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. */ + marker = read_address (obfd, buffer, cu_header, &dummy); + if ((marker & mask) == mask) + { + /* If we found the largest possible address, then + read the base address. */ + base = read_address (obfd, buffer + addr_size, + cu_header, &dummy); + buffer += 2 * addr_size; + offset += 2 * addr_size; + found_base = 1; + } + + low_set = 0; + + while (1) + { + CORE_ADDR range_beginning, range_end; + + range_beginning = read_address (obfd, buffer, + cu_header, &dummy); + buffer += addr_size; + range_end = read_address (obfd, buffer, cu_header, &dummy); + buffer += addr_size; + offset += 2 * addr_size; + + /* An end of list marker is a pair of zero addresses. */ + if (range_beginning == 0 && range_end == 0) + /* Found the end of list entry. */ + break; + + /* Each base address selection entry is a pair of 2 values. + The first is the largest possible address, the second is + the base address. Check for a base address here. */ + if ((range_beginning & mask) == mask) + { + /* If we found the largest possible address, then + read the base address. */ + base = read_address (obfd, buffer + addr_size, + cu_header, &dummy); + found_base = 1; + continue; + } + + if (!found_base) + { + /* We have no valid base address for the ranges + data. */ + complaint (&symfile_complaints, + "Invalid .debug_ranges data (no base address)"); + 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 + instead. */ + if (! low_set) + { + low = range_beginning; + high = range_end; + low_set = 1; + } + else + { + if (range_beginning < low) + low = range_beginning; + if (range_end > high) + high = range_end; + } + } + + if (! low_set) + /* If the first entry is an end-of-list marker, the range + describes an empty scope, i.e. no instructions. */ + return 0; + + ret = -1; + } + } if (high < low) return 0; @@ -2024,12 +2432,12 @@ dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc, CORE_ADDR *highpc, labels are not in the output, so the relocs get a value of 0. If this is a discarded function, mark the pc bounds as invalid, so that GDB will ignore it. */ - if (low == 0 && (bfd_get_file_flags (objfile->obfd) & HAS_RELOC) == 0) + if (low == 0 && (bfd_get_file_flags (obfd) & HAS_RELOC) == 0) return 0; *lowpc = low; *highpc = high; - return 1; + return ret; } /* Add an aggregate field to the field list. */ @@ -2700,7 +3108,7 @@ read_enumeration (struct die_info *die, struct objfile *objfile, * 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; @@ -2930,13 +3338,74 @@ read_common_block (struct die_info *die, struct objfile *objfile, /* 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; + } + + /* 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; + + /* 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 die_info *child_die = die->next; @@ -2947,6 +3416,8 @@ read_namespace (struct die_info *die, struct objfile *objfile, child_die = sibling_die (child_die); } } + + processing_current_namespace = previous_namespace; } /* Extract all information from a DW_TAG_pointer_type DIE and add to @@ -3408,15 +3879,20 @@ make_cleanup_free_die_list (struct die_info *dies) 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)) { @@ -3507,7 +3983,7 @@ dwarf2_read_abbrevs (bfd *abfd, struct comp_unit_head *cu_header) /* ARGSUSED */ static void -dwarf2_empty_abbrev_table (PTR ptr_to_abbrevs_table) +dwarf2_empty_abbrev_table (void *ptr_to_abbrevs_table) { int i; struct abbrev_info *abbrev, *next; @@ -3574,7 +4050,8 @@ read_partial_die (struct partial_die_info *part_die, bfd *abfd, 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; @@ -3718,7 +4195,8 @@ read_full_die (struct die_info **diep, bfd *abfd, char *info_ptr, 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; @@ -3854,8 +4332,9 @@ read_attribute_value (struct attribute *attr, unsigned form, 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; } @@ -3936,7 +4415,8 @@ read_address (bfd *abfd, char *buf, const struct comp_unit_head *cu_header, break; default: internal_error (__FILE__, __LINE__, - "read_address: bad switch, signed"); + "read_address: bad switch, signed [in module %s]", + bfd_get_filename (abfd)); } } else @@ -3954,7 +4434,8 @@ read_address (bfd *abfd, char *buf, const struct comp_unit_head *cu_header, break; default: internal_error (__FILE__, __LINE__, - "read_address: bad switch, unsigned"); + "read_address: bad switch, unsigned [in module %s]", + bfd_get_filename (abfd)); } } @@ -4069,7 +4550,8 @@ read_offset (bfd *abfd, char *buf, const struct comp_unit_head *cu_header, break; default: internal_error (__FILE__, __LINE__, - "read_offset: bad switch"); + "read_offset: bad switch [in module %s]", + bfd_get_filename (abfd)); } return retval; @@ -4111,12 +4593,14 @@ read_indirect_string (bfd *abfd, char *buf, 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); @@ -4215,7 +4699,7 @@ set_cu_language (unsigned int lang) 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); @@ -4545,8 +5029,8 @@ dwarf_decode_lines (struct line_header *lh, char *comp_dir, bfd *abfd, * 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) @@ -4592,8 +5076,8 @@ dwarf_decode_lines (struct line_header *lh, char *comp_dir, bfd *abfd, } 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: @@ -4704,6 +5188,61 @@ dwarf2_start_subfile (char *filename, char *dirname) 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. @@ -4720,19 +5259,25 @@ new_symbol (struct die_info *die, struct type *type, struct objfile *objfile, 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, 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; @@ -4743,15 +5288,6 @@ new_symbol (struct die_info *die, struct type *type, struct objfile *objfile, { 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: @@ -4799,106 +5335,12 @@ new_symbol (struct die_info *die, struct type *type, struct objfile *objfile, 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 { @@ -4921,32 +5363,10 @@ new_symbol (struct die_info *die, struct type *type, struct objfile *objfile, 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) @@ -4965,7 +5385,7 @@ new_symbol (struct die_info *die, struct type *type, struct objfile *objfile, 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 @@ -4977,11 +5397,11 @@ new_symbol (struct die_info *die, struct type *type, struct objfile *objfile, 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); } @@ -4989,7 +5409,7 @@ new_symbol (struct die_info *die, struct type *type, struct objfile *objfile, 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: @@ -5000,6 +5420,10 @@ new_symbol (struct die_info *die, struct type *type, struct objfile *objfile, } 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 @@ -5026,14 +5450,16 @@ dwarf2_const_value (struct attribute *attr, struct symbol *sym, { 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: @@ -5042,7 +5468,7 @@ dwarf2_const_value (struct attribute *attr, struct symbol *sym, 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))); @@ -5136,7 +5562,8 @@ die_type (struct die_info *die, struct objfile *objfile, 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; } } @@ -5144,7 +5571,8 @@ die_type (struct die_info *die, struct objfile *objfile, 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; } @@ -5168,7 +5596,8 @@ die_containing_type (struct die_info *die, struct objfile *objfile, 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); @@ -5177,7 +5606,8 @@ die_containing_type (struct die_info *die, struct objfile *objfile, { 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; } @@ -5214,7 +5644,8 @@ tag_type_to_type (struct die_info *die, struct objfile *objfile, 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; } @@ -5441,10 +5872,47 @@ dwarf2_linkage_name (struct die_info *die) 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 * -dwarf_tag_name (register unsigned tag) +dwarf_tag_name (unsigned tag) { switch (tag) { @@ -5576,7 +6044,7 @@ dwarf_tag_name (register unsigned 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) { @@ -5741,9 +6209,9 @@ dwarf_attr_name (register unsigned 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"; @@ -5767,7 +6235,7 @@ dwarf_attr_name (register unsigned attr) /* 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) { @@ -5821,7 +6289,7 @@ dwarf_form_name (register unsigned 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) { @@ -6144,7 +6612,7 @@ dwarf_bool_name (unsigned mybool) /* 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) { @@ -6175,7 +6643,7 @@ dwarf_type_encoding_name (register unsigned enc) #if 0 static char * -dwarf_cfi_name (register unsigned cfi_opc) +dwarf_cfi_name (unsigned cfi_opc) { switch (cfi_opc) { @@ -6389,8 +6857,8 @@ dwarf2_fundamental_type (struct objfile *objfile, int typeid) { 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 @@ -6452,7 +6920,6 @@ decode_locdesc (struct dwarf_block *blk, struct objfile *objfile, offreg = 0; isderef = 0; islocal = 0; - is_thread_local = 0; optimized_out = 1; while (i < size) @@ -6678,7 +7145,6 @@ decode_locdesc (struct dwarf_block *blk, struct objfile *objfile, 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 @@ -6700,7 +7166,7 @@ decode_locdesc (struct dwarf_block *blk, struct objfile *objfile, /* ARGSUSED */ static void -dwarf2_free_tmp_obstack (PTR ignore) +dwarf2_free_tmp_obstack (void *ignore) { obstack_free (&dwarf2_tmp_obstack, NULL); } @@ -7123,3 +7589,59 @@ attr_form_is_block (struct attribute *attr) || 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; + } +}