/* DWARF 2 debugging format support for GDB.
Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
- 2004, 2005, 2006, 2007, 2008, 2009, 2010
+ 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
Free Software Foundation, Inc.
Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology,
#include "vec.h"
#include "c-lang.h"
#include "valprint.h"
+#include <ctype.h>
#include <fcntl.h>
#include "gdb_string.h"
asection *asection;
gdb_byte *buffer;
bfd_size_type size;
- int was_mmapped;
+ /* Not NULL if the section was actually mmapped. */
+ void *map_addr;
+ /* Page aligned size of mmapped area. */
+ bfd_size_type map_len;
/* True if we have tried to read this section. */
int readin;
};
a comment by the code that writes the index. */
struct mapped_index
{
+ /* Index data format version. */
+ int version;
+
/* The total length of the buffer. */
off_t total_size;
+
/* A pointer to the address table data. */
const gdb_byte *address_table;
+
/* Size of the address table data in bytes. */
offset_type address_table_size;
+
/* The symbol table, implemented as a hash table. */
const offset_type *symbol_table;
+
/* Size in slots, each slot is 2 offset_types. */
offset_type symbol_table_slots;
+
/* A pointer to the constant pool. */
const char *constant_pool;
};
/* The mapped index, or NULL if .gdb_index is missing or not being used. */
struct mapped_index *index_table;
+ /* When using index_table, this keeps track of all quick_file_names entries.
+ TUs can share line table entries with CUs or other TUs, and there can be
+ a lot more TUs than unique line tables, so we maintain a separate table
+ of all line table entries to support the sharing. */
+ htab_t quick_file_names_table;
+
/* Set during partial symbol reading, to prevent queueing of full
symbols. */
int reading_partial_symbols;
static struct dwarf2_per_objfile *dwarf2_per_objfile;
-/* names of the debugging sections */
+/* Default names of the debugging sections. */
/* Note that if the debugging section has been compressed, it might
have a name like .zdebug_info. */
-#define INFO_SECTION "debug_info"
-#define ABBREV_SECTION "debug_abbrev"
-#define LINE_SECTION "debug_line"
-#define LOC_SECTION "debug_loc"
-#define MACINFO_SECTION "debug_macinfo"
-#define STR_SECTION "debug_str"
-#define RANGES_SECTION "debug_ranges"
-#define TYPES_SECTION "debug_types"
-#define FRAME_SECTION "debug_frame"
-#define EH_FRAME_SECTION "eh_frame"
-#define GDB_INDEX_SECTION "gdb_index"
+static const struct dwarf2_debug_sections dwarf2_elf_names = {
+ { ".debug_info", ".zdebug_info" },
+ { ".debug_abbrev", ".zdebug_abbrev" },
+ { ".debug_line", ".zdebug_line" },
+ { ".debug_loc", ".zdebug_loc" },
+ { ".debug_macinfo", ".zdebug_macinfo" },
+ { ".debug_str", ".zdebug_str" },
+ { ".debug_ranges", ".zdebug_ranges" },
+ { ".debug_types", ".zdebug_types" },
+ { ".debug_frame", ".zdebug_frame" },
+ { ".eh_frame", NULL },
+ { ".gdb_index", ".zgdb_index" }
+};
/* local data types */
-/* We hold several abbreviation tables in memory at the same time. */
+/* We hold several abbreviation tables in memory at the same time. */
#ifndef ABBREV_HASH_SIZE
#define ABBREV_HASH_SIZE 121
#endif
DIEs for namespaces, we don't need to try to infer them
from mangled names. */
unsigned int has_namespace_info : 1;
-};
-
-/* When using the index (and thus not using psymtabs), each CU has an
- object of this type. This is used to hold information needed by
- the various "quick" methods. */
-struct dwarf2_per_cu_quick_data
-{
- /* The line table. This can be NULL if there was no line table. */
- struct line_header *lines;
- /* The file names from the line table. */
- const char **file_names;
- /* The file names from the line table after being run through
- gdb_realpath. */
- const char **full_names;
-
- /* The corresponding symbol table. This is NULL if symbols for this
- CU have not yet been read. */
- struct symtab *symtab;
+ /* This CU references .debug_loc. See the symtab->locations_valid field.
+ This test is imperfect as there may exist optimized debug code not using
+ any location list and still facing inlining issues if handled as
+ unoptimized code. For a future better test see GCC PR other/32998. */
- /* A temporary mark bit used when iterating over all CUs in
- expand_symtabs_matching. */
- unsigned int mark : 1;
-
- /* True if we've tried to read the line table. */
- unsigned int read_lines : 1;
+ unsigned int has_loclist : 1;
};
/* Persistent data held for a compilation unit, even when not
{
ULONGEST signature;
- /* Offset in .debug_types of the TU (type_unit) for this type. */
- unsigned int offset;
-
/* Offset in .debug_types of the type defined by this TU. */
unsigned int type_offset;
struct dwarf2_per_cu_data per_cu;
};
-/* Struct used to pass misc. parameters to read_die_and_children, et. al.
- which are used for both .debug_info and .debug_types dies.
- All parameters here are unchanging for the life of the call.
- This struct exists to abstract away the constant parameters of
- die reading. */
+/* Struct used to pass misc. parameters to read_die_and_children, et
+ al. which are used for both .debug_info and .debug_types dies.
+ All parameters here are unchanging for the life of the call. This
+ struct exists to abstract away the constant parameters of die
+ reading. */
struct die_reader_specs
{
};
/* When we construct a partial symbol table entry we only
- need this much information. */
+ need this much information. */
struct partial_die_info
{
/* Offset of this DIE. */
struct partial_die_info *die_parent, *die_child, *die_sibling;
};
-/* This data structure holds the information of an abbrev. */
+/* This data structure holds the information of an abbrev. */
struct abbrev_info
{
unsigned int number; /* number identifying abbrev */
ENUM_BITFIELD(dwarf_form) form : 16;
};
-/* Attributes have a name and a value */
+/* Attributes have a name and a value. */
struct attribute
{
ENUM_BITFIELD(dwarf_attribute) name : 16;
u;
};
-/* This data structure holds a complete die structure. */
+/* This data structure holds a complete die structure. */
struct die_info
{
/* DWARF-2 tag for this DIE. */
struct function_range *next;
};
-/* Get at parts of an attribute structure */
+/* Get at parts of an attribute structure. */
#define DW_STRING(attr) ((attr)->u.str)
#define DW_STRING_IS_CANONICAL(attr) ((attr)->string_is_canonical)
#define DW_ADDR(attr) ((attr)->u.addr)
#define DW_SIGNATURED_TYPE(attr) ((attr)->u.signatured_type)
-/* Blocks are a bunch of untyped bytes. */
+/* Blocks are a bunch of untyped bytes. */
struct dwarf_block
{
unsigned int size;
in an instance of a field_info structure, as defined below. */
struct field_info
{
- /* List of data member and baseclasses fields. */
+ /* List of data member and baseclasses fields. */
struct nextfield
{
struct nextfield *next;
show_dwarf2_max_cache_age (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
- fprintf_filtered (file, _("\
-The upper bound on the age of cached dwarf2 compilation units is %s.\n"),
+ fprintf_filtered (file, _("The upper bound on the age of cached "
+ "dwarf2 compilation units is %s.\n"),
value);
}
-/* Various complaints about symbol reading that don't abort the process */
+/* Various complaints about symbol reading that don't abort the process. */
static void
dwarf2_statement_list_fits_in_line_number_section_complaint (void)
dwarf2_debug_line_missing_end_sequence_complaint (void)
{
complaint (&symfile_complaints,
- _(".debug_line section has line program sequence without an end"));
+ _(".debug_line section has line "
+ "program sequence without an end"));
}
static void
int arg3)
{
complaint (&symfile_complaints,
- _("const value length mismatch for '%s', got %d, expected %d"), arg1,
- arg2, arg3);
+ _("const value length mismatch for '%s', got %d, expected %d"),
+ arg1, arg2, arg3);
}
static void
dwarf2_macro_malformed_definition_complaint (const char *arg1)
{
complaint (&symfile_complaints,
- _("macro debug info contains a malformed macro definition:\n`%s'"),
+ _("macro debug info contains a "
+ "malformed macro definition:\n`%s'"),
arg1);
}
dwarf2_invalid_attrib_class_complaint (const char *arg1, const char *arg2)
{
complaint (&symfile_complaints,
- _("invalid attribute class or form for '%s' in '%s'"), arg1, arg2);
+ _("invalid attribute class or form for '%s' in '%s'"),
+ arg1, arg2);
}
/* local function prototypes */
static int need_gnat_info (struct dwarf2_cu *);
-static struct type *die_descriptive_type (struct die_info *, struct dwarf2_cu *);
+static struct type *die_descriptive_type (struct die_info *,
+ struct dwarf2_cu *);
static void set_descriptive_type (struct type *, struct die_info *,
struct dwarf2_cu *);
struct dwarf2_cu *);
static void dwarf2_attach_fn_fields_to_type (struct field_info *,
- struct type *, struct dwarf2_cu *);
+ struct type *,
+ struct dwarf2_cu *);
static void process_structure_scope (struct die_info *, struct dwarf2_cu *);
struct dwarf2_cu *cu);
/* Try to locate the sections we need for DWARF 2 debugging
- information and return true if we have enough to do something. */
+ information and return true if we have enough to do something.
+ NAMES points to the dwarf2 section names, or is NULL if the standard
+ ELF names are used. */
int
-dwarf2_has_info (struct objfile *objfile)
+dwarf2_has_info (struct objfile *objfile,
+ const struct dwarf2_debug_sections *names)
{
dwarf2_per_objfile = objfile_data (objfile, dwarf2_objfile_data_key);
if (!dwarf2_per_objfile)
set_objfile_data (objfile, dwarf2_objfile_data_key, data);
dwarf2_per_objfile = data;
- bfd_map_over_sections (objfile->obfd, dwarf2_locate_sections, NULL);
+ bfd_map_over_sections (objfile->obfd, dwarf2_locate_sections,
+ (void *) names);
dwarf2_per_objfile->objfile = objfile;
}
return (dwarf2_per_objfile->info.asection != NULL
&& dwarf2_per_objfile->abbrev.asection != NULL);
}
-/* When loading sections, we can either look for ".<name>", or for
- * ".z<name>", which indicates a compressed section. */
+/* When loading sections, we look either for uncompressed section or for
+ compressed section names. */
static int
-section_is_p (const char *section_name, const char *name)
+section_is_p (const char *section_name,
+ const struct dwarf2_section_names *names)
{
- return (section_name[0] == '.'
- && (strcmp (section_name + 1, name) == 0
- || (section_name[1] == 'z'
- && strcmp (section_name + 2, name) == 0)));
+ if (names->normal != NULL
+ && strcmp (section_name, names->normal) == 0)
+ return 1;
+ if (names->compressed != NULL
+ && strcmp (section_name, names->compressed) == 0)
+ return 1;
+ return 0;
}
/* This function is mapped across the sections and remembers the
in. */
static void
-dwarf2_locate_sections (bfd *abfd, asection *sectp, void *ignore_ptr)
+dwarf2_locate_sections (bfd *abfd, asection *sectp, void *vnames)
{
- if (section_is_p (sectp->name, INFO_SECTION))
+ const struct dwarf2_debug_sections *names;
+
+ if (vnames == NULL)
+ names = &dwarf2_elf_names;
+ else
+ names = (const struct dwarf2_debug_sections *) vnames;
+
+ if (section_is_p (sectp->name, &names->info))
{
dwarf2_per_objfile->info.asection = sectp;
dwarf2_per_objfile->info.size = bfd_get_section_size (sectp);
}
- else if (section_is_p (sectp->name, ABBREV_SECTION))
+ else if (section_is_p (sectp->name, &names->abbrev))
{
dwarf2_per_objfile->abbrev.asection = sectp;
dwarf2_per_objfile->abbrev.size = bfd_get_section_size (sectp);
}
- else if (section_is_p (sectp->name, LINE_SECTION))
+ else if (section_is_p (sectp->name, &names->line))
{
dwarf2_per_objfile->line.asection = sectp;
dwarf2_per_objfile->line.size = bfd_get_section_size (sectp);
}
- else if (section_is_p (sectp->name, LOC_SECTION))
+ else if (section_is_p (sectp->name, &names->loc))
{
dwarf2_per_objfile->loc.asection = sectp;
dwarf2_per_objfile->loc.size = bfd_get_section_size (sectp);
}
- else if (section_is_p (sectp->name, MACINFO_SECTION))
+ else if (section_is_p (sectp->name, &names->macinfo))
{
dwarf2_per_objfile->macinfo.asection = sectp;
dwarf2_per_objfile->macinfo.size = bfd_get_section_size (sectp);
}
- else if (section_is_p (sectp->name, STR_SECTION))
+ else if (section_is_p (sectp->name, &names->str))
{
dwarf2_per_objfile->str.asection = sectp;
dwarf2_per_objfile->str.size = bfd_get_section_size (sectp);
}
- else if (section_is_p (sectp->name, FRAME_SECTION))
+ else if (section_is_p (sectp->name, &names->frame))
{
dwarf2_per_objfile->frame.asection = sectp;
dwarf2_per_objfile->frame.size = bfd_get_section_size (sectp);
}
- else if (section_is_p (sectp->name, EH_FRAME_SECTION))
+ else if (section_is_p (sectp->name, &names->eh_frame))
{
flagword aflag = bfd_get_section_flags (ignore_abfd, sectp);
dwarf2_per_objfile->eh_frame.size = bfd_get_section_size (sectp);
}
}
- else if (section_is_p (sectp->name, RANGES_SECTION))
+ else if (section_is_p (sectp->name, &names->ranges))
{
dwarf2_per_objfile->ranges.asection = sectp;
dwarf2_per_objfile->ranges.size = bfd_get_section_size (sectp);
}
- else if (section_is_p (sectp->name, TYPES_SECTION))
+ else if (section_is_p (sectp->name, &names->types))
{
dwarf2_per_objfile->types.asection = sectp;
dwarf2_per_objfile->types.size = bfd_get_section_size (sectp);
}
- else if (section_is_p (sectp->name, GDB_INDEX_SECTION))
+ else if (section_is_p (sectp->name, &names->gdb_index))
{
dwarf2_per_objfile->gdb_index.asection = sectp;
dwarf2_per_objfile->gdb_index.size = bfd_get_section_size (sectp);
int header_size = 12;
if (bfd_seek (abfd, sectp->filepos, SEEK_SET) != 0
- || bfd_bread (compressed_buffer, compressed_size, abfd) != compressed_size)
+ || bfd_bread (compressed_buffer,
+ compressed_size, abfd) != compressed_size)
error (_("Dwarf Error: Can't read DWARF data from '%s'"),
bfd_get_filename (abfd));
#endif
}
+/* A helper function that decides whether a section is empty. */
+
+static int
+dwarf2_section_empty_p (struct dwarf2_section_info *info)
+{
+ return info->asection == NULL || info->size == 0;
+}
+
/* Read the contents of the section SECTP from object file specified by
OBJFILE, store info about the section into INFO.
If the section is compressed, uncompress it before returning. */
if (info->readin)
return;
info->buffer = NULL;
- info->was_mmapped = 0;
+ info->map_addr = NULL;
info->readin = 1;
- if (info->asection == NULL || info->size == 0)
+ if (dwarf2_section_empty_p (info))
return;
/* Check if the file has a 4-byte header indicating compression. */
if (info->size > 4 * pagesize && (sectp->flags & SEC_RELOC) == 0)
{
- off_t pg_offset = sectp->filepos & ~(pagesize - 1);
- size_t map_length = info->size + sectp->filepos - pg_offset;
- caddr_t retbuf = bfd_mmap (abfd, 0, map_length, PROT_READ,
- MAP_PRIVATE, pg_offset);
+ info->buffer = bfd_mmap (abfd, 0, info->size, PROT_READ,
+ MAP_PRIVATE, sectp->filepos,
+ &info->map_addr, &info->map_len);
- if (retbuf != MAP_FAILED)
+ if ((caddr_t)info->buffer != MAP_FAILED)
{
- info->was_mmapped = 1;
- info->buffer = retbuf + (sectp->filepos & (pagesize - 1)) ;
#if HAVE_POSIX_MADVISE
- posix_madvise (retbuf, map_length, POSIX_MADV_WILLNEED);
+ posix_madvise (info->map_addr, info->map_len, POSIX_MADV_WILLNEED);
#endif
return;
}
bfd_get_filename (abfd));
}
+/* A helper function that returns the size of a section in a safe way.
+ If you are positive that the section has been read before using the
+ size, then it is safe to refer to the dwarf2_section_info object's
+ "size" field directly. In other cases, you must call this
+ function, because for compressed sections the size field is not set
+ correctly until the section has been read. */
+
+static bfd_size_type
+dwarf2_section_size (struct objfile *objfile,
+ struct dwarf2_section_info *info)
+{
+ if (!info->readin)
+ dwarf2_read_section (objfile, info);
+ return info->size;
+}
+
/* Fill in SECTP, BUFP and SIZEP with section info, given OBJFILE and
- SECTION_NAME. */
+ SECTION_NAME. */
void
-dwarf2_get_section_info (struct objfile *objfile, const char *section_name,
+dwarf2_get_section_info (struct objfile *objfile,
+ enum dwarf2_section_enum sect,
asection **sectp, gdb_byte **bufp,
bfd_size_type *sizep)
{
*sizep = 0;
return;
}
- if (section_is_p (section_name, EH_FRAME_SECTION))
- info = &data->eh_frame;
- else if (section_is_p (section_name, FRAME_SECTION))
- info = &data->frame;
- else
- gdb_assert_not_reached ("unexpected section");
+ switch (sect)
+ {
+ case DWARF2_DEBUG_FRAME:
+ info = &data->frame;
+ break;
+ case DWARF2_EH_FRAME:
+ info = &data->eh_frame;
+ break;
+ default:
+ gdb_assert_not_reached ("unexpected section");
+ }
- if (info->asection != NULL && info->size != 0 && info->buffer == NULL)
- /* We haven't read this section in yet. Do it now. */
- dwarf2_read_section (objfile, info);
+ dwarf2_read_section (objfile, info);
*sectp = info->asection;
*bufp = info->buffer;
}
\f
+/* DWARF quick_symbols_functions support. */
+
+/* TUs can share .debug_line entries, and there can be a lot more TUs than
+ unique line tables, so we maintain a separate table of all .debug_line
+ derived entries to support the sharing.
+ All the quick functions need is the list of file names. We discard the
+ line_header when we're done and don't need to record it here. */
+struct quick_file_names
+{
+ /* The offset in .debug_line of the line table. We hash on this. */
+ unsigned int offset;
+
+ /* The number of entries in file_names, real_names. */
+ unsigned int num_file_names;
+
+ /* The file names from the line table, after being run through
+ file_full_name. */
+ const char **file_names;
+
+ /* The file names from the line table after being run through
+ gdb_realpath. These are computed lazily. */
+ const char **real_names;
+};
+
+/* When using the index (and thus not using psymtabs), each CU has an
+ object of this type. This is used to hold information needed by
+ the various "quick" methods. */
+struct dwarf2_per_cu_quick_data
+{
+ /* The file table. This can be NULL if there was no file table
+ or it's currently not read in.
+ NOTE: This points into dwarf2_per_objfile->quick_file_names_table. */
+ struct quick_file_names *file_names;
+
+ /* The corresponding symbol table. This is NULL if symbols for this
+ CU have not yet been read. */
+ struct symtab *symtab;
+
+ /* A temporary mark bit used when iterating over all CUs in
+ expand_symtabs_matching. */
+ unsigned int mark : 1;
+
+ /* True if we've tried to read the file table and found there isn't one.
+ There will be no point in trying to read it again next time. */
+ unsigned int no_file_data : 1;
+};
+
+/* Hash function for a quick_file_names. */
+
+static hashval_t
+hash_file_name_entry (const void *e)
+{
+ const struct quick_file_names *file_data = e;
+
+ return file_data->offset;
+}
+
+/* Equality function for a quick_file_names. */
+
+static int
+eq_file_name_entry (const void *a, const void *b)
+{
+ const struct quick_file_names *ea = a;
+ const struct quick_file_names *eb = b;
+
+ return ea->offset == eb->offset;
+}
+
+/* Delete function for a quick_file_names. */
+
+static void
+delete_file_name_entry (void *e)
+{
+ struct quick_file_names *file_data = e;
+ int i;
+
+ for (i = 0; i < file_data->num_file_names; ++i)
+ {
+ xfree ((void*) file_data->file_names[i]);
+ if (file_data->real_names)
+ xfree ((void*) file_data->real_names[i]);
+ }
+
+ /* The space for the struct itself lives on objfile_obstack,
+ so we don't free it here. */
+}
+
+/* Create a quick_file_names hash table. */
+
+static htab_t
+create_quick_file_names_table (unsigned int nr_initial_entries)
+{
+ return htab_create_alloc (nr_initial_entries,
+ hash_file_name_entry, eq_file_name_entry,
+ delete_file_name_entry, xcalloc, xfree);
+}
/* Read in the symbols for PER_CU. OBJFILE is the objfile from which
this CU came. */
type_sig = OBSTACK_ZALLOC (&objfile->objfile_obstack,
struct signatured_type);
type_sig->signature = signature;
- type_sig->offset = offset;
type_sig->type_offset = type_offset;
type_sig->per_cu.from_debug_types = 1;
type_sig->per_cu.offset = offset;
do_cleanups (cleanup);
}
-/* The hash function for strings in the mapped index. This is the
- same as the hashtab.c hash function, but we keep a separate copy to
- maintain control over the implementation. This is necessary
- because the hash function is tied to the format of the mapped index
- file. */
+/* The hash function for strings in the mapped index. This is the same as
+ SYMBOL_HASH_NEXT, but we keep a separate copy to maintain control over the
+ implementation. This is necessary because the hash function is tied to the
+ format of the mapped index file. The hash values do not have to match with
+ SYMBOL_HASH_NEXT.
+
+ Use INT_MAX for INDEX_VERSION if you generate the current index format. */
static hashval_t
-mapped_index_string_hash (const void *p)
+mapped_index_string_hash (int index_version, const void *p)
{
const unsigned char *str = (const unsigned char *) p;
hashval_t r = 0;
unsigned char c;
while ((c = *str++) != 0)
- r = r * 67 + c - 113;
+ {
+ if (index_version >= 5)
+ c = tolower (c);
+ r = r * 67 + c - 113;
+ }
return r;
}
find_slot_in_mapped_hash (struct mapped_index *index, const char *name,
offset_type **vec_out)
{
- offset_type hash = mapped_index_string_hash (name);
+ struct cleanup *back_to = make_cleanup (null_cleanup, 0);
+ offset_type hash;
offset_type slot, step;
+ int (*cmp) (const char *, const char *);
+
+ if (current_language->la_language == language_cplus
+ || current_language->la_language == language_java
+ || current_language->la_language == language_fortran)
+ {
+ /* NAME is already canonical. Drop any qualifiers as .gdb_index does
+ not contain any. */
+ const char *paren = strchr (name, '(');
+
+ if (paren)
+ {
+ char *dup;
+
+ dup = xmalloc (paren - name + 1);
+ memcpy (dup, name, paren - name);
+ dup[paren - name] = 0;
+
+ make_cleanup (xfree, dup);
+ name = dup;
+ }
+ }
+
+ /* Index version 4 did not support case insensitive searches. But the
+ indexes for case insensitive languages are built in lowercase, therefore
+ simulate our NAME being searched is also lowercased. */
+ hash = mapped_index_string_hash ((index->version == 4
+ && case_sensitivity == case_sensitive_off
+ ? 5 : index->version),
+ name);
slot = hash & (index->symbol_table_slots - 1);
step = ((hash * 17) & (index->symbol_table_slots - 1)) | 1;
+ cmp = (case_sensitivity == case_sensitive_on ? strcmp : strcasecmp);
for (;;)
{
offset_type i = 2 * slot;
const char *str;
if (index->symbol_table[i] == 0 && index->symbol_table[i + 1] == 0)
- return 0;
+ {
+ do_cleanups (back_to);
+ return 0;
+ }
str = index->constant_pool + MAYBE_SWAP (index->symbol_table[i]);
- if (!strcmp (name, str))
+ if (!cmp (name, str))
{
*vec_out = (offset_type *) (index->constant_pool
+ MAYBE_SWAP (index->symbol_table[i + 1]));
+ do_cleanups (back_to);
return 1;
}
offset_type types_list_elements = 0;
int i;
- if (dwarf2_per_objfile->gdb_index.asection == NULL
- || dwarf2_per_objfile->gdb_index.size == 0)
+ if (dwarf2_section_empty_p (&dwarf2_per_objfile->gdb_index))
return 0;
/* Older elfutils strip versions could keep the section in the main
/* Version check. */
version = MAYBE_SWAP (*(offset_type *) addr);
/* Versions earlier than 3 emitted every copy of a psymbol. This
- causes the index to behave very poorly for certain requests. So,
- it seems better to just ignore such indices. */
- if (version < 3)
+ causes the index to behave very poorly for certain requests. Version 3
+ contained incomplete addrmap. So, it seems better to just ignore such
+ indices. Index version 4 uses a different hash function than index
+ version 5 and later. */
+ if (version < 4)
return 0;
/* Indexes with higher version than the one supported by GDB may be no
longer backward compatible. */
- if (version > 3)
+ if (version > 5)
return 0;
map = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct mapped_index);
+ map->version = version;
map->total_size = dwarf2_per_objfile->gdb_index.size;
metadata = (offset_type *) (addr + sizeof (offset_type));
dwarf2_per_objfile->index_table = map;
dwarf2_per_objfile->using_index = 1;
+ dwarf2_per_objfile->quick_file_names_table =
+ create_quick_file_names_table (dwarf2_per_objfile->n_comp_units);
return 1;
}
/* A helper for the "quick" functions which attempts to read the line
table for THIS_CU. */
-static void
-dw2_require_line_header (struct objfile *objfile,
- struct dwarf2_per_cu_data *this_cu)
+static struct quick_file_names *
+dw2_get_file_names (struct objfile *objfile,
+ struct dwarf2_per_cu_data *this_cu)
{
bfd *abfd = objfile->obfd;
- struct line_header *lh = NULL;
+ struct line_header *lh;
struct attribute *attr;
struct cleanup *cleanups;
struct die_info *comp_unit_die;
unsigned int bytes_read, buffer_size;
struct die_reader_specs reader_specs;
char *name, *comp_dir;
+ void **slot;
+ struct quick_file_names *qfn;
+ unsigned int line_offset;
- if (this_cu->v.quick->read_lines)
- return;
- this_cu->v.quick->read_lines = 1;
+ if (this_cu->v.quick->file_names != NULL)
+ return this_cu->v.quick->file_names;
+ /* If we know there is no line data, no point in looking again. */
+ if (this_cu->v.quick->no_file_data)
+ return NULL;
init_one_comp_unit (&cu, objfile);
cleanups = make_cleanup (free_stack_comp_unit, &cu);
if (this_cu->from_debug_types)
info_ptr += 8 /*signature*/ + cu.header.offset_size;
init_cu_die_reader (&reader_specs, &cu);
- info_ptr = read_full_die (&reader_specs, &comp_unit_die, info_ptr,
- &has_children);
+ read_full_die (&reader_specs, &comp_unit_die, info_ptr,
+ &has_children);
+ lh = NULL;
+ slot = NULL;
+ line_offset = 0;
attr = dwarf2_attr (comp_unit_die, DW_AT_stmt_list, &cu);
if (attr)
{
- unsigned int line_offset = DW_UNSND (attr);
+ struct quick_file_names find_entry;
+
+ line_offset = DW_UNSND (attr);
+
+ /* We may have already read in this line header (TU line header sharing).
+ If we have we're done. */
+ find_entry.offset = line_offset;
+ slot = htab_find_slot (dwarf2_per_objfile->quick_file_names_table,
+ &find_entry, INSERT);
+ if (*slot != NULL)
+ {
+ do_cleanups (cleanups);
+ this_cu->v.quick->file_names = *slot;
+ return *slot;
+ }
+
lh = dwarf_decode_line_header (line_offset, abfd, &cu);
}
if (lh == NULL)
{
do_cleanups (cleanups);
- return;
+ this_cu->v.quick->no_file_data = 1;
+ return NULL;
}
- find_file_and_directory (comp_unit_die, &cu, &name, &comp_dir);
+ qfn = obstack_alloc (&objfile->objfile_obstack, sizeof (*qfn));
+ qfn->offset = line_offset;
+ gdb_assert (slot != NULL);
+ *slot = qfn;
- this_cu->v.quick->lines = lh;
+ find_file_and_directory (comp_unit_die, &cu, &name, &comp_dir);
- this_cu->v.quick->file_names
- = obstack_alloc (&objfile->objfile_obstack,
- lh->num_file_names * sizeof (char *));
+ qfn->num_file_names = lh->num_file_names;
+ qfn->file_names = obstack_alloc (&objfile->objfile_obstack,
+ lh->num_file_names * sizeof (char *));
for (i = 0; i < lh->num_file_names; ++i)
- this_cu->v.quick->file_names[i] = file_full_name (i + 1, lh, comp_dir);
+ qfn->file_names[i] = file_full_name (i + 1, lh, comp_dir);
+ qfn->real_names = NULL;
+ free_line_header (lh);
do_cleanups (cleanups);
+
+ this_cu->v.quick->file_names = qfn;
+ return qfn;
}
/* A helper for the "quick" functions which computes and caches the
- real path for a given file name from the line table.
- dw2_require_line_header must have been called before this is
- invoked. */
+ real path for a given file name from the line table. */
static const char *
-dw2_require_full_path (struct objfile *objfile,
- struct dwarf2_per_cu_data *per_cu,
- int index)
+dw2_get_real_path (struct objfile *objfile,
+ struct quick_file_names *qfn, int index)
{
- if (!per_cu->v.quick->full_names)
- per_cu->v.quick->full_names
- = OBSTACK_CALLOC (&objfile->objfile_obstack,
- per_cu->v.quick->lines->num_file_names,
- sizeof (char *));
+ if (qfn->real_names == NULL)
+ qfn->real_names = OBSTACK_CALLOC (&objfile->objfile_obstack,
+ qfn->num_file_names, sizeof (char *));
- if (!per_cu->v.quick->full_names[index])
- per_cu->v.quick->full_names[index]
- = gdb_realpath (per_cu->v.quick->file_names[index]);
+ if (qfn->real_names[index] == NULL)
+ qfn->real_names[index] = gdb_realpath (qfn->file_names[index]);
- return per_cu->v.quick->full_names[index];
+ return qfn->real_names[index];
}
static struct symtab *
return dw2_instantiate_symtab (objfile, dw2_get_cu (index));
}
-static void
-dw2_forget_cached_source_info (struct objfile *objfile)
+/* Traversal function for dw2_forget_cached_source_info. */
+
+static int
+dw2_free_cached_file_names (void **slot, void *info)
{
- int i;
+ struct quick_file_names *file_data = (struct quick_file_names *) *slot;
- dw2_setup (objfile);
- for (i = 0; i < (dwarf2_per_objfile->n_comp_units
- + dwarf2_per_objfile->n_type_comp_units); ++i)
+ if (file_data->real_names)
{
- struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
+ int i;
- if (per_cu->v.quick->full_names)
+ for (i = 0; i < file_data->num_file_names; ++i)
{
- int j;
-
- for (j = 0; j < per_cu->v.quick->lines->num_file_names; ++j)
- {
- xfree ((void *) per_cu->v.quick->full_names[j]);
- per_cu->v.quick->full_names[j] = NULL;
- }
+ xfree ((void*) file_data->real_names[i]);
+ file_data->real_names[i] = NULL;
}
}
+
+ return 1;
+}
+
+static void
+dw2_forget_cached_source_info (struct objfile *objfile)
+{
+ dw2_setup (objfile);
+
+ htab_traverse_noresize (dwarf2_per_objfile->quick_file_names_table,
+ dw2_free_cached_file_names, NULL);
}
static int
{
int j;
struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
+ struct quick_file_names *file_data;
if (per_cu->v.quick->symtab)
continue;
- dw2_require_line_header (objfile, per_cu);
- if (!per_cu->v.quick->lines)
+ file_data = dw2_get_file_names (objfile, per_cu);
+ if (file_data == NULL)
continue;
- for (j = 0; j < per_cu->v.quick->lines->num_file_names; ++j)
+ for (j = 0; j < file_data->num_file_names; ++j)
{
- const char *this_name = per_cu->v.quick->file_names[j];
+ const char *this_name = file_data->file_names[j];
if (FILENAME_CMP (name, this_name) == 0)
{
if (full_path != NULL)
{
- const char *this_full_name = dw2_require_full_path (objfile,
- per_cu, j);
+ const char *this_real_name = dw2_get_real_path (objfile,
+ file_data, j);
- if (this_full_name
- && FILENAME_CMP (full_path, this_full_name) == 0)
+ if (this_real_name != NULL
+ && FILENAME_CMP (full_path, this_real_name) == 0)
{
*result = dw2_instantiate_symtab (objfile, per_cu);
return 1;
if (real_path != NULL)
{
- const char *this_full_name = dw2_require_full_path (objfile,
- per_cu, j);
+ const char *this_real_name = dw2_get_real_path (objfile,
+ file_data, j);
- if (this_full_name != NULL
- && FILENAME_CMP (real_path, this_full_name) == 0)
+ if (this_real_name != NULL
+ && FILENAME_CMP (real_path, this_real_name) == 0)
{
*result = dw2_instantiate_symtab (objfile, per_cu);
return 1;
static void
dw2_pre_expand_symtabs_matching (struct objfile *objfile,
- int kind, const char *name,
+ enum block_enum block_kind, const char *name,
domain_enum domain)
{
dw2_do_expand_symtabs_matching (objfile, name);
{
int j;
struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
+ struct quick_file_names *file_data;
if (per_cu->v.quick->symtab)
continue;
- dw2_require_line_header (objfile, per_cu);
- if (!per_cu->v.quick->lines)
+ file_data = dw2_get_file_names (objfile, per_cu);
+ if (file_data == NULL)
continue;
- for (j = 0; j < per_cu->v.quick->lines->num_file_names; ++j)
+ for (j = 0; j < file_data->num_file_names; ++j)
{
- const char *this_name = per_cu->v.quick->file_names[j];
+ const char *this_name = file_data->file_names[j];
if (FILENAME_CMP (this_name, filename) == 0)
{
dw2_instantiate_symtab (objfile, per_cu);
{
struct dwarf2_per_cu_data *per_cu;
offset_type *vec;
+ struct quick_file_names *file_data;
dw2_setup (objfile);
/* vec[0] is the length, which must always be >0. */
per_cu = dw2_get_cu (MAYBE_SWAP (vec[1]));
- dw2_require_line_header (objfile, per_cu);
- if (!per_cu->v.quick->lines)
+ file_data = dw2_get_file_names (objfile, per_cu);
+ if (file_data == NULL)
return NULL;
- return per_cu->v.quick->file_names[per_cu->v.quick->lines->num_file_names - 1];
+ return file_data->file_names[file_data->num_file_names - 1];
}
static void
dw2_expand_symtabs_matching (struct objfile *objfile,
int (*file_matcher) (const char *, void *),
int (*name_matcher) (const char *, void *),
- domain_enum kind,
+ enum search_domain kind,
void *data)
{
int i;
return;
index = dwarf2_per_objfile->index_table;
- for (i = 0; i < (dwarf2_per_objfile->n_comp_units
- + dwarf2_per_objfile->n_type_comp_units); ++i)
- {
- int j;
- struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
+ if (file_matcher != NULL)
+ for (i = 0; i < (dwarf2_per_objfile->n_comp_units
+ + dwarf2_per_objfile->n_type_comp_units); ++i)
+ {
+ int j;
+ struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
+ struct quick_file_names *file_data;
- per_cu->v.quick->mark = 0;
- if (per_cu->v.quick->symtab)
- continue;
+ per_cu->v.quick->mark = 0;
+ if (per_cu->v.quick->symtab)
+ continue;
- dw2_require_line_header (objfile, per_cu);
- if (!per_cu->v.quick->lines)
- continue;
+ file_data = dw2_get_file_names (objfile, per_cu);
+ if (file_data == NULL)
+ continue;
- for (j = 0; j < per_cu->v.quick->lines->num_file_names; ++j)
- {
- if (file_matcher (per_cu->v.quick->file_names[j], data))
- {
- per_cu->v.quick->mark = 1;
- break;
- }
- }
- }
+ for (j = 0; j < file_data->num_file_names; ++j)
+ {
+ if (file_matcher (file_data->file_names[j], data))
+ {
+ per_cu->v.quick->mark = 1;
+ break;
+ }
+ }
+ }
for (iter = 0; iter < index->symbol_table_slots; ++iter)
{
struct dwarf2_per_cu_data *per_cu;
per_cu = dw2_get_cu (MAYBE_SWAP (vec[vec_idx + 1]));
- if (per_cu->v.quick->mark)
+ if (file_matcher == NULL || per_cu->v.quick->mark)
dw2_instantiate_symtab (objfile, per_cu);
}
}
}
static void
-dw2_map_symbol_names (struct objfile *objfile,
- void (*fun) (const char *, void *),
- void *data)
-{
- offset_type iter;
- struct mapped_index *index;
-
- dw2_setup (objfile);
-
- /* index_table is NULL if OBJF_READNOW. */
- if (!dwarf2_per_objfile->index_table)
- return;
- index = dwarf2_per_objfile->index_table;
-
- for (iter = 0; iter < index->symbol_table_slots; ++iter)
- {
- offset_type idx = 2 * iter;
- const char *name;
- offset_type *vec, vec_len, vec_idx;
-
- if (index->symbol_table[idx] == 0 && index->symbol_table[idx + 1] == 0)
- continue;
-
- name = (index->constant_pool + MAYBE_SWAP (index->symbol_table[idx]));
-
- (*fun) (name, data);
- }
-}
-
-static void
-dw2_map_symbol_filenames (struct objfile *objfile,
- void (*fun) (const char *, const char *, void *),
+dw2_map_symbol_filenames (struct objfile *objfile, symbol_filename_ftype *fun,
void *data)
{
int i;
{
int j;
struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
+ struct quick_file_names *file_data;
if (per_cu->v.quick->symtab)
continue;
- dw2_require_line_header (objfile, per_cu);
- if (!per_cu->v.quick->lines)
+ file_data = dw2_get_file_names (objfile, per_cu);
+ if (file_data == NULL)
continue;
- for (j = 0; j < per_cu->v.quick->lines->num_file_names; ++j)
+ for (j = 0; j < file_data->num_file_names; ++j)
{
- const char *this_full_name = dw2_require_full_path (objfile, per_cu,
- j);
- (*fun) (per_cu->v.quick->file_names[j], this_full_name, data);
+ const char *this_real_name = dw2_get_real_path (objfile, file_data,
+ j);
+ (*fun) (file_data->file_names[j], this_real_name, data);
}
}
}
dw2_map_matching_symbols,
dw2_expand_symtabs_matching,
dw2_find_pc_sect_symtab,
- dw2_map_symbol_names,
dw2_map_symbol_filenames
};
dwarf2_per_objfile->using_index = 1;
create_all_comp_units (objfile);
create_debug_types_hash_table (objfile);
+ dwarf2_per_objfile->quick_file_names_table =
+ create_quick_file_names_table (dwarf2_per_objfile->n_comp_units);
for (i = 0; i < (dwarf2_per_objfile->n_comp_units
+ dwarf2_per_objfile->n_type_comp_units); ++i)
if (dwarf2_read_index (objfile))
return 1;
- dwarf2_build_psymtabs (objfile);
return 0;
}
"(is %d, should be 2, 3, or 4) [in module %s]"), header->version,
bfd_get_filename (abfd));
- if (header->abbrev_offset >= dwarf2_per_objfile->abbrev.size)
+ if (header->abbrev_offset
+ >= dwarf2_section_size (dwarf2_per_objfile->objfile,
+ &dwarf2_per_objfile->abbrev))
error (_("Dwarf Error: bad offset (0x%lx) in compilation unit header "
"(offset 0x%lx + 6) [in module %s]"),
(long) header->abbrev_offset,
if (dwarf2_die_debug)
fprintf_unfiltered (gdb_stdlog, "Signatured types:\n");
- while (info_ptr < dwarf2_per_objfile->types.buffer + dwarf2_per_objfile->types.size)
+ while (info_ptr < dwarf2_per_objfile->types.buffer
+ + dwarf2_per_objfile->types.size)
{
unsigned int offset;
unsigned int offset_size;
> dwarf2_per_objfile->types.buffer + dwarf2_per_objfile->types.size)
{
complaint (&symfile_complaints,
- _("debug type entry runs off end of `.debug_types' section, ignored"));
+ _("debug type entry runs off end "
+ "of `.debug_types' section, ignored"));
break;
}
type_sig = obstack_alloc (&objfile->objfile_obstack, sizeof (*type_sig));
memset (type_sig, 0, sizeof (*type_sig));
type_sig->signature = signature;
- type_sig->offset = offset;
type_sig->type_offset = type_offset;
type_sig->per_cu.objfile = objfile;
type_sig->per_cu.from_debug_types = 1;
+ type_sig->per_cu.offset = offset;
slot = htab_find_slot (types_htab, type_sig, INSERT);
gdb_assert (slot != NULL);
+ if (*slot != NULL)
+ {
+ const struct signatured_type *dup_sig = *slot;
+
+ complaint (&symfile_complaints,
+ _("debug type entry at offset 0x%x is duplicate to the "
+ "entry at offset 0x%x, signature 0x%s"),
+ offset, dup_sig->per_cu.offset,
+ phex (signature, sizeof (signature)));
+ gdb_assert (signature == dup_sig->signature);
+ }
*slot = type_sig;
if (dwarf2_die_debug)
if (dwarf2_per_objfile->signatured_types == NULL)
{
complaint (&symfile_complaints,
- _("missing `.debug_types' section for DW_FORM_sig8 die"));
+ _("missing `.debug_types' section for DW_FORM_ref_sig8 die"));
return 0;
}
struct attribute *attr;
CORE_ADDR best_lowpc = 0, best_highpc = 0;
struct die_reader_specs reader_specs;
+ const char *filename;
init_one_comp_unit (&cu, objfile);
back_to_inner = make_cleanup (free_stack_comp_unit, &cu);
if (this_cu->from_debug_types)
{
- /* offset,length haven't been set yet for type units. */
- this_cu->offset = cu.header.offset;
+ /* LENGTH has not been set yet for type units. */
+ gdb_assert (this_cu->offset == cu.header.offset);
this_cu->length = cu.header.length + cu.header.initial_length_size;
}
else if (comp_unit_die->tag == DW_TAG_partial_unit)
/* Allocate a new partial symbol table structure. */
attr = dwarf2_attr (comp_unit_die, DW_AT_name, &cu);
+ if (attr == NULL || !DW_STRING (attr))
+ filename = "";
+ else
+ filename = DW_STRING (attr);
pst = start_psymtab_common (objfile, objfile->section_offsets,
- (attr != NULL) ? DW_STRING (attr) : "",
+ filename,
/* TEXTLOW and TEXTHIGH are set below. */
0,
objfile->global_psymbols.next,
baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
- /* Store the function that reads in the rest of the symbol table */
+ /* Store the function that reads in the rest of the symbol table. */
pst->read_symtab = dwarf2_psymtab_to_symtab;
this_cu->v.psymtab = pst;
/* Check if comp unit has_children.
If so, read the rest of the partial symbols from this comp unit.
- If not, there's no more debug_info for this comp unit. */
+ If not, there's no more debug_info for this comp unit. */
if (has_children)
{
struct partial_die_info *first_die;
gdb_assert (dwarf2_per_objfile->types.readin);
process_psymtab_comp_unit (objfile, this_cu,
dwarf2_per_objfile->types.buffer,
- dwarf2_per_objfile->types.buffer + entry->offset,
+ dwarf2_per_objfile->types.buffer + this_cu->offset,
dwarf2_per_objfile->types.size);
return 1;
{
struct dwarf2_per_cu_data *this_cu;
- this_cu = dwarf2_find_comp_unit (info_ptr - dwarf2_per_objfile->info.buffer,
+ this_cu = dwarf2_find_comp_unit (info_ptr
+ - dwarf2_per_objfile->info.buffer,
objfile);
info_ptr = process_psymtab_comp_unit (objfile, this_cu,
/* Check if comp unit has_children.
If so, read the rest of the partial symbols from this comp unit.
- If not, there's no more debug_info for this comp unit. */
+ If not, there's no more debug_info for this comp unit. */
if (has_children)
load_partial_dies (abfd, dwarf2_per_objfile->info.buffer, info_ptr, 0, cu);
all_comp_units = xmalloc (n_allocated
* sizeof (struct dwarf2_per_cu_data *));
- while (info_ptr < dwarf2_per_objfile->info.buffer + dwarf2_per_objfile->info.size)
+ while (info_ptr < dwarf2_per_objfile->info.buffer
+ + dwarf2_per_objfile->info.size)
{
unsigned int length, initial_length_size;
struct dwarf2_per_cu_data *this_cu;
if (grandparent_scope == NULL)
parent->scope = parent->name;
else
- parent->scope = typename_concat (&cu->comp_unit_obstack, grandparent_scope,
+ parent->scope = typename_concat (&cu->comp_unit_obstack,
+ grandparent_scope,
parent->name, 0, cu);
}
else if (parent->tag == DW_TAG_enumerator)
of the global scope. But in Ada, we want to be able to access
nested procedures globally. So all Ada subprograms are stored
in the global scope. */
- /*prim_record_minimal_symbol (actual_name, pdi->lowpc + baseaddr,
+ /* prim_record_minimal_symbol (actual_name, pdi->lowpc + baseaddr,
mst_text, objfile); */
- psym = add_psymbol_to_list (actual_name, strlen (actual_name),
- built_actual_name,
- VAR_DOMAIN, LOC_BLOCK,
- &objfile->global_psymbols,
- 0, pdi->lowpc + baseaddr,
- cu->language, objfile);
+ add_psymbol_to_list (actual_name, strlen (actual_name),
+ built_actual_name,
+ VAR_DOMAIN, LOC_BLOCK,
+ &objfile->global_psymbols,
+ 0, pdi->lowpc + baseaddr,
+ cu->language, objfile);
}
else
{
- /*prim_record_minimal_symbol (actual_name, pdi->lowpc + baseaddr,
+ /* prim_record_minimal_symbol (actual_name, pdi->lowpc + baseaddr,
mst_file_text, objfile); */
- psym = add_psymbol_to_list (actual_name, strlen (actual_name),
- built_actual_name,
- VAR_DOMAIN, LOC_BLOCK,
- &objfile->static_psymbols,
- 0, pdi->lowpc + baseaddr,
- cu->language, objfile);
+ add_psymbol_to_list (actual_name, strlen (actual_name),
+ built_actual_name,
+ VAR_DOMAIN, LOC_BLOCK,
+ &objfile->static_psymbols,
+ 0, pdi->lowpc + baseaddr,
+ cu->language, objfile);
}
break;
case DW_TAG_constant:
list = &objfile->global_psymbols;
else
list = &objfile->static_psymbols;
- psym = add_psymbol_to_list (actual_name, strlen (actual_name),
- built_actual_name, VAR_DOMAIN, LOC_STATIC,
- list, 0, 0, cu->language, objfile);
-
+ add_psymbol_to_list (actual_name, strlen (actual_name),
+ built_actual_name, VAR_DOMAIN, LOC_STATIC,
+ list, 0, 0, cu->language, objfile);
}
break;
case DW_TAG_variable:
table building. */
if (pdi->locdesc || pdi->has_type)
- psym = add_psymbol_to_list (actual_name, strlen (actual_name),
- built_actual_name,
- VAR_DOMAIN, LOC_STATIC,
- &objfile->global_psymbols,
- 0, addr + baseaddr,
- cu->language, objfile);
+ add_psymbol_to_list (actual_name, strlen (actual_name),
+ built_actual_name,
+ VAR_DOMAIN, LOC_STATIC,
+ &objfile->global_psymbols,
+ 0, addr + baseaddr,
+ cu->language, objfile);
}
else
{
- /* Static Variable. Skip symbols without location descriptors. */
+ /* Static Variable. Skip symbols without location descriptors. */
if (pdi->locdesc == NULL)
{
if (built_actual_name)
xfree (actual_name);
return;
}
- /*prim_record_minimal_symbol (actual_name, addr + baseaddr,
+ /* prim_record_minimal_symbol (actual_name, addr + baseaddr,
mst_file_data, objfile); */
- psym = add_psymbol_to_list (actual_name, strlen (actual_name),
- built_actual_name,
- VAR_DOMAIN, LOC_STATIC,
- &objfile->static_psymbols,
- 0, addr + baseaddr,
- cu->language, objfile);
+ add_psymbol_to_list (actual_name, strlen (actual_name),
+ built_actual_name,
+ VAR_DOMAIN, LOC_STATIC,
+ &objfile->static_psymbols,
+ 0, addr + baseaddr,
+ cu->language, objfile);
}
break;
case DW_TAG_typedef:
abbrev = dwarf2_lookup_abbrev (abbrev_number, cu);
if (!abbrev)
{
- error (_("Dwarf Error: Could not find abbrev number %d [in module %s]"), abbrev_number,
- bfd_get_filename (abfd));
+ error (_("Dwarf Error: Could not find abbrev number %d [in module %s]"),
+ abbrev_number, bfd_get_filename (abfd));
}
return abbrev;
read_attribute (&attr, &abbrev->attrs[i],
abfd, info_ptr, cu);
if (attr.form == DW_FORM_ref_addr)
- complaint (&symfile_complaints, _("ignoring absolute DW_AT_sibling"));
+ complaint (&symfile_complaints,
+ _("ignoring absolute DW_AT_sibling"));
else
return buffer + dwarf2_get_ref_die_offset (&attr);
}
break;
case DW_FORM_data8:
case DW_FORM_ref8:
- case DW_FORM_sig8:
+ case DW_FORM_ref_sig8:
info_ptr += 8;
break;
case DW_FORM_string:
goto skip_attribute;
default:
- error (_("Dwarf Error: Cannot handle %s in DWARF reader [in module %s]"),
+ error (_("Dwarf Error: Cannot handle %s "
+ "in DWARF reader [in module %s]"),
dwarf_form_name (form),
bfd_get_filename (abfd));
}
{
if (pst->readin)
{
- warning (_("bug: psymtab for %s is already read in."), pst->filename);
+ warning (_("bug: psymtab for %s is already read in."),
+ pst->filename);
}
else
{
if (info_verbose)
{
- printf_filtered (_("Reading in symbols for %s..."), pst->filename);
+ printf_filtered (_("Reading in symbols for %s..."),
+ pst->filename);
gdb_flush (gdb_stdout);
}
fputs_filtered ("and ", gdb_stdout);
wrap_here ("");
printf_filtered ("%s...", pst->dependencies[i]->filename);
- wrap_here (""); /* Flush output */
+ wrap_here (""); /* Flush output. */
gdb_flush (gdb_stdout);
}
psymtab_to_symtab_1 (pst->dependencies[i]);
/* Load the DIEs associated with PER_CU into memory. */
static void
-load_full_comp_unit (struct dwarf2_per_cu_data *per_cu, struct objfile *objfile)
+load_full_comp_unit (struct dwarf2_per_cu_data *per_cu,
+ struct objfile *objfile)
{
bfd *abfd = objfile->obfd;
struct dwarf2_cu *cu;
struct delayed_method_info *mi;
for (i = 0; VEC_iterate (delayed_method_info, cu->method_list, i, mi) ; ++i)
{
- char *physname;
+ const char *physname;
struct fn_fieldlist *fn_flp
= &TYPE_FN_FIELDLIST (mi->type, mi->fnfield_index);
- physname = (char *) dwarf2_physname ((char *) mi->name, mi->die, cu);
+ physname = dwarf2_physname ((char *) mi->name, mi->die, cu);
fn_flp->fn_fields[mi->index].physname = physname ? physname : "";
}
}
+/* Check for GCC >= 4.x. Return minor version (x) of 4.x in such case. If it
+ is not GCC or it is GCC older than 4.x return -1. If it is GCC 5.x or
+ higher return INT_MAX. */
+
+static int
+producer_is_gcc_ge_4 (struct dwarf2_cu *cu)
+{
+ const char *cs;
+ int major, minor;
+
+ if (cu->producer == NULL)
+ {
+ /* For unknown compilers expect their behavior is not compliant. For GCC
+ this case can also happen for -gdwarf-4 type units supported since
+ gcc-4.5. */
+
+ return -1;
+ }
+
+ /* Skip any identifier after "GNU " - such as "C++" or "Java". */
+
+ if (strncmp (cu->producer, "GNU ", strlen ("GNU ")) != 0)
+ {
+ /* For non-GCC compilers expect their behavior is not compliant. */
+
+ return -1;
+ }
+ cs = &cu->producer[strlen ("GNU ")];
+ while (*cs && !isdigit (*cs))
+ cs++;
+ if (sscanf (cs, "%d.%d", &major, &minor) != 2)
+ {
+ /* Not recognized as GCC. */
+
+ return -1;
+ }
+
+ if (major < 4)
+ return -1;
+ if (major > 4)
+ return INT_MAX;
+ return minor;
+}
+
/* Generate full symbol information for PST and CU, whose DIEs have
already been loaded into memory. */
symtab = end_symtab (highpc + baseaddr, objfile, SECT_OFF_TEXT (objfile));
- /* Set symtab language to language from DW_AT_language.
- If the compilation is from a C file generated by language preprocessors,
- do not set the language if it was already deduced by start_subfile. */
- if (symtab != NULL
- && !(cu->language == language_c && symtab->language != language_c))
+ if (symtab != NULL)
{
- symtab->language = cu->language;
+ int gcc_4_minor = producer_is_gcc_ge_4 (cu);
+
+ /* Set symtab language to language from DW_AT_language. If the
+ compilation is from a C file generated by language preprocessors, do
+ not set the language if it was already deduced by start_subfile. */
+ if (!(cu->language == language_c && symtab->language != language_c))
+ symtab->language = cu->language;
+
+ /* GCC-4.0 has started to support -fvar-tracking. GCC-3.x still can
+ produce DW_AT_location with location lists but it can be possibly
+ invalid without -fvar-tracking.
+
+ For -gdwarf-4 type units LOCATIONS_VALID indication is fortunately not
+ needed, it would be wrong due to missing DW_AT_producer there.
+
+ Still one can confuse GDB by using non-standard GCC compilation
+ options - this waits on GCC PR other/32998 (-frecord-gcc-switches).
+ */
+ if (cu->has_loclist && gcc_4_minor >= 0)
+ symtab->locations_valid = 1;
+
+ if (gcc_4_minor >= 5)
+ symtab->epilogue_unwind_valid = 1;
}
if (dwarf2_per_objfile->using_index)
xfree (prefixed_name);
}
else
- fputs_unfiltered (name ? name : "", buf);
+ fputs_unfiltered (name, buf);
/* Template parameters may be specified in the DIE's DW_AT_name, or
as children with DW_TAG_template_type_param or
if (attr == NULL)
{
complaint (&symfile_complaints,
- _("template parameter missing DW_AT_const_value"));
+ _("template parameter missing "
+ "DW_AT_const_value"));
fputs_unfiltered ("UNKNOWN_VALUE", buf);
continue;
}
else
v = value_from_longest (type, value);
- /* Specify decimal so that we do not depend on the radix. */
+ /* Specify decimal so that we do not depend on
+ the radix. */
get_formatted_print_options (&opts, 'd');
opts.raw = 1;
value_print (v, buf, &opts);
{
struct type *type = read_type_die (die, cu);
- c_type_print_args (type, buf, 0, cu->language);
+ c_type_print_args (type, buf, 1, cu->language);
if (cu->language == language_java)
{
/* For java, we must append the return type to method
- names. */
+ names. */
if (die->tag == DW_TAG_subprogram)
java_print_type (TYPE_TARGET_TYPE (type), "", buf,
0, 0);
if (TYPE_NFIELDS (type) > 0
&& TYPE_FIELD_ARTIFICIAL (type, 0)
&& TYPE_CODE (TYPE_FIELD_TYPE (type, 0)) == TYPE_CODE_PTR
- && TYPE_CONST (TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (type, 0))))
+ && TYPE_CONST (TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (type,
+ 0))))
fputs_unfiltered (" const", buf);
}
}
not have a name. NAME may either be from a previous call to
dwarf2_name or NULL.
- The output string will be canonicalized (if C++/Java). */
+ The output string will be canonicalized (if C++/Java). */
static const char *
dwarf2_full_name (char *name, struct die_info *die, struct dwarf2_cu *cu)
read_import_statement (struct die_info *die, struct dwarf2_cu *cu)
{
struct attribute *import_attr;
- struct die_info *imported_die;
+ struct die_info *imported_die, *child_die;
struct dwarf2_cu *imported_cu;
const char *imported_name;
const char *imported_name_prefix;
const char *import_alias;
const char *imported_declaration = NULL;
const char *import_prefix;
+ VEC (const_char_ptr) *excludes = NULL;
+ struct cleanup *cleanups;
char *temp;
else
canonical_name = imported_name;
+ cleanups = make_cleanup (VEC_cleanup (const_char_ptr), &excludes);
+
+ if (die->tag == DW_TAG_imported_module && cu->language == language_fortran)
+ for (child_die = die->child; child_die && child_die->tag;
+ child_die = sibling_die (child_die))
+ {
+ /* DWARF-4: A Fortran use statement with a “rename list” may be
+ represented by an imported module entry with an import attribute
+ referring to the module and owned entries corresponding to those
+ entities that are renamed as part of being imported. */
+
+ if (child_die->tag != DW_TAG_imported_declaration)
+ {
+ complaint (&symfile_complaints,
+ _("child DW_TAG_imported_declaration expected "
+ "- DIE at 0x%x [in module %s]"),
+ child_die->offset, cu->objfile->name);
+ continue;
+ }
+
+ import_attr = dwarf2_attr (child_die, DW_AT_import, cu);
+ if (import_attr == NULL)
+ {
+ complaint (&symfile_complaints, _("Tag '%s' has no DW_AT_import"),
+ dwarf_tag_name (child_die->tag));
+ continue;
+ }
+
+ imported_cu = cu;
+ imported_die = follow_die_ref_or_sig (child_die, import_attr,
+ &imported_cu);
+ imported_name = dwarf2_name (imported_die, imported_cu);
+ if (imported_name == NULL)
+ {
+ complaint (&symfile_complaints,
+ _("child DW_TAG_imported_declaration has unknown "
+ "imported name - DIE at 0x%x [in module %s]"),
+ child_die->offset, cu->objfile->name);
+ continue;
+ }
+
+ VEC_safe_push (const_char_ptr, excludes, imported_name);
+
+ process_die (child_die, cu);
+ }
+
cp_add_using_directive (import_prefix,
canonical_name,
import_alias,
imported_declaration,
+ excludes,
&cu->objfile->objfile_obstack);
+
+ do_cleanups (cleanups);
}
static void
if (cu->producer && strstr (cu->producer, "IBM XL C for OpenCL") != NULL)
cu->language = language_opencl;
- /* We assume that we're processing GCC output. */
+ /* We assume that we're processing GCC output. */
processing_gcc_compilation = 2;
processing_has_namespace_info = 0;
if (attr)
cu->producer = DW_STRING (attr);
- /* We assume that we're processing GCC output. */
+ /* We assume that we're processing GCC output. */
processing_gcc_compilation = 2;
processing_has_namespace_info = 0;
}
/* DW_AT_abstract_origin inherits whole DIEs (not just their attributes).
- Inherit only the children of the DW_AT_abstract_origin DIE not being already
- referenced by DW_AT_abstract_origin from the children of the current DIE. */
+ Inherit only the children of the DW_AT_abstract_origin DIE not being
+ already referenced by DW_AT_abstract_origin from the children of the
+ current DIE. */
static void
inherit_abstract_dies (struct die_info *die, struct dwarf2_cu *cu)
unsigned_int_compar);
for (offsetp = offsets + 1; offsetp < offsets_end; offsetp++)
if (offsetp[-1] == *offsetp)
- complaint (&symfile_complaints, _("Multiple children of DIE 0x%x refer "
- "to DIE 0x%x as their abstract origin"),
+ complaint (&symfile_complaints,
+ _("Multiple children of DIE 0x%x refer "
+ "to DIE 0x%x as their abstract origin"),
die->offset, *offsetp);
offsetp = offsets;
attr = dwarf2_attr (die, DW_AT_external, cu);
if (!attr || !DW_UNSND (attr))
complaint (&symfile_complaints,
- _("cannot get low and high bounds for subprogram DIE at %d"),
+ _("cannot get low and high bounds "
+ "for subprogram DIE at %d"),
die->offset);
return;
}
return 0;
}
+ if (range_beginning > range_end)
+ {
+ /* Inverted range entries are invalid. */
+ complaint (&symfile_complaints,
+ _("Invalid .debug_ranges data (inverted range)"));
+ return 0;
+ }
+
+ /* Empty range entries have no effect. */
+ if (range_beginning == range_end)
+ continue;
+
range_beginning += base;
range_end += base;
- if (ranges_pst != NULL && range_beginning < range_end)
+ if (ranges_pst != NULL)
addrmap_set_empty (objfile->psymtabs_addrmap,
- range_beginning + baseaddr, range_end - 1 + baseaddr,
+ range_beginning + baseaddr,
+ range_end - 1 + baseaddr,
ranges_pst);
/* FIXME: This is recording everything as a low-high
}
}
- if (high < low)
+ /* read_partial_die has also the strict LOW < HIGH requirement. */
+ if (high <= low)
return 0;
/* When using the GNU linker, .gnu.linkonce. sections are used to
}
break;
default:
- /* Ignore. */
+ /* Ignore. */
break;
}
if (!base_known)
{
complaint (&symfile_complaints,
- _("Invalid .debug_ranges data (no base address)"));
+ _("Invalid .debug_ranges data "
+ "(no base address)"));
return;
}
+ if (start > end)
+ {
+ /* Inverted range entries are invalid. */
+ complaint (&symfile_complaints,
+ _("Invalid .debug_ranges data "
+ "(inverted range)"));
+ return;
+ }
+
+ /* Empty range entries have no effect. */
+ if (start == end)
+ continue;
+
record_block_range (block,
baseaddr + base + start,
baseaddr + base + end - 1);
}
}
+/* Check for GCC PR debug/45124 fix which is not present in any G++ version up
+ to 4.5.any while it is present already in G++ 4.6.0 - the PR has been fixed
+ during 4.6.0 experimental. */
+
+static int
+producer_is_gxx_lt_4_6 (struct dwarf2_cu *cu)
+{
+ const char *cs;
+ int major, minor, release;
+
+ if (cu->producer == NULL)
+ {
+ /* For unknown compilers expect their behavior is DWARF version
+ compliant.
+
+ GCC started to support .debug_types sections by -gdwarf-4 since
+ gcc-4.5.x. As the .debug_types sections are missing DW_AT_producer
+ for their space efficiency GDB cannot workaround gcc-4.5.x -gdwarf-4
+ combination. gcc-4.5.x -gdwarf-4 binaries have DW_AT_accessibility
+ interpreted incorrectly by GDB now - GCC PR debug/48229. */
+
+ return 0;
+ }
+
+ /* Skip any identifier after "GNU " - such as "C++" or "Java". */
+
+ if (strncmp (cu->producer, "GNU ", strlen ("GNU ")) != 0)
+ {
+ /* For non-GCC compilers expect their behavior is DWARF version
+ compliant. */
+
+ return 0;
+ }
+ cs = &cu->producer[strlen ("GNU ")];
+ while (*cs && !isdigit (*cs))
+ cs++;
+ if (sscanf (cs, "%d.%d.%d", &major, &minor, &release) != 3)
+ {
+ /* Not recognized as GCC. */
+
+ return 0;
+ }
+
+ return major < 4 || (major == 4 && minor < 6);
+}
+
+/* Return the default accessibility type if it is not overriden by
+ DW_AT_accessibility. */
+
+static enum dwarf_access_attribute
+dwarf2_default_access_attribute (struct die_info *die, struct dwarf2_cu *cu)
+{
+ if (cu->header.version < 3 || producer_is_gxx_lt_4_6 (cu))
+ {
+ /* The default DWARF 2 accessibility for members is public, the default
+ accessibility for inheritance is private. */
+
+ if (die->tag != DW_TAG_inheritance)
+ return DW_ACCESS_public;
+ else
+ return DW_ACCESS_private;
+ }
+ else
+ {
+ /* DWARF 3+ defines the default accessibility a different way. The same
+ rules apply now for DW_TAG_inheritance as for the members and it only
+ depends on the container kind. */
+
+ if (die->parent->tag == DW_TAG_class_type)
+ return DW_ACCESS_private;
+ else
+ return DW_ACCESS_public;
+ }
+}
+
+/* Look for DW_AT_data_member_location. Set *OFFSET to the byte
+ offset. If the attribute was not found return 0, otherwise return
+ 1. If it was found but could not properly be handled, set *OFFSET
+ to 0. */
+
+static int
+handle_data_member_location (struct die_info *die, struct dwarf2_cu *cu,
+ LONGEST *offset)
+{
+ struct attribute *attr;
+
+ attr = dwarf2_attr (die, DW_AT_data_member_location, cu);
+ if (attr != NULL)
+ {
+ *offset = 0;
+
+ /* Note that we do not check for a section offset first here.
+ This is because DW_AT_data_member_location is new in DWARF 4,
+ so if we see it, we can assume that a constant form is really
+ a constant and not a section offset. */
+ if (attr_form_is_constant (attr))
+ *offset = dwarf2_get_attr_constant_value (attr, 0);
+ else if (attr_form_is_section_offset (attr))
+ dwarf2_complex_location_expr_complaint ();
+ else if (attr_form_is_block (attr))
+ *offset = decode_locdesc (DW_BLOCK (attr), cu);
+ else
+ dwarf2_complex_location_expr_complaint ();
+
+ return 1;
+ }
+
+ return 0;
+}
+
/* Add an aggregate field to the field list. */
static void
}
fip->nfields++;
- /* Handle accessibility and virtuality of field.
- The default accessibility for members is public, the default
- accessibility for inheritance is private. */
- if (die->tag != DW_TAG_inheritance)
- new_field->accessibility = DW_ACCESS_public;
- else
- new_field->accessibility = DW_ACCESS_private;
- new_field->virtuality = DW_VIRTUALITY_none;
-
attr = dwarf2_attr (die, DW_AT_accessibility, cu);
if (attr)
new_field->accessibility = DW_UNSND (attr);
+ else
+ new_field->accessibility = dwarf2_default_access_attribute (die, cu);
if (new_field->accessibility != DW_ACCESS_public)
fip->non_public_fields = 1;
+
attr = dwarf2_attr (die, DW_AT_virtuality, cu);
if (attr)
new_field->virtuality = DW_UNSND (attr);
+ else
+ new_field->virtuality = DW_VIRTUALITY_none;
fp = &new_field->field;
if (die->tag == DW_TAG_member && ! die_is_declaration (die, cu))
{
+ LONGEST offset;
+
/* Data member other than a C++ static data member. */
/* Get type of field. */
}
/* Get bit offset of field. */
- attr = dwarf2_attr (die, DW_AT_data_member_location, cu);
- if (attr)
- {
- int byte_offset = 0;
-
- if (attr_form_is_section_offset (attr))
- dwarf2_complex_location_expr_complaint ();
- else if (attr_form_is_constant (attr))
- byte_offset = dwarf2_get_attr_constant_value (attr, 0);
- else if (attr_form_is_block (attr))
- byte_offset = decode_locdesc (DW_BLOCK (attr), cu);
- else
- dwarf2_complex_location_expr_complaint ();
-
- SET_FIELD_BITPOS (*fp, byte_offset * bits_per_byte);
- }
+ if (handle_data_member_location (die, cu, &offset))
+ SET_FIELD_BITPOS (*fp, offset * bits_per_byte);
attr = dwarf2_attr (die, DW_AT_bit_offset, cu);
if (attr)
{
(so through at least 3.2.1) incorrectly generate
DW_TAG_variable tags. */
- char *physname;
+ const char *physname;
/* Get name of field. */
fieldname = dwarf2_name (die, cu);
}
/* Get physical name. */
- physname = (char *) dwarf2_physname (fieldname, die, cu);
+ physname = dwarf2_physname (fieldname, die, cu);
/* The name is already allocated along with this objfile, so we don't
need to duplicate it for the type. */
}
else if (die->tag == DW_TAG_inheritance)
{
- /* C++ base class field. */
- attr = dwarf2_attr (die, DW_AT_data_member_location, cu);
- if (attr)
- {
- int byte_offset = 0;
+ LONGEST offset;
- if (attr_form_is_section_offset (attr))
- dwarf2_complex_location_expr_complaint ();
- else if (attr_form_is_constant (attr))
- byte_offset = dwarf2_get_attr_constant_value (attr, 0);
- else if (attr_form_is_block (attr))
- byte_offset = decode_locdesc (DW_BLOCK (attr), cu);
- else
- dwarf2_complex_location_expr_complaint ();
-
- SET_FIELD_BITPOS (*fp, byte_offset * bits_per_byte);
- }
+ /* C++ base class field. */
+ if (handle_data_member_location (die, cu, &offset))
+ SET_FIELD_BITPOS (*fp, offset * bits_per_byte);
FIELD_BITSIZE (*fp) = 0;
FIELD_TYPE (*fp) = die_type (die, cu);
FIELD_NAME (*fp) = type_name_no_tag (fp->type);
struct dwarf2_cu *cu)
{
struct objfile *objfile = cu->objfile;
- struct gdbarch *gdbarch = get_objfile_arch (objfile);
struct typedef_field_list *new_field;
struct attribute *attr;
struct typedef_field *fp;
TYPE_N_BASECLASSES (type) = fip->nbaseclasses;
}
- /* Copy the saved-up fields into the field vector. Start from the head
- of the list, adding to the tail of the field array, so that they end
- up in the same order in the array in which they were added to the list. */
+ /* Copy the saved-up fields into the field vector. Start from the head of
+ the list, adding to the tail of the field array, so that they end up in
+ the same order in the array in which they were added to the list. */
while (nfields-- > 0)
{
struct nextfield *fieldp;
case DW_VIRTUALITY_virtual:
case DW_VIRTUALITY_pure_virtual:
if (cu->language == language_ada)
- error ("unexpected virtuality in component of Ada type");
+ error (_("unexpected virtuality in component of Ada type"));
SET_TYPE_FIELD_VIRTUAL (type, nfields);
break;
}
char *fieldname;
struct nextfnfield *new_fnfield;
struct type *this_type;
+ enum dwarf_access_attribute accessibility;
if (cu->language == language_ada)
- error ("unexpected member function in Ada type");
+ error (_("unexpected member function in Ada type"));
/* Get name of member function. */
fieldname = dwarf2_name (die, cu);
}
/* Create a new member function field and chain it to the field list
- entry. */
+ entry. */
new_fnfield = (struct nextfnfield *) xmalloc (sizeof (struct nextfnfield));
make_cleanup (xfree, new_fnfield);
memset (new_fnfield, 0, sizeof (struct nextfnfield));
}
else
{
- char *physname = (char *) dwarf2_physname (fieldname, die, cu);
+ const char *physname = dwarf2_physname (fieldname, die, cu);
fnp->physname = physname ? physname : "";
}
/* Handle static member functions.
Dwarf2 has no clean way to discern C++ static and non-static
- member functions. G++ helps GDB by marking the first
- parameter for non-static member functions (which is the
- this pointer) as artificial. We obtain this information
- from read_subroutine_type via TYPE_FIELD_ARTIFICIAL. */
+ member functions. G++ helps GDB by marking the first
+ parameter for non-static member functions (which is the this
+ pointer) as artificial. We obtain this information from
+ read_subroutine_type via TYPE_FIELD_ARTIFICIAL. */
if (nparams == 0 || TYPE_FIELD_ARTIFICIAL (this_type, 0) == 0)
fnp->voffset = VOFFSET_STATIC;
}
if (dwarf2_attr (die, DW_AT_containing_type, cu) != NULL)
fnp->fcontext = die_containing_type (die, cu);
- /* dwarf2 doesn't have stubbed physical names, so the setting of is_const
- and is_volatile is irrelevant, as it is needed by gdb_mangle_name only. */
+ /* dwarf2 doesn't have stubbed physical names, so the setting of is_const and
+ is_volatile is irrelevant, as it is needed by gdb_mangle_name only. */
/* Get accessibility. */
attr = dwarf2_attr (die, DW_AT_accessibility, cu);
if (attr)
+ accessibility = DW_UNSND (attr);
+ else
+ accessibility = dwarf2_default_access_attribute (die, cu);
+ switch (accessibility)
{
- switch (DW_UNSND (attr))
- {
- case DW_ACCESS_private:
- fnp->is_private = 1;
- break;
- case DW_ACCESS_protected:
- fnp->is_protected = 1;
- break;
- }
+ case DW_ACCESS_private:
+ fnp->is_private = 1;
+ break;
+ case DW_ACCESS_protected:
+ fnp->is_protected = 1;
+ break;
}
/* Check for artificial methods. */
{
/* GCC does this, as of 2008-08-25; PR debug/37237. */
complaint (&symfile_complaints,
- _("Member function \"%s\" (offset %d) is virtual but the vtable offset is not specified"),
+ _("Member function \"%s\" (offset %d) is virtual "
+ "but the vtable offset is not specified"),
fieldname, die->offset);
ALLOCATE_CPLUS_STRUCT_TYPE (type);
TYPE_CPLUS_DYNAMIC (type) = 1;
int i;
if (cu->language == language_ada)
- error ("unexpected member functions in Ada type");
+ error (_("unexpected member functions in Ada type"));
ALLOCATE_CPLUS_STRUCT_TYPE (type);
TYPE_FN_FIELDLISTS (type) = (struct fn_fieldlist *)
/* We need to add the type field to the die immediately so we don't
infinitely recurse when dealing with pointers to the structure
- type within the structure itself. */
+ type within the structure itself. */
set_die_type (die, type, cu);
/* set_die_type should be already done. */
}
else if (child_die->tag == DW_TAG_subprogram)
{
- /* C++ member function. */
+ /* C++ member function. */
dwarf2_add_member_fn (&fi, child_die, type, cu);
}
else if (child_die->tag == DW_TAG_inheritance)
/* Complain if virtual function table field not found. */
if (i < TYPE_N_BASECLASSES (t))
complaint (&symfile_complaints,
- _("virtual function table pointer not found when defining class '%s'"),
+ _("virtual function table pointer "
+ "not found when defining class '%s'"),
TYPE_TAG_NAME (type) ? TYPE_TAG_NAME (type) :
"");
}
if (child_type != NULL)
{
- /* The range type was succesfully read. Save it for
- the array type creation. */
+ /* The range type was succesfully read. Save it for the
+ array type creation. */
if ((ndim % DW_FIELD_ALLOC_CHUNK) == 0)
{
range_types = (struct type **)
if (DW_UNSND (attr) >= TYPE_LENGTH (type))
TYPE_LENGTH (type) = DW_UNSND (attr);
else
- complaint (&symfile_complaints, _("\
-DW_AT_byte_size for array type smaller than the total size of elements"));
+ complaint (&symfile_complaints,
+ _("DW_AT_byte_size for array type smaller "
+ "than the total size of elements"));
}
name = dwarf2_name (die, cu);
if (name)
TYPE_NAME (type) = name;
- /* Install the type in the die. */
+ /* Install the type in the die. */
set_die_type (die, type, cu);
/* set_die_type should be already done. */
if (attr) return DW_SND (attr);
- /*
- GNU F77 is a special case, as at 08/2004 array type info is the
- opposite order to the dwarf2 specification, but data is still
- laid out as per normal fortran.
+ /* GNU F77 is a special case, as at 08/2004 array type info is the
+ opposite order to the dwarf2 specification, but data is still
+ laid out as per normal fortran.
- FIXME: dsl/2004-8-20: If G77 is ever fixed, this will also need
- version checking.
- */
+ FIXME: dsl/2004-8-20: If G77 is ever fixed, this will also need
+ version checking. */
if (cu->language == language_fortran
&& cu->producer && strstr (cu->producer, "GNU F77"))
}
/* Extract all information from a DW_TAG_set_type DIE and put it in
- the DIE's type field. */
+ the DIE's type field. */
static struct type *
read_set_type (struct die_info *die, struct dwarf2_cu *cu)
attr = dwarf2_attr (die, DW_AT_location, cu);
if (attr)
{
- /* Support the .debug_loc offsets */
+ /* Support the .debug_loc offsets. */
if (attr_form_is_block (attr))
{
base = decode_locdesc (DW_BLOCK (attr), cu);
child_die = die->child;
while (child_die && child_die->tag)
{
+ LONGEST offset;
+
sym = new_symbol (child_die, NULL, cu);
- attr = dwarf2_attr (child_die, DW_AT_data_member_location, cu);
- if (sym != NULL && attr != NULL)
+ if (sym != NULL
+ && handle_data_member_location (child_die, cu, &offset))
{
- CORE_ADDR byte_offset = 0;
-
- if (attr_form_is_section_offset (attr))
- dwarf2_complex_location_expr_complaint ();
- else if (attr_form_is_constant (attr))
- byte_offset = dwarf2_get_attr_constant_value (attr, 0);
- else if (attr_form_is_block (attr))
- byte_offset = decode_locdesc (DW_BLOCK (attr), cu);
- else
- dwarf2_complex_location_expr_complaint ();
-
- SYMBOL_VALUE_ADDRESS (sym) = base + byte_offset;
+ SYMBOL_VALUE_ADDRESS (sym) = base + offset;
add_symbol_to_list (sym, &global_symbols);
}
child_die = sibling_die (child_die);
read_namespace (struct die_info *die, struct dwarf2_cu *cu)
{
struct objfile *objfile = cu->objfile;
- const char *name;
int is_anonymous;
/* Add a symbol associated to this if we haven't seen the namespace
type = read_type_die (die, cu);
new_symbol (die, type, cu);
- name = namespace_name (die, &is_anonymous, cu);
+ namespace_name (die, &is_anonymous, cu);
if (is_anonymous)
{
const char *previous_prefix = determine_prefix (die, cu);
cp_add_using_directive (previous_prefix, TYPE_NAME (type), NULL,
- NULL, &objfile->objfile_obstack);
+ NULL, NULL, &objfile->objfile_obstack);
}
}
module_name = dwarf2_name (die, cu);
if (!module_name)
- complaint (&symfile_complaints, _("DW_TAG_module has no name, offset 0x%x"),
+ complaint (&symfile_complaints,
+ _("DW_TAG_module has no name, offset 0x%x"),
die->offset);
type = init_type (TYPE_CODE_MODULE, 0, 0, module_name, objfile);
*is_anonymous = (name == NULL);
if (*is_anonymous)
- name = "(anonymous namespace)";
+ name = CP_ANONYMOUS_NAMESPACE_STR;
return name;
}
}
else if (TYPE_LENGTH (type) != byte_size)
{
- complaint (&symfile_complaints, _("invalid pointer size %d"), byte_size);
+ complaint (&symfile_complaints,
+ _("invalid pointer size %d"), byte_size);
}
else
{
}
else
{
- /* check for the DW_AT_byte_size attribute */
+ /* Check for the DW_AT_byte_size attribute. */
attr = dwarf2_attr (die, DW_AT_byte_size, cu);
if (attr)
{
int b;
};
- ('funcp' generates a DW_TAG_subroutine_type DIE)
- */
+ ('funcp' generates a DW_TAG_subroutine_type DIE). */
static struct type *
read_subroutine_type (struct die_info *die, struct dwarf2_cu *cu)
{
- struct type *type; /* Type that this function returns */
- struct type *ftype; /* Function that returns above type */
+ struct type *type; /* Type that this function returns. */
+ struct type *ftype; /* Function that returns above type. */
struct attribute *attr;
type = die_type (die, cu);
the subroutine die. Otherwise set the calling convention to
the default value DW_CC_normal. */
attr = dwarf2_attr (die, DW_AT_calling_convention, cu);
- TYPE_CALLING_CONVENTION (ftype) = attr ? DW_UNSND (attr) : DW_CC_normal;
+ if (attr)
+ TYPE_CALLING_CONVENTION (ftype) = DW_UNSND (attr);
+ else if (cu->producer && strstr (cu->producer, "IBM XL C for OpenCL"))
+ TYPE_CALLING_CONVENTION (ftype) = DW_CC_GDB_IBM_OpenCL;
+ else
+ TYPE_CALLING_CONVENTION (ftype) = DW_CC_normal;
/* We need to add the subroutine type to the die immediately so
we don't infinitely recurse when dealing with parameters
- declared as the same subroutine type. */
+ declared as the same subroutine type. */
set_die_type (die, ftype, cu);
if (die->child != NULL)
break;
case DW_ATE_unsigned:
type_flags |= TYPE_FLAG_UNSIGNED;
+ if (cu->language == language_fortran
+ && name
+ && strncmp (name, "character(", sizeof ("character(") - 1) == 0)
+ code = TYPE_CODE_CHAR;
break;
case DW_ATE_signed_char:
if (cu->language == language_ada || cu->language == language_m2
- || cu->language == language_pascal)
+ || cu->language == language_pascal
+ || cu->language == language_fortran)
code = TYPE_CODE_CHAR;
break;
case DW_ATE_unsigned_char:
if (cu->language == language_ada || cu->language == language_m2
- || cu->language == language_pascal)
+ || cu->language == language_pascal
+ || cu->language == language_fortran)
code = TYPE_CODE_CHAR;
type_flags |= TYPE_FLAG_UNSIGNED;
break;
static struct type *
read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
{
- struct gdbarch *gdbarch = get_objfile_arch (cu->objfile);
struct type *base_type;
struct type *range_type;
struct attribute *attr;
int count = dwarf2_get_attr_constant_value (attr, 1);
high = low + count - 1;
}
+ else
+ {
+ /* Unspecified array length. */
+ high = low - 1;
+ }
}
/* Dwarf-2 specifications explicitly allows to create subrange types
For the following C code: `extern char gdb_int [];'
GCC produces an empty range DIE.
FIXME: muller/2010-05-28: Possible references to object for low bound,
- high bound or count are not yet handled by this code.
- */
+ high bound or count are not yet handled by this code. */
if (TYPE_CODE (base_type) == TYPE_CODE_VOID)
{
struct objfile *objfile = cu->objfile;
if (attr && attr->form == DW_FORM_block1)
TYPE_HIGH_BOUND_UNDEFINED (range_type) = 1;
+ /* Ada expects an empty array on no boundary attributes. */
+ if (attr == NULL && cu->language != language_ada)
+ TYPE_HIGH_BOUND_UNDEFINED (range_type) = 1;
+
name = dwarf2_name (die, cu);
if (name)
TYPE_NAME (range_type) = name;
struct attr_abbrev *cur_attrs;
unsigned int allocated_attrs;
- /* Initialize dwarf2 abbrevs */
+ /* Initialize dwarf2 abbrevs. */
obstack_init (&cu->abbrev_obstack);
cu->dwarf2_abbrevs = obstack_alloc (&cu->abbrev_obstack,
(ABBREV_HASH_SIZE
allocated_attrs = ATTR_ALLOC_CHUNK;
cur_attrs = xmalloc (allocated_attrs * sizeof (struct attr_abbrev));
- /* loop until we reach an abbrev number of 0 */
+ /* Loop until we reach an abbrev number of 0. */
while (abbrev_number)
{
cur_abbrev = dwarf_alloc_abbrev (cu);
if (parent_die == NULL
&& part_die->has_specification == 0
&& part_die->is_declaration == 0
- && (part_die->tag == DW_TAG_typedef
+ && ((part_die->tag == DW_TAG_typedef && !part_die->has_children)
|| part_die->tag == DW_TAG_base_type
|| part_die->tag == DW_TAG_subrange_type))
{
continue;
}
+ /* The exception for DW_TAG_typedef with has_children above is
+ a workaround of GCC PR debug/47510. In the case of this complaint
+ type_name_no_tag_or_error will error on such types later.
+
+ GDB skipped children of DW_TAG_typedef by the shortcut above and then
+ it could not find the child DIEs referenced later, this is checked
+ above. In correct DWARF DW_TAG_typedef should have no children. */
+
+ if (part_die->tag == DW_TAG_typedef && part_die->has_children)
+ complaint (&symfile_complaints,
+ _("DW_TAG_typedef has childen - GCC PR debug/47510 bug "
+ "- DIE at 0x%x [in module %s]"),
+ part_die->offset, cu->objfile->name);
+
/* If we're at the second level, and we're an enumerator, and
our parent has no specification (meaning possibly lives in a
namespace elsewhere), then we can add the partial symbol now
&& parent_die->has_specification == 0)
{
if (part_die->name == NULL)
- complaint (&symfile_complaints, _("malformed enumerator DIE ignored"));
+ complaint (&symfile_complaints,
+ _("malformed enumerator DIE ignored"));
else if (building_psymtab)
add_psymbol_to_list (part_die->name, strlen (part_die->name), 0,
VAR_DOMAIN, LOC_CONST,
part_die->highpc = DW_ADDR (&attr);
break;
case DW_AT_location:
- /* Support the .debug_loc offsets */
+ /* Support the .debug_loc offsets. */
if (attr_form_is_block (&attr))
{
part_die->locdesc = DW_BLOCK (&attr);
/* Ignore absolute siblings, they might point outside of
the current compile unit. */
if (attr.form == DW_FORM_ref_addr)
- complaint (&symfile_complaints, _("ignoring absolute DW_AT_sibling"));
+ complaint (&symfile_complaints,
+ _("ignoring absolute DW_AT_sibling"));
else
part_die->sibling = buffer + dwarf2_get_ref_die_offset (&attr);
break;
}
}
- /* When using the GNU linker, .gnu.linkonce. sections are used to
- eliminate duplicate copies of functions and vtables and such.
- The linker will arbitrarily choose one and discard the others.
- The AT_*_pc values for such functions refer to local labels in
- these sections. If the section from that file was discarded, the
- 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 (has_low_pc_attr && has_high_pc_attr
- && part_die->lowpc < part_die->highpc
- && (part_die->lowpc != 0
- || dwarf2_per_objfile->has_section_at_zero))
- part_die->has_pc_info = 1;
+ if (has_low_pc_attr && has_high_pc_attr)
+ {
+ /* When using the GNU linker, .gnu.linkonce. sections are used to
+ eliminate duplicate copies of functions and vtables and such.
+ The linker will arbitrarily choose one and discard the others.
+ The AT_*_pc values for such functions refer to local labels in
+ these sections. If the section from that file was discarded, the
+ 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 (part_die->lowpc == 0 && !dwarf2_per_objfile->has_section_at_zero)
+ {
+ struct gdbarch *gdbarch = get_objfile_arch (cu->objfile);
+
+ complaint (&symfile_complaints,
+ _("DW_AT_low_pc %s is zero "
+ "for DIE at 0x%x [in module %s]"),
+ paddress (gdbarch, part_die->lowpc),
+ part_die->offset, cu->objfile->name);
+ }
+ /* dwarf2_get_pc_bounds has also the strict low < high requirement. */
+ else if (part_die->lowpc >= part_die->highpc)
+ {
+ struct gdbarch *gdbarch = get_objfile_arch (cu->objfile);
+
+ complaint (&symfile_complaints,
+ _("DW_AT_low_pc %s is not < DW_AT_high_pc %s "
+ "for DIE at 0x%x [in module %s]"),
+ paddress (gdbarch, part_die->lowpc),
+ paddress (gdbarch, part_die->highpc),
+ part_die->offset, cu->objfile->name);
+ }
+ else
+ part_die->has_pc_info = 1;
+ }
return info_ptr;
}
/* Find a partial DIE at OFFSET, which may or may not be in CU,
except in the case of .debug_types DIEs which do not reference
outside their CU (they do however referencing other types via
- DW_FORM_sig8). */
+ DW_FORM_ref_sig8). */
static struct partial_die_info *
find_partial_die (unsigned int offset, struct dwarf2_cu *cu)
if (pd == NULL)
internal_error (__FILE__, __LINE__,
- _("could not find partial DIE 0x%x in cache [from module %s]\n"),
+ _("could not find partial DIE 0x%x "
+ "in cache [from module %s]\n"),
offset, bfd_get_filename (cu->objfile->obfd));
return pd;
}
/* Set default names for some unnamed DIEs. */
if (part_die->name == NULL && part_die->tag == DW_TAG_namespace)
- part_die->name = "(anonymous namespace)";
+ part_die->name = CP_ANONYMOUS_NAMESPACE_STR;
/* If there is no parent die to provide a namespace, and there are
children, see if we can determine the namespace from their linkage
|| part_die->tag == DW_TAG_union_type))
guess_partial_die_structure_name (part_die, cu);
+ /* GCC might emit a nameless struct or union that has a linkage
+ name. See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47510. */
+ if (part_die->name == NULL
+ && (part_die->tag == DW_TAG_structure_type
+ || part_die->tag == DW_TAG_union_type
+ || part_die->tag == DW_TAG_class_type)
+ && part_die->linkage_name != NULL)
+ {
+ char *demangled;
+
+ demangled = cplus_demangle (part_die->linkage_name, DMGL_TYPES);
+ if (demangled)
+ {
+ part_die->name = obsavestring (demangled, strlen (demangled),
+ &cu->objfile->objfile_obstack);
+ xfree (demangled);
+ }
+ }
+
part_die->fixup_called = 1;
}
if (cu->header.version == 2)
DW_ADDR (attr) = read_address (abfd, info_ptr, cu, &bytes_read);
else
- DW_ADDR (attr) = read_offset (abfd, info_ptr, &cu->header, &bytes_read);
+ DW_ADDR (attr) = read_offset (abfd, info_ptr,
+ &cu->header, &bytes_read);
info_ptr += bytes_read;
break;
case DW_FORM_addr:
DW_ADDR (attr) = cu->header.offset + read_8_bytes (abfd, info_ptr);
info_ptr += 8;
break;
- case DW_FORM_sig8:
+ case DW_FORM_ref_sig8:
/* Convert the signature to something we can record in DW_UNSND
for later lookup.
NOTE: This is NULL if the type wasn't found. */
return read_attribute_value (attr, abbrev->form, abfd, info_ptr, cu);
}
-/* read dwarf information from a buffer */
+/* Read dwarf information from a buffer. */
static unsigned int
read_1_byte (bfd *abfd, gdb_byte *buf)
break;
default:
internal_error (__FILE__, __LINE__,
- _("read_address: bad switch, unsigned [in module %s]"),
+ _("read_address: bad switch, "
+ "unsigned [in module %s]"),
bfd_get_filename (abfd));
}
}
}
if (str_offset >= dwarf2_per_objfile->str.size)
{
- error (_("DW_FORM_strp pointing outside of .debug_str section [in module %s]"),
- bfd_get_filename (abfd));
+ 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);
{
lh->maximum_ops_per_instruction = 1;
complaint (&symfile_complaints,
- _("invalid maximum_ops_per_instruction in `.debug_line' section"));
+ _("invalid maximum_ops_per_instruction "
+ "in `.debug_line' section"));
}
lh->default_is_stmt = read_1_byte (abfd, line_ptr);
if (line_ptr > (dwarf2_per_objfile->line.buffer
+ dwarf2_per_objfile->line.size))
complaint (&symfile_complaints,
- _("line number info header doesn't fit in `.debug_line' section"));
+ _("line number info header doesn't "
+ "fit in `.debug_line' section"));
discard_cleanups (back_to);
return lh;
return include_name;
}
+/* Ignore this record_line request. */
+
+static void
+noop_record_line (struct subfile *subfile, int line, CORE_ADDR pc)
+{
+ return;
+}
+
/* Decode the Line Number Program (LNP) for the given line_header
structure and CU. The actual information extracted and the type
of structures created from the LNP depends on the value of PST.
struct gdbarch *gdbarch = get_objfile_arch (objfile);
const int decode_for_pst_p = (pst != NULL);
struct subfile *last_subfile = NULL, *first_subfile = current_subfile;
+ void (*p_record_line) (struct subfile *subfile, int line, CORE_ADDR pc)
+ = record_line;
baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
{
addr = gdbarch_addr_bits_remove (gdbarch, address);
if (last_subfile)
- record_line (last_subfile, 0, addr);
+ (*p_record_line) (last_subfile, 0, addr);
last_subfile = current_subfile;
}
/* Append row to matrix using current values. */
addr = check_cu_functions (address, cu);
addr = gdbarch_addr_bits_remove (gdbarch, addr);
- record_line (current_subfile, line, addr);
+ (*p_record_line) (current_subfile, line, addr);
}
}
basic_block = 0;
else switch (op_code)
{
case DW_LNS_extended_op:
- extended_len = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+ extended_len = read_unsigned_leb128 (abfd, line_ptr,
+ &bytes_read);
line_ptr += bytes_read;
extended_end = line_ptr + extended_len;
extended_op = read_1_byte (abfd, line_ptr);
switch (extended_op)
{
case DW_LNE_end_sequence:
+ p_record_line = record_line;
end_sequence = 1;
break;
case DW_LNE_set_address:
address = read_address (abfd, line_ptr, cu, &bytes_read);
+
+ if (address == 0 && !dwarf2_per_objfile->has_section_at_zero)
+ {
+ /* This line table is for a function which has been
+ GCd by the linker. Ignore it. PR gdb/12528 */
+
+ long line_offset
+ = line_ptr - dwarf2_per_objfile->line.buffer;
+
+ complaint (&symfile_complaints,
+ _(".debug_line address at offset 0x%lx is 0 "
+ "[in module %s]"),
+ line_offset, cu->objfile->name);
+ p_record_line = noop_record_line;
+ }
+
op_index = 0;
line_ptr += bytes_read;
address += baseaddr;
char *cur_file;
unsigned int dir_index, mod_time, length;
- cur_file = read_direct_string (abfd, line_ptr, &bytes_read);
+ cur_file = read_direct_string (abfd, line_ptr,
+ &bytes_read);
line_ptr += bytes_read;
dir_index =
read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
{
addr = gdbarch_addr_bits_remove (gdbarch, address);
if (last_subfile)
- record_line (last_subfile, 0, addr);
+ (*p_record_line) (last_subfile, 0, addr);
last_subfile = current_subfile;
}
addr = check_cu_functions (address, cu);
addr = gdbarch_addr_bits_remove (gdbarch, addr);
- record_line (current_subfile, line, addr);
+ (*p_record_line) (current_subfile, line, addr);
}
}
basic_block = 0;
address increment value corresponding to special opcode
255. I.e., this value is scaled by the minimum
instruction length since special opcode 255 would have
- scaled the the increment. */
+ scaled the increment. */
case DW_LNS_const_add_pc:
{
CORE_ADDR adjust = (255 - lh->opcode_base) / lh->line_range;
if (!decode_for_pst_p)
{
addr = gdbarch_addr_bits_remove (gdbarch, address);
- record_line (current_subfile, 0, addr);
+ (*p_record_line) (current_subfile, 0, addr);
}
}
}
subfile's name. */
static void
-dwarf2_start_subfile (char *filename, const char *dirname, const char *comp_dir)
+dwarf2_start_subfile (char *filename, const char *dirname,
+ const char *comp_dir)
{
char *fullname;
dwarf2_symbol_mark_computed (attr, sym, cu);
SYMBOL_CLASS (sym) = LOC_COMPUTED;
+
+ if (SYMBOL_COMPUTED_OPS (sym) == &dwarf2_loclist_funcs)
+ cu->has_loclist = 1;
}
/* Given a pointer to a DWARF information entry, figure out if we need
case DW_TAG_constant:
case DW_TAG_variable:
case DW_TAG_member:
- /* Compilation with minimal debug info may result in variables
- with missing type entries. Change the misleading `void' type
- to something sensible. */
+ /* Compilation with minimal debug info may result in
+ variables with missing type entries. Change the
+ misleading `void' type to something sensible. */
if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_VOID)
SYMBOL_TYPE (sym)
= objfile_type (objfile)->nodebug_data_symbol;
/* Not a tag we recognize. Hopefully we aren't processing
trash data, but since we must specifically ignore things
we don't recognize, there is nothing else we should do at
- this point. */
+ this point. */
complaint (&symfile_complaints, _("unsupported tag: '%s'"),
dwarf_tag_name (die->tag));
break;
converted to host endianness, so we just need to sign- or
zero-extend it as appropriate. */
case DW_FORM_data1:
- *bytes = dwarf2_const_value_data (attr, type, name, obstack, cu, value, 8);
+ *bytes = dwarf2_const_value_data (attr, type, name,
+ obstack, cu, value, 8);
break;
case DW_FORM_data2:
- *bytes = dwarf2_const_value_data (attr, type, name, obstack, cu, value, 16);
+ *bytes = dwarf2_const_value_data (attr, type, name,
+ obstack, cu, value, 16);
break;
case DW_FORM_data4:
- *bytes = dwarf2_const_value_data (attr, type, name, obstack, cu, value, 32);
+ *bytes = dwarf2_const_value_data (attr, type, name,
+ obstack, cu, value, 32);
break;
case DW_FORM_data8:
- *bytes = dwarf2_const_value_data (attr, type, name, obstack, cu, value, 64);
+ *bytes = dwarf2_const_value_data (attr, type, name,
+ obstack, cu, value, 64);
break;
case DW_FORM_sdata:
this_type = get_die_type_at_offset (offset, cu->per_cu);
}
- else if (attr->form == DW_FORM_sig8)
+ else if (attr->form == DW_FORM_ref_sig8)
{
struct signatured_type *sig_type = DW_SIGNATURED_TYPE (attr);
struct dwarf2_cu *sig_cu;
die->offset, cu->objfile->name);
gdb_assert (sig_type->per_cu.from_debug_types);
- offset = sig_type->offset + sig_type->type_offset;
+ offset = sig_type->per_cu.offset + sig_type->type_offset;
this_type = get_die_type_at_offset (offset, &sig_type->per_cu);
}
else
this_type = read_module_type (die, cu);
break;
default:
- complaint (&symfile_complaints, _("unexpected tag in read_type_die: '%s'"),
+ complaint (&symfile_complaints,
+ _("unexpected tag in read_type_die: '%s'"),
dwarf_tag_name (die->tag));
break;
}
/* Test for '::' as a sanity check. */
if (actual_name_len > die_name_len + 2
- && actual_name[actual_name_len - die_name_len - 1] == ':')
+ && actual_name[actual_name_len
+ - die_name_len - 1] == ':')
name =
obsavestring (actual_name,
actual_name_len - die_name_len - 2,
}
}
-/* Return a newly-allocated string formed by concatenating PREFIX and
- SUFFIX with appropriate separator. If PREFIX or SUFFIX is NULL or empty, then
- simply copy the SUFFIX or PREFIX, respectively. If OBS is non-null,
- perform an obconcat, otherwise allocate storage for the result. The CU argument
- is used to determine the language and hence, the appropriate separator. */
+/* Return a newly-allocated string formed by concatenating PREFIX and SUFFIX
+ with appropriate separator. If PREFIX or SUFFIX is NULL or empty, then
+ simply copy the SUFFIX or PREFIX, respectively. If OBS is non-null, perform
+ an obconcat, otherwise allocate storage for the result. The CU argument is
+ used to determine the language and hence, the appropriate separator. */
#define MAX_SEP_LEN 7 /* strlen ("__") + strlen ("_MOD_") */
const char *lead = "";
const char *sep;
- if (suffix == NULL || suffix[0] == '\0' || prefix == NULL || prefix[0] == '\0')
+ if (suffix == NULL || suffix[0] == '\0'
+ || prefix == NULL || prefix[0] == '\0')
sep = "";
else if (cu->language == language_java)
sep = ".";
if (obs == NULL)
{
- char *retval = xmalloc (strlen (prefix) + MAX_SEP_LEN + strlen (suffix) + 1);
+ char *retval
+ = xmalloc (strlen (prefix) + MAX_SEP_LEN + strlen (suffix) + 1);
strcpy (retval, lead);
strcat (retval, prefix);
struct attribute *attr;
attr = dwarf2_attr (die, DW_AT_name, cu);
- if (!attr || !DW_STRING (attr))
+ if ((!attr || !DW_STRING (attr))
+ && die->tag != DW_TAG_class_type
+ && die->tag != DW_TAG_interface_type
+ && die->tag != DW_TAG_structure_type
+ && die->tag != DW_TAG_union_type)
return NULL;
switch (die->tag)
structures or unions. These were of the form "._%d" in GCC 4.1,
or simply "<anonymous struct>" or "<anonymous union>" in GCC 4.3
and GCC 4.4. We work around this problem by ignoring these. */
- if (strncmp (DW_STRING (attr), "._", 2) == 0
- || strncmp (DW_STRING (attr), "<anonymous", 10) == 0)
+ if (attr && DW_STRING (attr)
+ && (strncmp (DW_STRING (attr), "._", 2) == 0
+ || strncmp (DW_STRING (attr), "<anonymous", 10) == 0))
return NULL;
+
+ /* GCC might emit a nameless typedef that has a linkage name. See
+ http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47510. */
+ if (!attr || DW_STRING (attr) == NULL)
+ {
+ char *demangled = NULL;
+
+ attr = dwarf2_attr (die, DW_AT_linkage_name, cu);
+ if (attr == NULL)
+ attr = dwarf2_attr (die, DW_AT_MIPS_linkage_name, cu);
+
+ if (attr == NULL || DW_STRING (attr) == NULL)
+ return NULL;
+
+ /* Avoid demangling DW_STRING (attr) the second time on a second
+ call for the same DIE. */
+ if (!DW_STRING_IS_CANONICAL (attr))
+ demangled = cplus_demangle (DW_STRING (attr), DMGL_TYPES);
+
+ if (demangled)
+ {
+ /* FIXME: we already did this for the partial symbol... */
+ DW_STRING (attr)
+ = obsavestring (demangled, strlen (demangled),
+ &cu->objfile->objfile_obstack);
+ DW_STRING_IS_CANONICAL (attr) = 1;
+ xfree (demangled);
+ }
+ }
break;
default:
return "DW_FORM_exprloc";
case DW_FORM_flag_present:
return "DW_FORM_flag_present";
- case DW_FORM_sig8:
- return "DW_FORM_sig8";
+ case DW_FORM_ref_sig8:
+ return "DW_FORM_ref_sig8";
default:
return "DW_FORM_<unknown>";
}
/* Convert a DWARF stack opcode into its string name. */
const char *
-dwarf_stack_op_name (unsigned op, int def)
+dwarf_stack_op_name (unsigned op)
{
switch (op)
{
return "DW_OP_GNU_uninit";
case DW_OP_GNU_implicit_pointer:
return "DW_OP_GNU_implicit_pointer";
+ case DW_OP_GNU_entry_value:
+ return "DW_OP_GNU_entry_value";
+ case DW_OP_GNU_const_type:
+ return "DW_OP_GNU_const_type";
+ case DW_OP_GNU_regval_type:
+ return "DW_OP_GNU_regval_type";
+ case DW_OP_GNU_deref_type:
+ return "DW_OP_GNU_deref_type";
+ case DW_OP_GNU_convert:
+ return "DW_OP_GNU_convert";
+ case DW_OP_GNU_reinterpret:
+ return "DW_OP_GNU_reinterpret";
default:
- return def ? "OP_<unknown>" : NULL;
+ return NULL;
}
}
}
}
-/* Convert a DWARF call frame info operation to its string name. */
+/* Convert a DWARF call frame info operation to its string name. */
#if 0
static char *
case DW_FORM_block4:
case DW_FORM_block:
case DW_FORM_block1:
- fprintf_unfiltered (f, "block: size %d", DW_BLOCK (&die->attrs[i])->size);
+ fprintf_unfiltered (f, "block: size %d",
+ DW_BLOCK (&die->attrs[i])->size);
break;
case DW_FORM_exprloc:
fprintf_unfiltered (f, "expression: size %u",
fprintf_unfiltered (f, "section offset: %s",
pulongest (DW_UNSND (&die->attrs[i])));
break;
- case DW_FORM_sig8:
+ case DW_FORM_ref_sig8:
if (DW_SIGNATURED_TYPE (&die->attrs[i]) != NULL)
fprintf_unfiltered (f, "signatured type, offset: 0x%x",
- DW_SIGNATURED_TYPE (&die->attrs[i])->offset);
+ DW_SIGNATURED_TYPE (&die->attrs[i])->per_cu.offset);
else
fprintf_unfiltered (f, "signatured type, offset: unknown");
break;
fprintf_unfiltered (f, "flag: TRUE");
break;
case DW_FORM_indirect:
- /* the reader will have reduced the indirect form to
- the "base form" so this form should not occur */
- fprintf_unfiltered (f, "unexpected attribute form: DW_FORM_indirect");
+ /* The reader will have reduced the indirect form to
+ the "base form" so this form should not occur. */
+ fprintf_unfiltered (f,
+ "unexpected attribute form: DW_FORM_indirect");
break;
default:
fprintf_unfiltered (f, "unsupported attribute form: %d.",
}
else
{
- fprintf_unfiltered (f, " [not printed, max nesting level reached]\n");
+ fprintf_unfiltered (f,
+ " [not printed, max nesting level reached]\n");
}
}
return DW_UNSND (attr);
else
{
- complaint (&symfile_complaints, _("Attribute value is not a constant (%s)"),
+ complaint (&symfile_complaints,
+ _("Attribute value is not a constant (%s)"),
dwarf_form_name (attr->form));
return default_value;
}
if (is_ref_attr (attr))
die = follow_die_ref (src_die, attr, ref_cu);
- else if (attr->form == DW_FORM_sig8)
+ else if (attr->form == DW_FORM_ref_sig8)
die = follow_die_sig (src_die, attr, ref_cu);
else
{
{
/* .debug_types CUs cannot reference anything outside their CU.
If they need to, they have to reference a signatured type via
- DW_FORM_sig8. */
+ DW_FORM_ref_sig8. */
if (! offset_in_cu_p (&cu->header, offset))
return NULL;
}
return retval;
}
+/* Return the type of the DIE at DIE_OFFSET in the CU named by
+ PER_CU. */
+
+struct type *
+dwarf2_get_die_type (unsigned int die_offset,
+ struct dwarf2_per_cu_data *per_cu)
+{
+ dw2_setup (per_cu->objfile);
+ return get_die_type_at_offset (die_offset, per_cu);
+}
+
/* Follow the signature attribute ATTR in SRC_DIE.
On entry *REF_CU is the CU of SRC_DIE.
On exit *REF_CU is the CU of the result. */
return die;
}
- error (_("Dwarf Error: Cannot find signatured DIE at 0x%x referenced from DIE "
- "at 0x%x [in module %s]"),
+ error (_("Dwarf Error: Cannot find signatured DIE at 0x%x referenced "
+ "from DIE at 0x%x [in module %s]"),
sig_type->type_offset, src_die->offset, objfile->name);
}
/* This is only used to lookup previously recorded types.
If we didn't find it, it's our bug. */
gdb_assert (type_sig != NULL);
- gdb_assert (offset == type_sig->offset);
+ gdb_assert (offset == type_sig->per_cu.offset);
return type_sig;
}
struct cleanup *back_to, *free_cu_cleanup;
dwarf2_read_section (objfile, &dwarf2_per_objfile->types);
- types_ptr = dwarf2_per_objfile->types.buffer + type_sig->offset;
+ types_ptr = dwarf2_per_objfile->types.buffer + type_sig->per_cu.offset;
gdb_assert (type_sig->per_cu.cu == NULL);
break;
case DW_OP_plus_uconst:
- stack[stacki] += read_unsigned_leb128 (NULL, (data + i), &bytes_read);
+ stack[stacki] += read_unsigned_leb128 (NULL, (data + i),
+ &bytes_read);
i += bytes_read;
break;
break;
default:
- complaint (&symfile_complaints, _("unsupported stack op: '%s'"),
- dwarf_stack_op_name (op, 1));
+ {
+ const char *name = dwarf_stack_op_name (op);
+
+ if (name)
+ complaint (&symfile_complaints, _("unsupported stack op: '%s'"),
+ name);
+ else
+ complaint (&symfile_complaints, _("unsupported stack op: '%02x'"),
+ op);
+ }
+
return (stack[stacki]);
}
if (*p == ' ')
{
complaint (&symfile_complaints,
- _("macro definition contains spaces in formal argument list:\n`%s'"),
+ _("macro definition contains spaces "
+ "in formal argument list:\n`%s'"),
body);
while (*p == ' ')
if (mac_ptr >= mac_end)
{
/* Complaint is printed during the second pass as GDB will probably
- stop the first pass earlier upon finding DW_MACINFO_start_file. */
+ stop the first pass earlier upon finding
+ DW_MACINFO_start_file. */
break;
}
file = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
mac_ptr += bytes_read;
- current_file = macro_start_file (file, line, current_file, comp_dir,
- lh, cu->objfile);
+ current_file = macro_start_file (file, line, current_file,
+ comp_dir, lh, cu->objfile);
}
break;
_("something-or-other"), line, body);
break;
}
- if ((line == 0 && !at_commandline) || (line != 0 && at_commandline))
+ if ((line == 0 && !at_commandline)
+ || (line != 0 && at_commandline))
complaint (&symfile_complaints,
_("debug info gives %s macro %s with %s line %d: %s"),
at_commandline ? _("command-line") : _("in-file"),
file = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
mac_ptr += bytes_read;
- if ((line == 0 && !at_commandline) || (line != 0 && at_commandline))
+ if ((line == 0 && !at_commandline)
+ || (line != 0 && at_commandline))
complaint (&symfile_complaints,
_("debug info gives source %d included "
"from %s at %s line %d"),
case DW_MACINFO_end_file:
if (! current_file)
complaint (&symfile_complaints,
- _("macro debug info has an unmatched `close_file' directive"));
+ _("macro debug info has an unmatched "
+ "`close_file' directive"));
else
{
current_file = current_file->included_by;
next_type = read_1_byte (abfd, mac_ptr);
if (next_type != 0)
complaint (&symfile_complaints,
- _("no terminating 0-type entry for macros in `.debug_macinfo' section"));
+ _("no terminating 0-type entry for "
+ "macros in `.debug_macinfo' section"));
return;
}
{
unsigned int bytes_read;
int constant;
- char *string;
constant = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
mac_ptr += bytes_read;
- string = read_direct_string (abfd, mac_ptr, &bytes_read);
+ read_direct_string (abfd, mac_ptr, &bytes_read);
mac_ptr += bytes_read;
/* We don't recognize any vendor extensions. */
}
/* Check if the attribute's form is a DW_FORM_block*
- if so return true else false. */
+ if so return true else false. */
static int
attr_form_is_block (struct attribute *attr)
{
/* ".debug_loc" may not exist at all, or the offset may be outside
the section. If so, fall through to the complaint in the
other branch. */
- && DW_UNSND (attr) < dwarf2_per_objfile->loc.size)
+ && DW_UNSND (attr) < dwarf2_section_size (dwarf2_per_objfile->objfile,
+ &dwarf2_per_objfile->loc))
{
struct dwarf2_loclist_baton *baton;
if (cu->base_known == 0)
complaint (&symfile_complaints,
- _("Location list used without specifying the CU base address."));
+ _("Location list used without "
+ "specifying the CU base address."));
SYMBOL_COMPUTED_OPS (sym) = &dwarf2_loclist_funcs;
SYMBOL_LOCATION_BATON (sym) = baton;
if (attr)
set_cu_language (DW_UNSND (attr), cu);
else
- set_cu_language (language_minimal, cu);
+ {
+ cu->language = language_minimal;
+ cu->language_defn = language_def (cu->language);
+ }
}
/* Release one cached compilation unit, CU. We unlink it from the tree
/* Cached DIE trees use xmalloc and the comp_unit_obstack. */
free_cached_comp_units (NULL);
- if (dwarf2_per_objfile->using_index)
- {
- int i;
-
- for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
- {
- int j;
- struct dwarf2_per_cu_data *per_cu =
- dwarf2_per_objfile->all_comp_units[i];
-
- if (!per_cu->v.quick->lines)
- continue;
-
- for (j = 0; j < per_cu->v.quick->lines->num_file_names; ++j)
- {
- if (per_cu->v.quick->file_names)
- xfree ((void *) per_cu->v.quick->file_names[j]);
- if (per_cu->v.quick->full_names)
- xfree ((void *) per_cu->v.quick->full_names[j]);
- }
-
- free_line_header (per_cu->v.quick->lines);
- }
- }
+ if (dwarf2_per_objfile->quick_file_names_table)
+ htab_delete (dwarf2_per_objfile->quick_file_names_table);
/* Everything else should be on the objfile obstack. */
}
static void
munmap_section_buffer (struct dwarf2_section_info *info)
{
- if (info->was_mmapped)
+ if (info->map_addr != NULL)
{
#ifdef HAVE_MMAP
- intptr_t begin = (intptr_t) info->buffer;
- intptr_t map_begin = begin & ~(pagesize - 1);
- size_t map_length = info->size + begin - map_begin;
+ int res;
- gdb_assert (munmap ((void *) map_begin, map_length) == 0);
+ res = munmap (info->map_addr, info->map_len);
+ gdb_assert (res == 0);
#else
/* Without HAVE_MMAP, we should never be here to begin with. */
gdb_assert_not_reached ("no mmap support");
const char *str;
};
-/* Hash function for a strtab_entry. */
+/* Hash function for a strtab_entry.
+
+ Function is used only during write_hash_table so no index format backward
+ compatibility is needed. */
static hashval_t
hash_strtab_entry (const void *e)
{
const struct strtab_entry *entry = e;
- return mapped_index_string_hash (entry->str);
+ return mapped_index_string_hash (INT_MAX, entry->str);
}
/* Equality function for a strtab_entry. */
}
/* Find a slot in SYMTAB for the symbol NAME. Returns a pointer to
- the slot. */
+ the slot.
+
+ Function is used only during write_hash_table so no index format backward
+ compatibility is needed. */
static struct symtab_index_entry **
find_slot (struct mapped_symtab *symtab, const char *name)
{
- offset_type index, step, hash = mapped_index_string_hash (name);
+ offset_type index, step, hash = mapped_index_string_hash (INT_MAX, name);
index = hash & (symtab->size - 1);
step = ((hash * 17) & (symtab->size - 1)) | 1;
/* Don't push an index twice. Due to how we add entries we only
have to check the last one. */
if (VEC_empty (offset_type, (*slot)->cu_indices)
- || VEC_length (offset_type, (*slot)->cu_indices) != cu_index)
+ || VEC_last (offset_type, (*slot)->cu_indices) != cu_index)
VEC_safe_push (offset_type, (*slot)->cu_indices, cu_index);
}
int previous_valid;
/* Index of the CU in the table of all CUs in the index file. */
unsigned int previous_cu_index;
- /* Start address of the CU. */
+ /* Start address of the CU. */
CORE_ADDR previous_cu_start;
};
write_psymbols (info->symtab,
info->psyms_seen,
- info->objfile->global_psymbols.list + psymtab->globals_offset,
+ info->objfile->global_psymbols.list
+ + psymtab->globals_offset,
psymtab->n_global_syms, info->cu_index,
0);
write_psymbols (info->symtab,
info->psyms_seen,
- info->objfile->static_psymbols.list + psymtab->statics_offset,
+ info->objfile->static_psymbols.list
+ + psymtab->statics_offset,
psymtab->n_static_syms, info->cu_index,
1);
- store_unsigned_integer (val, 8, BFD_ENDIAN_LITTLE, entry->offset);
+ store_unsigned_integer (val, 8, BFD_ENDIAN_LITTLE, entry->per_cu.offset);
obstack_grow (info->types_list, val, 8);
store_unsigned_integer (val, 8, BFD_ENDIAN_LITTLE, entry->type_offset);
obstack_grow (info->types_list, val, 8);
htab_t cu_index_htab;
struct psymtab_cu_index_map *psymtab_cu_index_map;
- if (!objfile->psymtabs)
+ if (!objfile->psymtabs || !objfile->psymtabs_addrmap)
return;
+
if (dwarf2_per_objfile->using_index)
error (_("Cannot use an index to create the index"));
all_comp_units, but only in their own hash table. */
for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
{
- struct dwarf2_per_cu_data *per_cu = dwarf2_per_objfile->all_comp_units[i];
+ struct dwarf2_per_cu_data *per_cu
+ = dwarf2_per_objfile->all_comp_units[i];
struct partial_symtab *psymtab = per_cu->v.psymtab;
gdb_byte val[8];
struct psymtab_cu_index_map *map;
total_len = size_of_contents;
/* The version number. */
- val = MAYBE_SWAP (3);
+ val = MAYBE_SWAP (5);
obstack_grow (&contents, &val, sizeof (val));
/* The offset of the CU list from the start of the file. */
do_cleanups (cleanup);
}
-/* The mapped index file format is designed to be directly mmap()able
- on any architecture. In most cases, a datum is represented using a
- little-endian 32-bit integer value, called an offset_type. Big
- endian machines must byte-swap the values before using them.
- Exceptions to this rule are noted. The data is laid out such that
- alignment is always respected.
-
- A mapped index consists of several sections.
-
- 1. The file header. This is a sequence of values, of offset_type
- unless otherwise noted:
-
- [0] The version number, currently 3. Versions 1 and 2 are
- obsolete.
- [1] The offset, from the start of the file, of the CU list.
- [2] The offset, from the start of the file, of the types CU list.
- Note that this section can be empty, in which case this offset will
- be equal to the next offset.
- [3] The offset, from the start of the file, of the address section.
- [4] The offset, from the start of the file, of the symbol table.
- [5] The offset, from the start of the file, of the constant pool.
-
- 2. The CU list. This is a sequence of pairs of 64-bit
- little-endian values, sorted by the CU offset. The first element
- in each pair is the offset of a CU in the .debug_info section. The
- second element in each pair is the length of that CU. References
- to a CU elsewhere in the map are done using a CU index, which is
- just the 0-based index into this table. Note that if there are
- type CUs, then conceptually CUs and type CUs form a single list for
- the purposes of CU indices.
-
- 3. The types CU list. This is a sequence of triplets of 64-bit
- little-endian values. In a triplet, the first value is the CU
- offset, the second value is the type offset in the CU, and the
- third value is the type signature. The types CU list is not
- sorted.
-
- 4. The address section. The address section consists of a sequence
- of address entries. Each address entry has three elements.
- [0] The low address. This is a 64-bit little-endian value.
- [1] The high address. This is a 64-bit little-endian value.
- Like DW_AT_high_pc, the value is one byte beyond the end.
- [2] The CU index. This is an offset_type value.
-
- 5. The symbol table. This is a hash table. The size of the hash
- table is always a power of 2. The initial hash and the step are
- currently defined by the `find_slot' function.
-
- Each slot in the hash table consists of a pair of offset_type
- values. The first value is the offset of the symbol's name in the
- constant pool. The second value is the offset of the CU vector in
- the constant pool.
-
- If both values are 0, then this slot in the hash table is empty.
- This is ok because while 0 is a valid constant pool index, it
- cannot be a valid index for both a string and a CU vector.
-
- A string in the constant pool is stored as a \0-terminated string,
- as you'd expect.
-
- A CU vector in the constant pool is a sequence of offset_type
- values. The first value is the number of CU indices in the vector.
- Each subsequent value is the index of a CU in the CU list. This
- element in the hash table is used to indicate which CUs define the
- symbol.
-
- 6. The constant pool. This is simply a bunch of bytes. It is
- organized so that alignment is correct: CU vectors are stored
- first, followed by strings. */
+/* Implementation of the `save gdb-index' command.
+
+ Note that the file format used by this command is documented in the
+ GDB manual. Any changes here must be documented there. */
static void
save_gdb_index_command (char *arg, int from_tty)
show_dwarf2_always_disassemble (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
- fprintf_filtered (file, _("\
-Whether to always disassemble DWARF expressions is %s.\n"),
+ fprintf_filtered (file,
+ _("Whether to always disassemble "
+ "DWARF expressions is %s.\n"),
value);
}
c = add_cmd ("gdb-index", class_files, save_gdb_index_command,
_("\
-Save a .gdb-index file.\n\
+Save a gdb-index file.\n\
Usage: save gdb-index DIRECTORY"),
&save_cmdlist);
set_cmd_completer (c, filename_completer);