/* 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.
#include "vec.h"
#include "c-lang.h"
#include "valprint.h"
+#include <ctype.h>
#include <fcntl.h>
#include "gdb_string.h"
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 hash table. */
- const offset_type *index_table;
+
+ /* The symbol table, implemented as a hash table. */
+ const offset_type *symbol_table;
+
/* Size in slots, each slot is 2 offset_types. */
- offset_type index_table_slots;
+ offset_type symbol_table_slots;
+
/* A pointer to the constant pool. */
const char *constant_pool;
};
VMA of 0. */
int has_section_at_zero;
- /* True if we are using the mapped index. */
+ /* True if we are using the mapped index,
+ or we are faking it for OBJF_READNOW's sake. */
unsigned char using_index;
- /* The mapped index. */
+ /* 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;
/* 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;
- /* A temporary mark bit used when iterating over all CUs in
- expand_symtabs_matching. */
- unsigned int mark : 1;
+ /* 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. */
- /* 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
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. */
/* Flag set if any of the DIE's children are template arguments. */
unsigned int has_template_arguments : 1;
+ /* Flag set if fixup_partial_die has been called on this die. */
+ unsigned int fixup_called : 1;
+
/* The name of this DIE. Normally the value of DW_AT_name, but
sometimes a default name for unnamed DIEs. */
char *name;
+ /* The linkage name, if present. */
+ const char *linkage_name;
+
/* The scope to prepend to our children. This is generally
allocated on the comp_unit_obstack, so will disappear
when this compilation unit leaves the cache. */
/* Pointer into the info_buffer (or types_buffer) pointing at the target of
DW_AT_sibling, if any. */
+ /* NOTE: This member isn't strictly necessary, read_partial_die could
+ return DW_AT_sibling values to its caller load_partial_dies. */
gdb_byte *sibling;
/* If HAS_SPECIFICATION, the offset of the DIE referred to by
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. */
/* The dies in a compilation unit form an n-ary tree. PARENT
points to this die's parent; CHILD points to the first child of
this node; and all the children of a given node are chained
- together via their SIBLING fields, terminated by a die whose
- tag is zero. */
+ together via their SIBLING fields. */
struct die_info *child; /* Its first child, if any. */
struct die_info *sibling; /* Its next sibling, if any. */
struct die_info *parent; /* Its parent, if any. */
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 */
(unsigned int offset,
bfd *abfd, struct dwarf2_cu *cu));
-static void dwarf_decode_lines (struct line_header *, char *, bfd *,
+static void dwarf_decode_lines (struct line_header *, const char *, bfd *,
struct dwarf2_cu *, struct partial_symtab *);
-static void dwarf2_start_subfile (char *, char *, char *);
+static void dwarf2_start_subfile (char *, const char *, const char *);
static struct symbol *new_symbol (struct die_info *, struct type *,
struct dwarf2_cu *);
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 *);
static int attr_form_is_constant (struct attribute *);
+static void fill_in_loclist_baton (struct dwarf2_cu *cu,
+ struct dwarf2_loclist_baton *baton,
+ struct attribute *attr);
+
static void dwarf2_symbol_mark_computed (struct attribute *attr,
struct symbol *sym,
struct dwarf2_cu *cu);
static struct dwarf2_per_cu_data *dwarf2_find_comp_unit
(unsigned int offset, struct objfile *objfile);
-static struct dwarf2_cu *alloc_one_comp_unit (struct objfile *objfile);
+static void init_one_comp_unit (struct dwarf2_cu *cu,
+ struct objfile *objfile);
+
+static void prepare_one_comp_unit (struct dwarf2_cu *cu,
+ struct die_info *comp_unit_die);
static void free_one_comp_unit (void *);
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. */
info->was_mmapped = 0;
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. */
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,
else
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. */
+
static void
dw2_do_instantiate_symtab (struct objfile *objfile,
struct dwarf2_per_cu_data *per_cu)
/* Ensure that the symbols for PER_CU have been read in. OBJFILE is
the objfile from which this CU came. Returns the resulting symbol
table. */
+
static struct symtab *
dw2_instantiate_symtab (struct objfile *objfile,
struct dwarf2_per_cu_data *per_cu)
}
/* Return the CU given its index. */
+
static struct dwarf2_per_cu_data *
dw2_get_cu (int index)
{
/* A helper function that knows how to read a 64-bit value in a way
that doesn't make gdb die. Returns 1 if the conversion went ok, 0
otherwise. */
+
static int
extract_cu_value (const char *bytes, ULONGEST *result)
{
/* Read the CU list from the mapped index, and use it to create all
the CU objects for this objfile. Return 0 if something went wrong,
1 if everything went ok. */
+
static int
create_cus_from_index (struct objfile *objfile, const gdb_byte *cu_list,
offset_type cu_list_elements)
/* Read the address map data from the mapped index, and use it to
populate the objfile's psymtabs_addrmap. */
+
static void
create_addrmap_from_index (struct objfile *objfile, struct mapped_index *index)
{
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 a slot in the mapped index INDEX for the object named NAME.
If NAME is found, set *VEC_OUT to point to the CU vector in the
constant pool and return 1. If NAME cannot be found, return 0. */
+
static int
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, '(');
- slot = hash & (index->index_table_slots - 1);
- step = ((hash * 17) & (index->index_table_slots - 1)) | 1;
+ 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 (;;)
{
/* Convert a slot number to an offset into the table. */
offset_type i = 2 * slot;
const char *str;
- if (index->index_table[i] == 0 && index->index_table[i + 1] == 0)
- return 0;
+ if (index->symbol_table[i] == 0 && index->symbol_table[i + 1] == 0)
+ {
+ do_cleanups (back_to);
+ return 0;
+ }
- str = index->constant_pool + MAYBE_SWAP (index->index_table[i]);
- if (!strcmp (name, str))
+ str = index->constant_pool + MAYBE_SWAP (index->symbol_table[i]);
+ if (!cmp (name, str))
{
*vec_out = (offset_type *) (index->constant_pool
- + MAYBE_SWAP (index->index_table[i + 1]));
+ + MAYBE_SWAP (index->symbol_table[i + 1]));
+ do_cleanups (back_to);
return 1;
}
- slot = (slot + step) & (index->index_table_slots - 1);
+ slot = (slot + step) & (index->symbol_table_slots - 1);
}
}
/* Read the index file. If everything went ok, initialize the "quick"
elements of all the CUs and return 1. Otherwise, return 0. */
+
static int
dwarf2_read_index (struct objfile *objfile)
{
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
+ executable while splitting it for the separate debug info file. */
+ if ((bfd_get_file_flags (dwarf2_per_objfile->gdb_index.asection)
+ & SEC_HAS_CONTENTS) == 0)
+ return 0;
+
dwarf2_read_section (objfile, &dwarf2_per_objfile->gdb_index);
addr = dwarf2_per_objfile->gdb_index.buffer;
/* Version check. */
version = MAYBE_SWAP (*(offset_type *) addr);
- if (version == 1)
- {
- /* Index version 1 neglected to account for .debug_types. So,
- if we see .debug_types, we cannot use this index. */
- if (dwarf2_per_objfile->types.asection != NULL
- && dwarf2_per_objfile->types.size != 0)
- return 0;
- }
- else if (version != 2)
+ /* Versions earlier than 3 emitted every copy of a psymbol. This
+ 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 > 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));
/ 8);
++i;
- if (version == 2)
- {
- types_list = addr + MAYBE_SWAP (metadata[i]);
- types_list_elements = ((MAYBE_SWAP (metadata[i + 1])
- - MAYBE_SWAP (metadata[i]))
- / 8);
- ++i;
- }
+ types_list = addr + MAYBE_SWAP (metadata[i]);
+ types_list_elements = ((MAYBE_SWAP (metadata[i + 1])
+ - MAYBE_SWAP (metadata[i]))
+ / 8);
+ ++i;
map->address_table = addr + MAYBE_SWAP (metadata[i]);
map->address_table_size = (MAYBE_SWAP (metadata[i + 1])
- MAYBE_SWAP (metadata[i]));
++i;
- map->index_table = (offset_type *) (addr + MAYBE_SWAP (metadata[i]));
- map->index_table_slots = ((MAYBE_SWAP (metadata[i + 1])
- - MAYBE_SWAP (metadata[i]))
- / (2 * sizeof (offset_type)));
+ map->symbol_table = (offset_type *) (addr + MAYBE_SWAP (metadata[i]));
+ map->symbol_table_slots = ((MAYBE_SWAP (metadata[i + 1])
+ - MAYBE_SWAP (metadata[i]))
+ / (2 * sizeof (offset_type)));
++i;
map->constant_pool = addr + MAYBE_SWAP (metadata[i]);
if (!create_cus_from_index (objfile, cu_list, cu_list_elements))
return 0;
- if (version == 2
- && types_list_elements
+ if (types_list_elements
&& !create_signatured_type_table_from_index (objfile, types_list,
types_list_elements))
return 0;
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 sets the global
dwarf2_per_objfile according to OBJFILE. */
+
static void
dw2_setup (struct objfile *objfile)
{
/* 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;
-
- memset (&cu, 0, sizeof (cu));
- cu.objfile = objfile;
- obstack_init (&cu.comp_unit_obstack);
+ 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)
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 *
dw2_find_last_source_symtab (struct objfile *objfile)
{
int index;
+
dw2_setup (objfile);
index = dwarf2_per_objfile->n_comp_units - 1;
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]);
+ 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
struct dwarf2_per_cu_data *base_cu = NULL;
dw2_setup (objfile);
+
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;
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)
+ if (this_real_name != NULL
+ && FILENAME_CMP (real_path, this_real_name) == 0)
{
- char *rp = gdb_realpath (this_full_name);
- if (rp != NULL && FILENAME_CMP (real_path, rp) == 0)
- {
- xfree (rp);
- *result = dw2_instantiate_symtab (objfile, per_cu);
- return 1;
- }
- xfree (rp);
+ *result = dw2_instantiate_symtab (objfile, per_cu);
+ return 1;
}
}
}
/* A helper function that expands all symtabs that hold an object
named NAME. */
+
static void
dw2_do_expand_symtabs_matching (struct objfile *objfile, const char *name)
{
dw2_setup (objfile);
+ /* index_table is NULL if OBJF_READNOW. */
if (dwarf2_per_objfile->index_table)
{
offset_type *vec;
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 i;
dw2_setup (objfile);
- for (i = 0; i < (dwarf2_per_objfile->n_comp_units
- + dwarf2_per_objfile->n_type_comp_units); ++i)
+
+ /* We don't need to consider type units here.
+ This is only called for examining code, e.g. expand_line_sal.
+ There can be an order of magnitude (or more) more type units
+ than comp units, and we avoid them if we can. */
+
+ for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++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_name = per_cu->v.quick->file_names[j];
- if (strcmp (this_name, filename) == 0)
+ const char *this_name = file_data->file_names[j];
+ if (FILENAME_CMP (this_name, filename) == 0)
{
dw2_instantiate_symtab (objfile, per_cu);
break;
{
struct dwarf2_per_cu_data *per_cu;
offset_type *vec;
+ struct quick_file_names *file_data;
dw2_setup (objfile);
+ /* index_table is NULL if OBJF_READNOW. */
if (!dwarf2_per_objfile->index_table)
return NULL;
/* 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_map_ada_symtabs (struct objfile *objfile,
- int (*wild_match) (const char *, int, const char *),
- int (*is_name_suffix) (const char *),
- void (*callback) (struct objfile *,
- struct symtab *, void *),
- const char *name, int global,
- domain_enum namespace, int wild,
- void *data)
+dw2_map_matching_symbols (const char * name, domain_enum namespace,
+ struct objfile *objfile, int global,
+ int (*callback) (struct block *,
+ struct symbol *, void *),
+ void *data, symbol_compare_ftype *match,
+ symbol_compare_ftype *ordered_compare)
{
- /* For now, we don't support Ada, so this function can't be
- reached. */
- internal_error (__FILE__, __LINE__,
- _("map_ada_symtabs called via index method"));
+ /* Currently unimplemented; used for Ada. The function can be called if the
+ current language is Ada for a non-Ada objfile using GNU index. As Ada
+ does not look for non-Ada symbols this function should just return. */
}
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;
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 (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 < dwarf2_per_objfile->index_table->index_table_slots;
- ++iter)
+ 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 (dwarf2_per_objfile->index_table->index_table[idx] == 0
- && dwarf2_per_objfile->index_table->index_table[idx + 1] == 0)
+ if (index->symbol_table[idx] == 0 && index->symbol_table[idx + 1] == 0)
continue;
- name = (dwarf2_per_objfile->index_table->constant_pool
- + dwarf2_per_objfile->index_table->index_table[idx]);
+ name = index->constant_pool + MAYBE_SWAP (index->symbol_table[idx]);
if (! (*name_matcher) (name, data))
continue;
/* The name was matched, now expand corresponding CUs that were
marked. */
- vec = (offset_type *) (dwarf2_per_objfile->index_table->constant_pool
- + dwarf2_per_objfile->index_table->index_table[idx + 1]);
+ vec = (offset_type *) (index->constant_pool
+ + MAYBE_SWAP (index->symbol_table[idx + 1]));
vec_len = MAYBE_SWAP (vec[0]);
for (vec_idx = 0; vec_idx < vec_len; ++vec_idx)
{
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);
}
}
return dw2_instantiate_symtab (objfile, data);
}
-static void
-dw2_map_symbol_names (struct objfile *objfile,
- void (*fun) (const char *, void *),
- void *data)
-{
- offset_type iter;
- dw2_setup (objfile);
-
- if (!dwarf2_per_objfile->index_table)
- return;
-
- for (iter = 0;
- iter < dwarf2_per_objfile->index_table->index_table_slots;
- ++iter)
- {
- offset_type idx = 2 * iter;
- const char *name;
- offset_type *vec, vec_len, vec_idx;
-
- if (dwarf2_per_objfile->index_table->index_table[idx] == 0
- && dwarf2_per_objfile->index_table->index_table[idx + 1] == 0)
- continue;
-
- name = (dwarf2_per_objfile->index_table->constant_pool
- + dwarf2_per_objfile->index_table->index_table[idx]);
-
- (*fun) (name, data);
- }
-}
-
static void
dw2_map_symbol_filenames (struct objfile *objfile,
void (*fun) (const char *, const char *, void *),
int i;
dw2_setup (objfile);
+
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;
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_expand_all_symtabs,
dw2_expand_symtabs_with_filename,
dw2_find_symbol_file,
- dw2_map_ada_symtabs,
+ 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;
}
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;
- memset (&cu, 0, sizeof (cu));
- cu.objfile = objfile;
- obstack_init (&cu.comp_unit_obstack);
-
+ init_one_comp_unit (&cu, objfile);
back_to_inner = make_cleanup (free_stack_comp_unit, &cu);
info_ptr = partial_read_comp_unit_head (&cu.header, info_ptr,
return info_ptr;
}
- /* Set the language we're debugging. */
- attr = dwarf2_attr (comp_unit_die, DW_AT_language, &cu);
- if (attr)
- set_cu_language (DW_UNSND (attr), &cu);
- else
- set_cu_language (language_minimal, &cu);
+ prepare_one_comp_unit (&cu, comp_unit_die);
/* 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;
{
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,
struct die_info *comp_unit_die;
struct dwarf2_cu *cu;
struct cleanup *free_abbrevs_cleanup, *free_cu_cleanup = NULL;
- struct attribute *attr;
int has_children;
struct die_reader_specs reader_specs;
int read_cu = 0;
if (this_cu->cu == NULL)
{
- cu = alloc_one_comp_unit (objfile);
+ cu = xmalloc (sizeof (*cu));
+ init_one_comp_unit (cu, objfile);
read_cu = 1;
info_ptr = read_full_die (&reader_specs, &comp_unit_die, info_ptr,
&has_children);
- /* Set the language we're debugging. */
- attr = dwarf2_attr (comp_unit_die, DW_AT_language, cu);
- if (attr)
- set_cu_language (DW_UNSND (attr), cu);
- else
- set_cu_language (language_minimal, cu);
+ prepare_one_comp_unit (cu, comp_unit_die);
/* 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;
case DW_TAG_subprogram:
add_partial_subprogram (pdi, lowpc, highpc, need_pc, cu);
break;
+ case DW_TAG_constant:
case DW_TAG_variable:
case DW_TAG_typedef:
case DW_TAG_union_type:
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:
+ {
+ struct psymbol_allocation_list *list;
+
+ if (pdi->is_external)
+ list = &objfile->global_psymbols;
+ else
+ list = &objfile->static_psymbols;
+ 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:
if (pdi->locdesc)
addr = decode_locdesc (pdi->locdesc, cu);
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:
}
}
-/* See if we can figure out if the class lives in a namespace. We do
- this by looking for a member function; its demangled name will
- contain namespace info, if there is any. */
-
-static void
-guess_structure_name (struct partial_die_info *struct_pdi,
- struct dwarf2_cu *cu)
-{
- if ((cu->language == language_cplus
- || cu->language == language_java)
- && cu->has_namespace_info == 0
- && struct_pdi->has_children)
- {
- /* NOTE: carlton/2003-10-07: Getting the info this way changes
- what template types look like, because the demangler
- frequently doesn't give the same name as the debug info. We
- could fix this by only using the demangled name to get the
- prefix (but see comment in read_structure_type). */
-
- struct partial_die_info *real_pdi;
-
- /* If this DIE (this DIE's specification, if any) has a parent, then
- we should not do this. We'll prepend the parent's fully qualified
- name when we create the partial symbol. */
-
- real_pdi = struct_pdi;
- while (real_pdi->has_specification)
- real_pdi = find_partial_die (real_pdi->spec_offset, cu);
-
- if (real_pdi->die_parent != NULL)
- return;
- }
-}
-
/* Read a partial die corresponding to an enumeration type. */
static void
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;
if (per_cu->cu == NULL)
{
- cu = alloc_one_comp_unit (objfile);
+ cu = xmalloc (sizeof (*cu));
+ init_one_comp_unit (cu, objfile);
read_cu = 1;
all objfiles needed for references have been loaded yet, and symbol
table processing isn't initialized. But we have to set the CU language,
or we won't be able to build types correctly. */
- attr = dwarf2_attr (cu->dies, DW_AT_language, cu);
- if (attr)
- set_cu_language (DW_UNSND (attr), cu);
- else
- set_cu_language (language_minimal, cu);
+ prepare_one_comp_unit (cu, cu->dies);
/* Similarly, if we do not read the producer, we can not apply
producer-specific interpretation. */
}
}
+/* Check for GCC >= 4.0. */
+
+static int
+producer_is_gcc_ge_4_0 (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 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 not compliant. */
+
+ return 0;
+ }
+ cs = &cu->producer[strlen ("GNU ")];
+ while (*cs && !isdigit (*cs))
+ cs++;
+ if (sscanf (cs, "%d.%d", &major, &minor) != 2)
+ {
+ /* Not recognized as GCC. */
+
+ return 0;
+ }
+
+ return major >= 4;
+}
+
/* 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;
+ /* 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 && producer_is_gcc_ge_4_0 (cu))
+ symtab->locations_valid = 1;
}
if (dwarf2_per_objfile->using_index)
return 1;
case DW_TAG_variable:
+ case DW_TAG_constant:
/* We only need to prefix "globally" visible variables. These include
any variable marked with DW_AT_external or any variable that
lives in a namespace. [Variables in anonymous namespaces
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);
}
else if (cu->language == language_cplus)
{
+ /* Assume that an artificial first parameter is
+ "this", but do not crash if it is not. RealView
+ marks unnamed (and thus unused) parameters as
+ artificial; there is no way to differentiate
+ the two cases. */
if (TYPE_NFIELDS (type) > 0
&& TYPE_FIELD_ARTIFICIAL (type, 0)
- && TYPE_CONST (TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (type, 0))))
+ && TYPE_CODE (TYPE_FIELD_TYPE (type, 0)) == TYPE_CODE_PTR
+ && 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)
cu->first_fn = cu->last_fn = cu->cached_fn = NULL;
}
+/* Cleanup function for read_file_scope. */
+
static void
free_cu_line_header (void *arg)
{
*name = "<unknown>";
}
+/* Process DW_TAG_compile_unit. */
+
static void
read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
{
if (attr)
cu->producer = DW_STRING (attr);
- /* We assume that we're processing GCC output. */
+ /* The XLCL doesn't generate DW_LANG_OpenCL because this attribute is not
+ standardised yet. As a workaround for the language detection we fall
+ back to the DW_AT_producer string. */
+ if (cu->producer && strstr (cu->producer, "IBM XL C for OpenCL") != NULL)
+ cu->language = language_opencl;
+
+ /* We assume that we're processing GCC output. */
processing_gcc_compilation = 2;
processing_has_namespace_info = 0;
do_cleanups (back_to);
}
-/* For TUs we want to skip the first top level sibling if it's not the
+/* Process DW_TAG_type_unit.
+ For TUs we want to skip the first top level sibling if it's not the
actual type being defined by this TU. In this case the first top
level sibling is there to provide context only. */
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;
}
{
struct symbol *arg = new_symbol (child_die, NULL, cu);
- VEC_safe_push (symbolp, template_args, arg);
+ if (arg != NULL)
+ VEC_safe_push (symbolp, template_args, arg);
}
else
process_die (child_die, cu);
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)
{
}
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;
(B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields));
B_CLRALL (TYPE_FIELD_PROTECTED_BITS (type), nfields);
- /* We don't set TYPE_FIELD_IGNORE_BITS here. The DWARF reader
- never sets any bits in that array, so leaving it NULL lets us
- save a little memory. */
+ TYPE_FIELD_IGNORE_BITS (type) =
+ (B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields));
+ B_CLRALL (TYPE_FIELD_IGNORE_BITS (type), nfields);
}
/* If the type has baseclasses, allocate and clear a bit vector for
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));
/* 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 *)
}
/* Called when we find the DIE that starts a structure or union scope
- (definition) to process all dies that define the members of the
- structure or union.
+ (definition) to create a type for the structure or union. Fill in
+ the type's name and general properties; the members will not be
+ processed until process_structure_type.
- NOTE: we need to call struct_type regardless of whether or not the
- DIE has an at_name attribute, since it might be an anonymous
+ NOTE: we need to call these functions regardless of whether or not the
+ DIE has a DW_AT_name attribute, since it might be an anonymous
structure or union. This gets the type entered into our set of
user defined types.
struct type *type;
struct attribute *attr;
char *name;
- struct cleanup *back_to;
/* If the definition of this type lives in .debug_types, read that type.
Don't follow DW_AT_specification though, that will take us back up
return set_die_type (die, type, cu);
}
- back_to = make_cleanup (null_cleanup, 0);
-
type = alloc_type (objfile);
INIT_CPLUS_SPECIFIC (type);
/* 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. */
set_descriptive_type (type, die, cu);
+ return type;
+}
+
+/* Finish creating a structure or union type, including filling in
+ its members and creating a symbol for it. */
+
+static void
+process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
+{
+ struct objfile *objfile = cu->objfile;
+ struct die_info *child_die = die->child;
+ struct type *type;
+
+ type = get_die_type (die, cu);
+ if (type == NULL)
+ type = read_structure_type (die, cu);
+
if (die->child != NULL && ! die_is_declaration (die, cu))
{
struct field_info fi;
struct die_info *child_die;
VEC (symbolp) *template_args = NULL;
+ struct cleanup *back_to = make_cleanup (null_cleanup, 0);
memset (&fi, 0, sizeof (struct field_info));
}
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)
{
struct symbol *arg = new_symbol (child_die, NULL, cu);
- VEC_safe_push (symbolp, template_args, arg);
+ if (arg != NULL)
+ VEC_safe_push (symbolp, template_args, arg);
}
child_die = sibling_die (child_die);
/* 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) :
"");
}
*dest = *src;
}
}
+
+ do_cleanups (back_to);
}
quirk_gcc_member_function_pointer (type, cu->objfile);
- do_cleanups (back_to);
- return type;
-}
-
-static void
-process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
-{
- struct die_info *child_die = die->child;
- struct type *this_type;
-
- this_type = get_die_type (die, cu);
- if (this_type == NULL)
- this_type = read_structure_type (die, cu);
-
/* NOTE: carlton/2004-03-16: GCC 3.4 (or at least one of its
snapshots) has been known to create a die giving a declaration
for a class that has, as a child, a die giving a definition for a
attribute, and a declaration attribute. */
if (dwarf2_attr (die, DW_AT_byte_size, cu) != NULL
|| !die_is_declaration (die, cu))
- new_symbol (die, this_type, cu);
+ new_symbol (die, type, cu);
}
/* Given a DW_AT_enumeration_type die, set its type. We do not
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 (attr)
make_vector_type (type);
+ /* The DIE may have DW_AT_byte_size set. For example an OpenCL
+ implementation may choose to implement triple vectors using this
+ attribute. */
+ attr = dwarf2_attr (die, DW_AT_byte_size, cu);
+ if (attr)
+ {
+ 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"));
+ }
+
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 (attr)
+ 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);
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);
}
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
{
if (cv_type)
return cv_type;
+ /* In case the const qualifier is applied to an array type, the element type
+ is so qualified, not the array type (section 6.7.3 of C99). */
+ if (TYPE_CODE (base_type) == TYPE_CODE_ARRAY)
+ {
+ struct type *el_type, *inner_array;
+
+ base_type = copy_type (base_type);
+ inner_array = base_type;
+
+ while (TYPE_CODE (TYPE_TARGET_TYPE (inner_array)) == TYPE_CODE_ARRAY)
+ {
+ TYPE_TARGET_TYPE (inner_array) =
+ copy_type (TYPE_TARGET_TYPE (inner_array));
+ inner_array = TYPE_TARGET_TYPE (inner_array);
+ }
+
+ el_type = TYPE_TARGET_TYPE (inner_array);
+ TYPE_TARGET_TYPE (inner_array) =
+ make_cv_type (1, TYPE_VOLATILE (el_type), el_type, NULL);
+
+ return set_die_type (die, base_type, cu);
+ }
+
cv_type = make_cv_type (1, TYPE_VOLATILE (base_type), base_type, 0);
return set_die_type (die, cv_type, cu);
}
}
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)
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);
static members). */
if (!load_all
&& !is_type_tag_for_partial (abbrev->tag)
+ && abbrev->tag != DW_TAG_constant
&& abbrev->tag != DW_TAG_enumerator
&& abbrev->tag != DW_TAG_subprogram
&& abbrev->tag != DW_TAG_lexical_block
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,
unit with load_all_dies set. */
if (load_all
+ || abbrev->tag == DW_TAG_constant
|| abbrev->tag == DW_TAG_subprogram
|| abbrev->tag == DW_TAG_variable
|| abbrev->tag == DW_TAG_namespace
one we see. */
if (cu->language == language_ada)
part_die->name = DW_STRING (&attr);
+ part_die->linkage_name = DW_STRING (&attr);
break;
case DW_AT_low_pc:
has_low_pc_attr = 1;
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;
practice. */
if (DW_UNSND (&attr) == DW_CC_program
&& cu->language == language_fortran)
- set_main_name (part_die->name);
+ {
+ set_main_name (part_die->name);
+
+ /* As this DIE has a static linkage the name would be difficult
+ to look up later. */
+ language_of_main = language_fortran;
+ }
break;
default:
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)
0, per_cu->cu);
do_cleanups (back_to);
- pd = find_partial_die_in_comp_unit (offset, per_cu->cu);
- }
+ pd = find_partial_die_in_comp_unit (offset, per_cu->cu);
+ }
+
+ not_found:
+
+ if (pd == NULL)
+ internal_error (__FILE__, __LINE__,
+ _("could not find partial DIE 0x%x "
+ "in cache [from module %s]\n"),
+ offset, bfd_get_filename (cu->objfile->obfd));
+ return pd;
+}
+
+/* See if we can figure out if the class lives in a namespace. We do
+ this by looking for a member function; its demangled name will
+ contain namespace info, if there is any. */
+
+static void
+guess_partial_die_structure_name (struct partial_die_info *struct_pdi,
+ struct dwarf2_cu *cu)
+{
+ /* NOTE: carlton/2003-10-07: Getting the info this way changes
+ what template types look like, because the demangler
+ frequently doesn't give the same name as the debug info. We
+ could fix this by only using the demangled name to get the
+ prefix (but see comment in read_structure_type). */
+
+ struct partial_die_info *real_pdi;
+ struct partial_die_info *child_pdi;
- not_found:
+ /* If this DIE (this DIE's specification, if any) has a parent, then
+ we should not do this. We'll prepend the parent's fully qualified
+ name when we create the partial symbol. */
- if (pd == NULL)
- internal_error (__FILE__, __LINE__,
- _("could not find partial DIE 0x%x in cache [from module %s]\n"),
- offset, bfd_get_filename (cu->objfile->obfd));
- return pd;
+ real_pdi = struct_pdi;
+ while (real_pdi->has_specification)
+ real_pdi = find_partial_die (real_pdi->spec_offset, cu);
+
+ if (real_pdi->die_parent != NULL)
+ return;
+
+ for (child_pdi = struct_pdi->die_child;
+ child_pdi != NULL;
+ child_pdi = child_pdi->die_sibling)
+ {
+ if (child_pdi->tag == DW_TAG_subprogram
+ && child_pdi->linkage_name != NULL)
+ {
+ char *actual_class_name
+ = language_class_name_from_physname (cu->language_defn,
+ child_pdi->linkage_name);
+ if (actual_class_name != NULL)
+ {
+ struct_pdi->name
+ = obsavestring (actual_class_name,
+ strlen (actual_class_name),
+ &cu->objfile->objfile_obstack);
+ xfree (actual_class_name);
+ }
+ break;
+ }
+ }
}
/* Adjust PART_DIE before generating a symbol for it. This function
fixup_partial_die (struct partial_die_info *part_die,
struct dwarf2_cu *cu)
{
+ /* Once we've fixed up a die, there's no point in doing so again.
+ This also avoids a memory leak if we were to call
+ guess_partial_die_structure_name multiple times. */
+ if (part_die->fixup_called)
+ return;
+
/* If we found a reference attribute and the DIE has no name, try
to find a name in the referred to DIE. */
}
/* Set default names for some unnamed DIEs. */
- if (part_die->name == NULL && (part_die->tag == DW_TAG_structure_type
- || part_die->tag == DW_TAG_class_type))
- part_die->name = "(anonymous class)";
if (part_die->name == NULL && part_die->tag == DW_TAG_namespace)
part_die->name = "(anonymous namespace)";
- if (part_die->tag == DW_TAG_structure_type
- || part_die->tag == DW_TAG_class_type
- || part_die->tag == DW_TAG_union_type)
- guess_structure_name (part_die, cu);
+ /* If there is no parent die to provide a namespace, and there are
+ children, see if we can determine the namespace from their linkage
+ name.
+ NOTE: We need to do this even if cu->has_namespace_info != 0.
+ gcc-4.5 -gdwarf-4 can drop the enclosing namespace. */
+ if (cu->language == language_cplus
+ && dwarf2_per_objfile->types.asection != NULL
+ && part_die->die_parent == NULL
+ && part_die->has_children
+ && (part_die->tag == DW_TAG_class_type
+ || part_die->tag == DW_TAG_structure_type
+ || 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;
}
/* Read an attribute value described by an attribute form. */
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);
}
/* Free the line_header structure *LH, and any arrays and strings it
- refers to. */
+ refers to.
+ NOTE: This is also used as a "cleanup" function. */
+
static void
free_line_header (struct line_header *lh)
{
xfree (lh);
}
-
/* Add an entry to LH's include directory table. */
+
static void
add_include_dir (struct line_header *lh, char *include_dir)
{
lh->include_dirs[lh->num_include_dirs++] = include_dir;
}
-
/* Add an entry to LH's file name table. */
+
static void
add_file_name (struct line_header *lh,
char *name,
fe->symtab = NULL;
}
-
/* Read the statement program header starting at OFFSET in
.debug_line, according to the endianness of ABFD. Return a pointer
to a struct line_header, allocated using xmalloc.
NOTE: the strings in the include directory and file name tables of
the returned object point into debug_line_buffer, and must not be
freed. */
+
static struct line_header *
dwarf_decode_line_header (unsigned int offset, bfd *abfd,
struct dwarf2_cu *cu)
{
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;
char *include_name = fe.name;
char *include_name_to_compare = include_name;
char *dir_name = NULL;
- char *pst_filename;
+ const char *pst_filename;
+ char *copied_name = NULL;
int file_is_pst;
if (fe.dir_index)
pst_filename = pst->filename;
if (!IS_ABSOLUTE_PATH (pst_filename) && pst->dirname != NULL)
{
- pst_filename = concat (pst->dirname, SLASH_STRING,
- pst_filename, (char *)NULL);
+ copied_name = concat (pst->dirname, SLASH_STRING,
+ pst_filename, (char *)NULL);
+ pst_filename = copied_name;
}
- file_is_pst = strcmp (include_name_to_compare, pst_filename) == 0;
+ file_is_pst = FILENAME_CMP (include_name_to_compare, pst_filename) == 0;
if (include_name_to_compare != include_name)
xfree (include_name_to_compare);
- if (pst_filename != pst->filename)
- xfree (pst_filename);
+ if (copied_name != NULL)
+ xfree (copied_name);
if (file_is_pst)
return NULL;
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.
A good testcase for this is mb-inline.exp. */
static void
-dwarf_decode_lines (struct line_header *lh, char *comp_dir, bfd *abfd,
+dwarf_decode_lines (struct line_header *lh, const char *comp_dir, bfd *abfd,
struct dwarf2_cu *cu, struct partial_symtab *pst)
{
gdb_byte *line_ptr, *extended_end;
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, char *dirname, 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_template_value_param:
suppress_add = 1;
/* Fall through. */
+ 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;
&& (cu->language == language_cplus
|| cu->language == language_java)
? &global_symbols : cu->list_in_scope);
- }
- /* The semantics of C++ state that "struct foo { ... }" also
- defines a typedef for "foo". A Java class declaration also
- defines a typedef for the class. */
- if (cu->language == language_cplus
- || cu->language == language_java
- || cu->language == language_ada)
- {
- /* The symbol's name is already allocated along with
- this objfile, so we don't need to duplicate it for
- the type. */
- if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0)
- TYPE_NAME (SYMBOL_TYPE (sym)) = SYMBOL_SEARCH_NAME (sym);
+ /* The semantics of C++ state that "struct foo {
+ ... }" also defines a typedef for "foo". A Java
+ class declaration also defines a typedef for the
+ class. */
+ if (cu->language == language_cplus
+ || cu->language == language_java
+ || cu->language == language_ada)
+ {
+ /* The symbol's name is already allocated along
+ with this objfile, so we don't need to
+ duplicate it for the type. */
+ if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0)
+ TYPE_NAME (SYMBOL_TYPE (sym)) = SYMBOL_SEARCH_NAME (sym);
+ }
}
}
break;
/* 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;
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;
}
return this_type;
}
+/* See if we can figure out if the class lives in a namespace. We do
+ this by looking for a member function; its demangled name will
+ contain namespace info, if there is any.
+ Return the computed name or NULL.
+ Space for the result is allocated on the objfile's obstack.
+ This is the full-die version of guess_partial_die_structure_name.
+ In this case we know DIE has no useful parent. */
+
+static char *
+guess_full_die_structure_name (struct die_info *die, struct dwarf2_cu *cu)
+{
+ struct die_info *spec_die;
+ struct dwarf2_cu *spec_cu;
+ struct die_info *child;
+
+ spec_cu = cu;
+ spec_die = die_specification (die, &spec_cu);
+ if (spec_die != NULL)
+ {
+ die = spec_die;
+ cu = spec_cu;
+ }
+
+ for (child = die->child;
+ child != NULL;
+ child = child->sibling)
+ {
+ if (child->tag == DW_TAG_subprogram)
+ {
+ struct attribute *attr;
+
+ attr = dwarf2_attr (child, DW_AT_linkage_name, cu);
+ if (attr == NULL)
+ attr = dwarf2_attr (child, DW_AT_MIPS_linkage_name, cu);
+ if (attr != NULL)
+ {
+ char *actual_name
+ = language_class_name_from_physname (cu->language_defn,
+ DW_STRING (attr));
+ char *name = NULL;
+
+ if (actual_name != NULL)
+ {
+ char *die_name = dwarf2_name (die, cu);
+
+ if (die_name != NULL
+ && strcmp (die_name, actual_name) != 0)
+ {
+ /* Strip off the class name from the full name.
+ We want the prefix. */
+ int die_name_len = strlen (die_name);
+ int actual_name_len = strlen (actual_name);
+
+ /* Test for '::' as a sanity check. */
+ if (actual_name_len > die_name_len + 2
+ && actual_name[actual_name_len
+ - die_name_len - 1] == ':')
+ name =
+ obsavestring (actual_name,
+ actual_name_len - die_name_len - 2,
+ &cu->objfile->objfile_obstack);
+ }
+ }
+ xfree (actual_name);
+ return name;
+ }
+ }
+ }
+
+ return NULL;
+}
+
/* Return the name of the namespace/class that DIE is defined within,
or "" if we can't tell. The caller should not xfree the result.
members; no typedefs, no member functions, et cetera.
So it does not need a prefix. */
return "";
+ case DW_TAG_compile_unit:
+ /* gcc-4.5 -gdwarf-4 can drop the enclosing namespace. Cope. */
+ if (cu->language == language_cplus
+ && dwarf2_per_objfile->types.asection != NULL
+ && die->child != NULL
+ && (die->tag == DW_TAG_class_type
+ || die->tag == DW_TAG_structure_type
+ || die->tag == DW_TAG_union_type))
+ {
+ char *name = guess_full_die_structure_name (die, cu);
+ if (name != NULL)
+ return name;
+ }
+ return "";
default:
return determine_prefix (parent, cu);
}
}
-/* 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_push_tls_address";
case DW_OP_GNU_uninit:
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);
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;
}
struct dwarf2_locexpr_baton
dwarf2_fetch_die_location_block (unsigned int offset,
- struct dwarf2_per_cu_data *per_cu)
+ struct dwarf2_per_cu_data *per_cu,
+ CORE_ADDR (*get_frame_pc) (void *baton),
+ void *baton)
{
struct dwarf2_cu *cu = per_cu->cu;
struct die_info *die;
struct attribute *attr;
struct dwarf2_locexpr_baton retval;
+ dw2_setup (per_cu->objfile);
+
die = follow_die_offset (offset, &cu);
if (!die)
error (_("Dwarf Error: Cannot find DIE at 0x%x referenced in module %s"),
retval.data = NULL;
retval.size = 0;
}
+ else if (attr_form_is_section_offset (attr))
+ {
+ struct dwarf2_loclist_baton loclist_baton;
+ CORE_ADDR pc = (*get_frame_pc) (baton);
+ size_t size;
+
+ fill_in_loclist_baton (cu, &loclist_baton, attr);
+
+ retval.data = dwarf2_find_location_expression (&loclist_baton,
+ &size, pc);
+ retval.size = size;
+ }
else
{
if (!attr_form_is_block (attr))
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);
}
struct dwarf2_cu *cu;
ULONGEST signature;
struct cleanup *back_to, *free_cu_cleanup;
- struct attribute *attr;
dwarf2_read_section (objfile, &dwarf2_per_objfile->types);
types_ptr = dwarf2_per_objfile->types.buffer + type_sig->offset;
gdb_assert (type_sig->per_cu.cu == NULL);
- cu = xmalloc (sizeof (struct dwarf2_cu));
- memset (cu, 0, sizeof (struct dwarf2_cu));
- obstack_init (&cu->comp_unit_obstack);
- cu->objfile = objfile;
+ cu = xmalloc (sizeof (*cu));
+ init_one_comp_unit (cu, objfile);
+
type_sig->per_cu.cu = cu;
cu->per_cu = &type_sig->per_cu;
all objfiles needed for references have been loaded yet, and symbol
table processing isn't initialized. But we have to set the CU language,
or we won't be able to build types correctly. */
- attr = dwarf2_attr (cu->dies, DW_AT_language, cu);
- if (attr)
- set_cu_language (DW_UNSND (attr), cu);
- else
- set_cu_language (language_minimal, cu);
+ prepare_one_comp_unit (cu, cu->dies);
do_cleanups (back_to);
callers will only want a very basic result and this can become a
complaint.
- Note that stack[0] is unused except as a default error return.
- Note that stack overflow is not yet handled. */
+ Note that stack[0] is unused except as a default error return. */
static CORE_ADDR
decode_locdesc (struct dwarf_block *blk, struct dwarf2_cu *cu)
i = 0;
stacki = 0;
stack[stacki] = 0;
+ stack[++stacki] = 0;
while (i < size)
{
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]);
}
+
+ /* Enforce maximum stack depth of SIZE-1 to avoid writing
+ outside of the allocated space. Also enforce minimum>0. */
+ if (stacki >= ARRAY_SIZE (stack) - 1)
+ {
+ complaint (&symfile_complaints,
+ _("location description stack overflow"));
+ return 0;
+ }
+
+ if (stacki <= 0)
+ {
+ complaint (&symfile_complaints,
+ _("location description stack underflow"));
+ return 0;
+ }
}
return (stack[stacki]);
}
\f
/* Macro support. */
-
/* Return the full name of file number I in *LH's file name table.
Use COMP_DIR as the name of the current directory of the
compilation. The result is allocated using xmalloc; the caller is
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)
{
}
}
+/* A helper function that fills in a dwarf2_loclist_baton. */
+
+static void
+fill_in_loclist_baton (struct dwarf2_cu *cu,
+ struct dwarf2_loclist_baton *baton,
+ struct attribute *attr)
+{
+ dwarf2_read_section (dwarf2_per_objfile->objfile,
+ &dwarf2_per_objfile->loc);
+
+ baton->per_cu = cu->per_cu;
+ gdb_assert (baton->per_cu);
+ /* We don't know how long the location list is, but make sure we
+ don't run off the edge of the section. */
+ baton->size = dwarf2_per_objfile->loc.size - DW_UNSND (attr);
+ baton->data = dwarf2_per_objfile->loc.buffer + DW_UNSND (attr);
+ baton->base_address = cu->base_address;
+}
+
static void
dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym,
struct dwarf2_cu *cu)
/* ".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;
baton = obstack_alloc (&cu->objfile->objfile_obstack,
sizeof (struct dwarf2_loclist_baton));
- baton->per_cu = cu->per_cu;
- gdb_assert (baton->per_cu);
- dwarf2_read_section (dwarf2_per_objfile->objfile,
- &dwarf2_per_objfile->loc);
+ fill_in_loclist_baton (cu, baton, attr);
- /* We don't know how long the location list is, but make sure we
- don't run off the edge of the section. */
- baton->size = dwarf2_per_objfile->loc.size - DW_UNSND (attr);
- baton->data = dwarf2_per_objfile->loc.buffer + DW_UNSND (attr);
- baton->base_address = cu->base_address;
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;
return this_cu;
}
-/* Malloc space for a dwarf2_cu for OBJFILE and initialize it. */
+/* Initialize dwarf2_cu CU for OBJFILE in a pre-allocated space. */
-static struct dwarf2_cu *
-alloc_one_comp_unit (struct objfile *objfile)
+static void
+init_one_comp_unit (struct dwarf2_cu *cu, struct objfile *objfile)
{
- struct dwarf2_cu *cu = xcalloc (1, sizeof (struct dwarf2_cu));
+ memset (cu, 0, sizeof (*cu));
cu->objfile = objfile;
obstack_init (&cu->comp_unit_obstack);
- return cu;
+}
+
+/* Initialize basic fields of dwarf_cu CU according to DIE COMP_UNIT_DIE. */
+
+static void
+prepare_one_comp_unit (struct dwarf2_cu *cu, struct die_info *comp_unit_die)
+{
+ struct attribute *attr;
+
+ /* Set the language we're debugging. */
+ attr = dwarf2_attr (comp_unit_die, DW_AT_language, cu);
+ if (attr)
+ set_cu_language (DW_UNSND (attr), cu);
+ else
+ {
+ 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. */
}
}
\f
+/* The "save gdb-index" command. */
/* The contents of the hash table we create when building the string
table. */
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. */
+
static int
eq_strtab_entry (const void *a, const void *b)
{
}
/* Create a strtab_entry hash table. */
+
static htab_t
create_strtab (void)
{
/* Add a string to the constant pool. Return the string's offset in
host order. */
+
static offset_type
add_string (htab_t table, struct obstack *cpool, const char *str)
{
};
/* Hash function for a symtab_index_entry. */
+
static hashval_t
hash_symtab_entry (const void *e)
{
}
/* Equality function for a symtab_index_entry. */
+
static int
eq_symtab_entry (const void *a, const void *b)
{
}
/* Destroy a symtab_index_entry. */
+
static void
delete_symtab_entry (void *p)
{
}
/* Create a hash table holding symtab_index_entry objects. */
+
static htab_t
-create_index_table (void)
+create_symbol_hash_table (void)
{
return htab_create_alloc (100, hash_symtab_entry, eq_symtab_entry,
delete_symtab_entry, xcalloc, xfree);
}
/* Create a new mapped symtab object. */
+
static struct mapped_symtab *
create_mapped_symtab (void)
{
}
/* Destroy a mapped_symtab. */
+
static void
cleanup_mapped_symtab (void *p)
{
}
/* 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;
}
/* Expand SYMTAB's hash table. */
+
static void
hash_expand (struct mapped_symtab *symtab)
{
/* Add an entry to SYMTAB. NAME is the name of the symbol. CU_INDEX
is the index of the CU in which the symbol appears. */
+
static void
add_index_entry (struct mapped_symtab *symtab, const char *name,
offset_type cu_index)
/* 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);
}
/* Add a vector of indices to the constant pool. */
+
static offset_type
-add_indices_to_cpool (htab_t index_table, struct obstack *cpool,
+add_indices_to_cpool (htab_t symbol_hash_table, struct obstack *cpool,
struct symtab_index_entry *entry)
{
void **slot;
- slot = htab_find_slot (index_table, entry, INSERT);
+ slot = htab_find_slot (symbol_hash_table, entry, INSERT);
if (!*slot)
{
offset_type len = VEC_length (offset_type, entry->cu_indices);
/* Write the mapped hash table SYMTAB to the obstack OUTPUT, with
constant pool entries going into the obstack CPOOL. */
+
static void
write_hash_table (struct mapped_symtab *symtab,
struct obstack *output, struct obstack *cpool)
{
offset_type i;
- htab_t index_table;
+ htab_t symbol_hash_table;
htab_t str_table;
- index_table = create_index_table ();
+ symbol_hash_table = create_symbol_hash_table ();
str_table = create_strtab ();
+
/* We add all the index vectors to the constant pool first, to
ensure alignment is ok. */
for (i = 0; i < symtab->size; ++i)
{
if (symtab->data[i])
- add_indices_to_cpool (index_table, cpool, symtab->data[i]);
+ add_indices_to_cpool (symbol_hash_table, cpool, symtab->data[i]);
}
/* Now write out the hash table. */
}
htab_delete (str_table);
- htab_delete (index_table);
+ htab_delete (symbol_hash_table);
+}
+
+/* Struct to map psymtab to CU index in the index file. */
+struct psymtab_cu_index_map
+{
+ struct partial_symtab *psymtab;
+ unsigned int cu_index;
+};
+
+static hashval_t
+hash_psymtab_cu_index (const void *item)
+{
+ const struct psymtab_cu_index_map *map = item;
+
+ return htab_hash_pointer (map->psymtab);
+}
+
+static int
+eq_psymtab_cu_index (const void *item_lhs, const void *item_rhs)
+{
+ const struct psymtab_cu_index_map *lhs = item_lhs;
+ const struct psymtab_cu_index_map *rhs = item_rhs;
+
+ return lhs->psymtab == rhs->psymtab;
}
-/* Write an address entry to ADDR_OBSTACK. The addresses are taken
- from PST; CU_INDEX is the index of the CU in the vector of all
- CUs. */
+/* Helper struct for building the address table. */
+struct addrmap_index_data
+{
+ struct objfile *objfile;
+ struct obstack *addr_obstack;
+ htab_t cu_index_htab;
+
+ /* Non-zero if the previous_* fields are valid.
+ We can't write an entry until we see the next entry (since it is only then
+ that we know the end of the entry). */
+ 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. */
+ CORE_ADDR previous_cu_start;
+};
+
+/* Write an address entry to OBSTACK. */
+
static void
-add_address_entry (struct objfile *objfile,
- struct obstack *addr_obstack, struct partial_symtab *pst,
- unsigned int cu_index)
+add_address_entry (struct objfile *objfile, struct obstack *obstack,
+ CORE_ADDR start, CORE_ADDR end, unsigned int cu_index)
{
- offset_type offset;
+ offset_type cu_index_to_write;
char addr[8];
CORE_ADDR baseaddr;
- /* Don't bother recording empty ranges. */
- if (pst->textlow == pst->texthigh)
- return;
-
baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
- store_unsigned_integer (addr, 8, BFD_ENDIAN_LITTLE, pst->textlow - baseaddr);
- obstack_grow (addr_obstack, addr, 8);
- store_unsigned_integer (addr, 8, BFD_ENDIAN_LITTLE, pst->texthigh - baseaddr);
- obstack_grow (addr_obstack, addr, 8);
- offset = MAYBE_SWAP (cu_index);
- obstack_grow (addr_obstack, &offset, sizeof (offset_type));
+ store_unsigned_integer (addr, 8, BFD_ENDIAN_LITTLE, start - baseaddr);
+ obstack_grow (obstack, addr, 8);
+ store_unsigned_integer (addr, 8, BFD_ENDIAN_LITTLE, end - baseaddr);
+ obstack_grow (obstack, addr, 8);
+ cu_index_to_write = MAYBE_SWAP (cu_index);
+ obstack_grow (obstack, &cu_index_to_write, sizeof (offset_type));
+}
+
+/* Worker function for traversing an addrmap to build the address table. */
+
+static int
+add_address_entry_worker (void *datap, CORE_ADDR start_addr, void *obj)
+{
+ struct addrmap_index_data *data = datap;
+ struct partial_symtab *pst = obj;
+ offset_type cu_index;
+ void **slot;
+
+ if (data->previous_valid)
+ add_address_entry (data->objfile, data->addr_obstack,
+ data->previous_cu_start, start_addr,
+ data->previous_cu_index);
+
+ data->previous_cu_start = start_addr;
+ if (pst != NULL)
+ {
+ struct psymtab_cu_index_map find_map, *map;
+ find_map.psymtab = pst;
+ map = htab_find (data->cu_index_htab, &find_map);
+ gdb_assert (map != NULL);
+ data->previous_cu_index = map->cu_index;
+ data->previous_valid = 1;
+ }
+ else
+ data->previous_valid = 0;
+
+ return 0;
+}
+
+/* Write OBJFILE's address map to OBSTACK.
+ CU_INDEX_HTAB is used to map addrmap entries to their CU indices
+ in the index file. */
+
+static void
+write_address_map (struct objfile *objfile, struct obstack *obstack,
+ htab_t cu_index_htab)
+{
+ struct addrmap_index_data addrmap_index_data;
+
+ /* When writing the address table, we have to cope with the fact that
+ the addrmap iterator only provides the start of a region; we have to
+ wait until the next invocation to get the start of the next region. */
+
+ addrmap_index_data.objfile = objfile;
+ addrmap_index_data.addr_obstack = obstack;
+ addrmap_index_data.cu_index_htab = cu_index_htab;
+ addrmap_index_data.previous_valid = 0;
+
+ addrmap_foreach (objfile->psymtabs_addrmap, add_address_entry_worker,
+ &addrmap_index_data);
+
+ /* It's highly unlikely the last entry (end address = 0xff...ff)
+ is valid, but we should still handle it.
+ The end address is recorded as the start of the next region, but that
+ doesn't work here. To cope we pass 0xff...ff, this is a rare situation
+ anyway. */
+ if (addrmap_index_data.previous_valid)
+ add_address_entry (objfile, obstack,
+ addrmap_index_data.previous_cu_start, (CORE_ADDR) -1,
+ addrmap_index_data.previous_cu_index);
}
/* Add a list of partial symbols to SYMTAB. */
+
static void
write_psymbols (struct mapped_symtab *symtab,
+ htab_t psyms_seen,
struct partial_symbol **psymp,
int count,
- offset_type cu_index)
+ offset_type cu_index,
+ int is_static)
{
for (; count-- > 0; ++psymp)
{
+ void **slot, *lookup;
+
if (SYMBOL_LANGUAGE (*psymp) == language_ada)
error (_("Ada is not currently supported by the index"));
- add_index_entry (symtab, SYMBOL_NATURAL_NAME (*psymp), cu_index);
+
+ /* We only want to add a given psymbol once. However, we also
+ want to account for whether it is global or static. So, we
+ may add it twice, using slightly different values. */
+ if (is_static)
+ {
+ uintptr_t val = 1 | (uintptr_t) *psymp;
+
+ lookup = (void *) val;
+ }
+ else
+ lookup = *psymp;
+
+ /* Only add a given psymbol once. */
+ slot = htab_find_slot (psyms_seen, lookup, INSERT);
+ if (!*slot)
+ {
+ *slot = lookup;
+ add_index_entry (symtab, SYMBOL_NATURAL_NAME (*psymp), cu_index);
+ }
}
}
/* Write the contents of an ("unfinished") obstack to FILE. Throw an
exception if there is an error. */
+
static void
write_obstack (FILE *file, struct obstack *obstack)
{
}
/* Unlink a file if the argument is not NULL. */
+
static void
unlink_if_set (void *p)
{
struct objfile *objfile;
struct mapped_symtab *symtab;
struct obstack *types_list;
+ htab_t psyms_seen;
int cu_index;
};
/* A helper function that writes a single signatured_type to an
obstack. */
+
static int
write_one_signatured_type (void **slot, void *d)
{
gdb_byte val[8];
write_psymbols (info->symtab,
- info->objfile->global_psymbols.list + psymtab->globals_offset,
- psymtab->n_global_syms, info->cu_index);
+ info->psyms_seen,
+ info->objfile->global_psymbols.list
+ + psymtab->globals_offset,
+ psymtab->n_global_syms, info->cu_index,
+ 0);
write_psymbols (info->symtab,
- info->objfile->static_psymbols.list + psymtab->statics_offset,
- psymtab->n_static_syms, info->cu_index);
+ info->psyms_seen,
+ 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);
obstack_grow (info->types_list, val, 8);
return 1;
}
+/* A cleanup function for an htab_t. */
+
+static void
+cleanup_htab (void *arg)
+{
+ htab_delete (arg);
+}
+
/* Create an index file for OBJFILE in the directory DIR. */
+
static void
write_psymtabs_to_index (struct objfile *objfile, const char *dir)
{
offset_type val, size_of_contents, total_len;
struct stat st;
char buf[8];
+ htab_t psyms_seen;
+ 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"));
if (stat (objfile->name, &st) < 0)
- perror_with_name (_("Could not stat"));
+ perror_with_name (objfile->name);
filename = concat (dir, SLASH_STRING, lbasename (objfile->name),
INDEX_SUFFIX, (char *) NULL);
obstack_init (&types_cu_list);
make_cleanup_obstack_free (&types_cu_list);
- /* The list is already sorted, so we don't need to do additional
+ psyms_seen = htab_create_alloc (100, htab_hash_pointer, htab_eq_pointer,
+ NULL, xcalloc, xfree);
+ make_cleanup (cleanup_htab, psyms_seen);
+
+ /* While we're scanning CU's create a table that maps a psymtab pointer
+ (which is what addrmap records) to its index (which is what is recorded
+ in the index file). This will later be needed to write the address
+ table. */
+ cu_index_htab = htab_create_alloc (100,
+ hash_psymtab_cu_index,
+ eq_psymtab_cu_index,
+ NULL, xcalloc, xfree);
+ make_cleanup (cleanup_htab, cu_index_htab);
+ psymtab_cu_index_map = (struct psymtab_cu_index_map *)
+ xmalloc (sizeof (struct psymtab_cu_index_map)
+ * dwarf2_per_objfile->n_comp_units);
+ make_cleanup (xfree, psymtab_cu_index_map);
+
+ /* The CU list is already sorted, so we don't need to do additional
work here. Also, the debug_types entries do not appear in
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;
+ void **slot;
write_psymbols (symtab,
+ psyms_seen,
objfile->global_psymbols.list + psymtab->globals_offset,
- psymtab->n_global_syms, i);
+ psymtab->n_global_syms, i,
+ 0);
write_psymbols (symtab,
+ psyms_seen,
objfile->static_psymbols.list + psymtab->statics_offset,
- psymtab->n_static_syms, i);
+ psymtab->n_static_syms, i,
+ 1);
- add_address_entry (objfile, &addr_obstack, psymtab, i);
+ map = &psymtab_cu_index_map[i];
+ map->psymtab = psymtab;
+ map->cu_index = i;
+ slot = htab_find_slot (cu_index_htab, map, INSERT);
+ gdb_assert (slot != NULL);
+ gdb_assert (*slot == NULL);
+ *slot = map;
store_unsigned_integer (val, 8, BFD_ENDIAN_LITTLE, per_cu->offset);
obstack_grow (&cu_list, val, 8);
obstack_grow (&cu_list, val, 8);
}
+ /* Dump the address map. */
+ write_address_map (objfile, &addr_obstack, cu_index_htab);
+
/* Write out the .debug_type entries, if any. */
if (dwarf2_per_objfile->signatured_types)
{
sig_data.objfile = objfile;
sig_data.symtab = symtab;
sig_data.types_list = &types_cu_list;
+ sig_data.psyms_seen = psyms_seen;
sig_data.cu_index = dwarf2_per_objfile->n_comp_units;
htab_traverse_noresize (dwarf2_per_objfile->signatured_types,
write_one_signatured_type, &sig_data);
total_len = size_of_contents;
/* The version number. */
- val = MAYBE_SWAP (2);
+ 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 1 or 2. The differences are
- noted below. Version 1 did not account for .debug_types sections;
- the presence of a .debug_types section invalidates any version 1
- index that may exist.
- [1] The offset, from the start of the file, of the CU list.
- [1.5] In version 2, the offset, from the start of the file, of the
- types CU list. This offset does not appear in version 1. Note
- that this can be empty, in which case this offset will be equal to
- the next offset.
- [2] The offset, from the start of the file, of the address section.
- [3] The offset, from the start of the file, of the symbol table.
- [4] 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.
-
- 2.5 The types CU list. This does not appear in a version 1 index.
- 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.
-
- 3. 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.
- [2] The CU index. This is an offset_type value.
-
- 4. 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.
-
- 5. 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);
}
&setdebuglist, &showdebuglist);
c = add_cmd ("gdb-index", class_files, save_gdb_index_command,
- _("Save a .gdb-index file"),
+ _("\
+Save a gdb-index file.\n\
+Usage: save gdb-index DIRECTORY"),
&save_cmdlist);
set_cmd_completer (c, filename_completer);
}