/* DWARF 2 debugging format support for GDB.
- Copyright (C) 1994-2014 Free Software Foundation, Inc.
+ Copyright (C) 1994-2015 Free Software Foundation, Inc.
Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology,
Inc. with support from Florida State University (under contract
#include "typeprint.h"
#include "jv-lang.h"
#include "psympriv.h"
-#include "exceptions.h"
#include <sys/stat.h>
#include "completer.h"
#include "vec.h"
#include "build-id.h"
#include <fcntl.h>
-#include <string.h>
-#include "gdb_assert.h"
#include <sys/types.h>
typedef struct symbol *symbolp;
/* When == 1, print basic high level tracing messages.
When > 1, be more verbose.
- This is in contrast to the low level DIE reading of dwarf2_die_debug. */
-static unsigned int dwarf2_read_debug = 0;
+ This is in contrast to the low level DIE reading of dwarf_die_debug. */
+static unsigned int dwarf_read_debug = 0;
/* When non-zero, dump DIEs after they are read in. */
-static unsigned int dwarf2_die_debug = 0;
+static unsigned int dwarf_die_debug = 0;
+
+/* When non-zero, dump line number entries as they are read in. */
+static unsigned int dwarf_line_debug = 0;
/* When non-zero, cross-check physname against demangler. */
static int check_physname = 0;
typedef struct dwarf2_per_cu_data *dwarf2_per_cu_ptr;
DEF_VEC_P (dwarf2_per_cu_ptr);
+struct tu_stats
+{
+ int nr_uniq_abbrev_tables;
+ int nr_symtabs;
+ int nr_symtab_sharers;
+ int nr_stmt_less_type_units;
+ int nr_all_type_units_reallocs;
+};
+
/* Collection of data recorded per objfile.
This hangs off of dwarf2_objfile_data_key. */
/* The number of .debug_types-related CUs. */
int n_type_units;
+ /* The number of elements allocated in all_type_units.
+ If there are skeleton-less TUs, we add them to all_type_units lazily. */
+ int n_allocated_type_units;
+
/* The .debug_types-related CUs (TUs).
This is stored in malloc space because we may realloc it. */
struct signatured_type **all_type_units;
- /* The number of entries in all_type_unit_groups. */
- int n_type_unit_groups;
-
- /* Table of type unit groups.
- This exists to make it easy to iterate over all CUs and TU groups. */
- struct type_unit_group **all_type_unit_groups;
-
/* Table of struct type_unit_group objects.
The hash key is the DW_AT_stmt_list value. */
htab_t type_unit_groups;
/* Type unit statistics, to see how well the scaling improvements
are doing. */
- struct tu_stats
- {
- int nr_uniq_abbrev_tables;
- int nr_symtabs;
- int nr_symtab_sharers;
- int nr_stmt_less_type_units;
- } tu_stats;
+ struct tu_stats tu_stats;
/* A chain of compilation units that are currently read in, so that
they can be freed later. */
/* The CUs we recently read. */
VEC (dwarf2_per_cu_ptr) *just_read_cus;
+
+ /* Table containing line_header indexed by offset and offset_in_dwz. */
+ htab_t line_header_hash;
};
static struct dwarf2_per_objfile *dwarf2_per_objfile;
/* The DW_AT_addr_base attribute if present, zero otherwise
(zero is a valid value though).
- Note this value comes from the stub CU/TU's DIE. */
+ Note this value comes from the Fission stub CU/TU's DIE. */
ULONGEST addr_base;
/* The DW_AT_ranges_base attribute if present, zero otherwise
(zero is a valid value though).
- Note this value comes from the stub CU/TU's DIE.
+ Note this value comes from the Fission stub CU/TU's DIE.
Also note that the value is zero in the non-DWO case so this value can
be used without needing to know whether DWO files are in use or not.
N.B. This does not apply to DW_AT_ranges appearing in
However we can enter this file with just a "per_cu" handle. */
struct objfile *objfile;
- /* When using partial symbol tables, the 'psymtab' field is active.
- Otherwise the 'quick' field is active. */
+ /* When dwarf2_per_objfile->using_index is true, the 'quick' field
+ is active. Otherwise, the 'psymtab' field is active. */
union
{
/* The partial symbol table associated with this compilation unit,
and is deleted afterwards and not used again. */
VEC (sig_type_ptr) *tus;
- /* The primary symtab.
+ /* The compunit symtab.
Type units in a group needn't all be defined in the same source file,
- so we create an essentially anonymous symtab as the primary symtab. */
- struct symtab *primary_symtab;
+ so we create an essentially anonymous symtab as the compunit symtab. */
+ struct compunit_symtab *compunit_symtab;
/* The data used to construct the hash key. */
struct stmt_list_hash hash;
int has_children,
void *data);
+struct file_entry
+{
+ const char *name;
+ unsigned int dir_index;
+ unsigned int mod_time;
+ unsigned int length;
+ /* Non-zero if referenced by the Line Number Program. */
+ int included_p;
+ /* The associated symbol table, if any. */
+ struct symtab *symtab;
+};
+
/* The line number information for a compilation unit (found in the
.debug_line section) begins with a "statement program header",
which contains the following information. */
struct line_header
{
+ /* Offset of line number information in .debug_line section. */
+ sect_offset offset;
+
+ /* OFFSET is for struct dwz_file associated with dwarf2_per_objfile. */
+ unsigned offset_in_dwz : 1;
+
unsigned int total_length;
unsigned short version;
unsigned int header_length;
with xmalloc; instead, they are pointers into debug_line_buffer.
Don't try to free them directly. */
unsigned int num_file_names, file_names_size;
- struct file_entry
- {
- const char *name;
- unsigned int dir_index;
- unsigned int mod_time;
- unsigned int length;
- int included_p; /* Non-zero if referenced by the Line Number Program. */
- struct symtab *symtab; /* The associated symbol table, if any. */
- } *file_names;
+ struct file_entry *file_names;
/* The start and end of the statement program following this
header. These point into dwarf2_per_objfile->line_buffer. */
/* Flag set if the DIE has a byte_size attribute. */
unsigned int has_byte_size : 1;
+ /* Flag set if the DIE has a DW_AT_const_value attribute. */
+ unsigned int has_const_value : 1;
+
/* Flag set if any of the DIE's children are template arguments. */
unsigned int has_template_arguments : 1;
type derived from this DIE. */
unsigned char building_fullname : 1;
+ /* True if this die is in process. PR 16581. */
+ unsigned char in_process : 1;
+
/* Abbrev number */
unsigned int abbrev;
and friends. */
static int bits_per_byte = 8;
+struct nextfield
+{
+ struct nextfield *next;
+ int accessibility;
+ int virtuality;
+ struct field field;
+};
+
+struct nextfnfield
+{
+ struct nextfnfield *next;
+ struct fn_field fnfield;
+};
+
+struct fnfieldlist
+{
+ const char *name;
+ int length;
+ struct nextfnfield *head;
+};
+
+struct typedef_field_list
+{
+ struct typedef_field field;
+ struct typedef_field_list *next;
+};
+
/* The routines that read and process dies for a C struct or C++ class
pass lists of data member fields and lists of member function fields
in an instance of a field_info structure, as defined below. */
struct field_info
{
/* List of data member and baseclasses fields. */
- struct nextfield
- {
- struct nextfield *next;
- int accessibility;
- int virtuality;
- struct field field;
- }
- *fields, *baseclasses;
+ struct nextfield *fields, *baseclasses;
/* Number of fields (including baseclasses). */
int nfields;
/* Member function fields array, entries are allocated in the order they
are encountered in the object file. */
- struct nextfnfield
- {
- struct nextfnfield *next;
- struct fn_field fnfield;
- }
- *fnfields;
+ struct nextfnfield *fnfields;
/* Member function fieldlist array, contains name of possibly overloaded
member function, number of overloaded member functions and a pointer
to the head of the member function field chain. */
- struct fnfieldlist
- {
- const char *name;
- int length;
- struct nextfnfield *head;
- }
- *fnfieldlists;
+ struct fnfieldlist *fnfieldlists;
/* Number of entries in the fnfieldlists array. */
int nfnfields;
/* typedefs defined inside this class. TYPEDEF_FIELD_LIST contains head of
a NULL terminated list of TYPEDEF_FIELD_LIST_COUNT elements. */
- struct typedef_field_list
- {
- struct typedef_field field;
- struct typedef_field_list *next;
- }
- *typedef_field_list;
+ struct typedef_field_list *typedef_field_list;
unsigned typedef_field_list_count;
};
compilation units. Set this to zero to disable caching. Cache
sizes of up to at least twenty will improve startup time for
typical inter-CU-reference binaries, at an obvious memory cost. */
-static int dwarf2_max_cache_age = 5;
+static int dwarf_max_cache_age = 5;
static void
-show_dwarf2_max_cache_age (struct ui_file *file, int from_tty,
- struct cmd_list_element *c, const char *value)
+show_dwarf_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"),
+ "DWARF compilation units is %s.\n"),
value);
}
\f
static void add_partial_namespace (struct partial_die_info *pdi,
CORE_ADDR *lowpc, CORE_ADDR *highpc,
- int need_pc, struct dwarf2_cu *cu);
+ int set_addrmap, struct dwarf2_cu *cu);
static void add_partial_module (struct partial_die_info *pdi, CORE_ADDR *lowpc,
- CORE_ADDR *highpc, int need_pc,
+ CORE_ADDR *highpc, int set_addrmap,
struct dwarf2_cu *cu);
static void add_partial_enumeration (struct partial_die_info *enum_pdi,
unsigned int *);
static const char *read_str_index (const struct die_reader_specs *reader,
- struct dwarf2_cu *cu, ULONGEST str_index);
+ ULONGEST str_index);
static void set_cu_language (unsigned int, struct dwarf2_cu *);
static void dwarf_decode_lines (struct line_header *, const char *,
struct dwarf2_cu *, struct partial_symtab *,
- int);
+ CORE_ADDR, int decode_mapping);
-static void dwarf2_start_subfile (const char *, const char *, const char *);
+static void dwarf2_start_subfile (const char *, const char *);
-static void dwarf2_start_symtab (struct dwarf2_cu *,
- const char *, const char *, CORE_ADDR);
+static struct compunit_symtab *dwarf2_start_symtab (struct dwarf2_cu *,
+ const char *, const char *,
+ CORE_ADDR);
static struct symbol *new_symbol (struct die_info *, struct type *,
struct dwarf2_cu *);
static void read_signatured_type (struct signatured_type *);
-static struct type_unit_group *get_type_unit_group
- (struct dwarf2_cu *, const struct attribute *);
-
-static void build_type_unit_groups (die_reader_func_ftype *, void *);
-
/* memory allocation interface */
static struct dwarf_block *dwarf_alloc_block (struct dwarf2_cu *);
static struct die_info *dwarf_alloc_die (struct dwarf2_cu *, int);
-static void dwarf_decode_macros (struct dwarf2_cu *, unsigned int,
- const char *, int);
+static void dwarf_decode_macros (struct dwarf2_cu *, unsigned int, int);
static int attr_form_is_block (const struct attribute *);
static void process_cu_includes (void);
static void check_producer (struct dwarf2_cu *cu);
+
+static void free_line_header_voidp (void *arg);
\f
/* Various complaints about symbol reading that don't abort the process. */
_("invalid attribute class or form for '%s' in '%s'"),
arg1, arg2);
}
+
+/* Hash function for line_header_hash. */
+
+static hashval_t
+line_header_hash (const struct line_header *ofs)
+{
+ return ofs->offset.sect_off ^ ofs->offset_in_dwz;
+}
+
+/* Hash function for htab_create_alloc_ex for line_header_hash. */
+
+static hashval_t
+line_header_hash_voidp (const void *item)
+{
+ const struct line_header *ofs = item;
+
+ return line_header_hash (ofs);
+}
+
+/* Equality function for line_header_hash. */
+
+static int
+line_header_eq_voidp (const void *item_lhs, const void *item_rhs)
+{
+ const struct line_header *ofs_lhs = item_lhs;
+ const struct line_header *ofs_rhs = item_rhs;
+
+ return (ofs_lhs->offset.sect_off == ofs_rhs->offset.sect_off
+ && ofs_lhs->offset_in_dwz == ofs_rhs->offset_in_dwz);
+}
+
\f
#if WORDS_BIGENDIAN
#define MAYBE_SWAP(V) (V)
#endif /* WORDS_BIGENDIAN */
+/* Read the given attribute value as an address, taking the attribute's
+ form into account. */
+
+static CORE_ADDR
+attr_value_as_address (struct attribute *attr)
+{
+ CORE_ADDR addr;
+
+ if (attr->form != DW_FORM_addr && attr->form != DW_FORM_GNU_addr_index)
+ {
+ /* Aside from a few clearly defined exceptions, attributes that
+ contain an address must always be in DW_FORM_addr form.
+ Unfortunately, some compilers happen to be violating this
+ requirement by encoding addresses using other forms, such
+ as DW_FORM_data4 for example. For those broken compilers,
+ we try to do our best, without any guarantee of success,
+ to interpret the address correctly. It would also be nice
+ to generate a complaint, but that would require us to maintain
+ a list of legitimate cases where a non-address form is allowed,
+ as well as update callers to pass in at least the CU's DWARF
+ version. This is more overhead than what we're willing to
+ expand for a pretty rare case. */
+ addr = DW_UNSND (attr);
+ }
+ else
+ addr = DW_ADDR (attr);
+
+ return addr;
+}
+
/* The suffix for an index file. */
#define INDEX_SUFFIX ".gdb-index"
do_cleanups (cleanup);
+ gdb_bfd_record_inclusion (dwarf2_per_objfile->objfile->obfd, dwz_bfd);
dwarf2_per_objfile->dwz_file = result;
return result;
}
/* The corresponding symbol table. This is NULL if symbols for this
CU have not yet been read. */
- struct symtab *symtab;
+ struct compunit_symtab *compunit_symtab;
/* A temporary mark bit used when iterating over all CUs in
expand_symtabs_matching. */
back_to = make_cleanup (dwarf2_release_queue, NULL);
if (dwarf2_per_objfile->using_index
- ? per_cu->v.quick->symtab == NULL
+ ? per_cu->v.quick->compunit_symtab == NULL
: (per_cu->v.psymtab == NULL || !per_cu->v.psymtab->readin))
{
queue_comp_unit (per_cu, language_minimal);
the objfile from which this CU came. Returns the resulting symbol
table. */
-static struct symtab *
+static struct compunit_symtab *
dw2_instantiate_symtab (struct dwarf2_per_cu_data *per_cu)
{
gdb_assert (dwarf2_per_objfile->using_index);
- if (!per_cu->v.quick->symtab)
+ if (!per_cu->v.quick->compunit_symtab)
{
struct cleanup *back_to = make_cleanup (free_cached_comp_units, NULL);
increment_reading_symtab ();
process_cu_includes ();
do_cleanups (back_to);
}
- return per_cu->v.quick->symtab;
+
+ return per_cu->v.quick->compunit_symtab;
}
-/* Return the CU given its index.
+/* Return the CU/TU given its index.
This is intended for loops like:
for (i = 0; i < (dwarf2_per_objfile->n_comp_units
+ dwarf2_per_objfile->n_type_units); ++i)
{
- struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
+ struct dwarf2_per_cu_data *per_cu = dw2_get_cutu (i);
...;
}
*/
static struct dwarf2_per_cu_data *
-dw2_get_cu (int index)
+dw2_get_cutu (int index)
{
if (index >= dwarf2_per_objfile->n_comp_units)
{
return dwarf2_per_objfile->all_comp_units[index];
}
-/* Return the primary CU given its index.
- The difference between this function and dw2_get_cu is in the handling
- of type units (TUs). Here we return the type_unit_group object.
-
- This is intended for loops like:
-
- for (i = 0; i < (dwarf2_per_objfile->n_comp_units
- + dwarf2_per_objfile->n_type_unit_groups); ++i)
- {
- struct dwarf2_per_cu_data *per_cu = dw2_get_primary_cu (i);
-
- ...;
- }
-*/
+/* Return the CU given its index.
+ This differs from dw2_get_cutu in that it's for when you know INDEX
+ refers to a CU. */
static struct dwarf2_per_cu_data *
-dw2_get_primary_cu (int index)
+dw2_get_cu (int index)
{
- if (index >= dwarf2_per_objfile->n_comp_units)
- {
- index -= dwarf2_per_objfile->n_comp_units;
- gdb_assert (index < dwarf2_per_objfile->n_type_unit_groups);
- return &dwarf2_per_objfile->all_type_unit_groups[index]->per_cu;
- }
+ gdb_assert (index >= 0 && index < dwarf2_per_objfile->n_comp_units);
return dwarf2_per_objfile->all_comp_units[index];
}
offset_type i;
htab_t sig_types_hash;
- dwarf2_per_objfile->n_type_units = elements / 3;
+ dwarf2_per_objfile->n_type_units
+ = dwarf2_per_objfile->n_allocated_type_units
+ = elements / 3;
dwarf2_per_objfile->all_type_units
= xmalloc (dwarf2_per_objfile->n_type_units
* sizeof (struct signatured_type *));
static void
create_addrmap_from_index (struct objfile *objfile, struct mapped_index *index)
{
+ struct gdbarch *gdbarch = get_objfile_arch (objfile);
const gdb_byte *iter, *end;
struct obstack temp_obstack;
struct addrmap *mutable_map;
continue;
}
- addrmap_set_empty (mutable_map, lo + baseaddr, hi + baseaddr - 1,
- dw2_get_cu (cu_index));
+ lo = gdbarch_adjust_dwarf2_addr (gdbarch, lo + baseaddr);
+ hi = gdbarch_adjust_dwarf2_addr (gdbarch, hi + baseaddr);
+ addrmap_set_empty (mutable_map, lo, hi - 1, dw2_get_cutu (cu_index));
}
objfile->psymtabs_addrmap = addrmap_create_fixed (mutable_map,
{
/* NAME is already canonical. Drop any qualifiers as .gdb_index does
not contain any. */
- const char *paren = strchr (name, '(');
- if (paren)
+ if (strchr (name, '(') != NULL)
{
- char *dup;
-
- dup = xmalloc (paren - name + 1);
- memcpy (dup, name, paren - name);
- dup[paren - name] = 0;
+ char *without_params = cp_remove_params (name);
- make_cleanup (xfree, dup);
- name = dup;
+ if (without_params != NULL)
+ {
+ make_cleanup (xfree, without_params);
+ name = without_params;
+ }
}
}
{
if (qfn->real_names == NULL)
qfn->real_names = OBSTACK_CALLOC (&objfile->objfile_obstack,
- qfn->num_file_names, char *);
+ qfn->num_file_names, const char *);
if (qfn->real_names[index] == NULL)
qfn->real_names[index] = gdb_realpath (qfn->file_names[index]);
static struct symtab *
dw2_find_last_source_symtab (struct objfile *objfile)
{
+ struct compunit_symtab *cust;
int index;
dw2_setup (objfile);
index = dwarf2_per_objfile->n_comp_units - 1;
- return dw2_instantiate_symtab (dw2_get_cu (index));
+ cust = dw2_instantiate_symtab (dw2_get_cutu (index));
+ if (cust == NULL)
+ return NULL;
+ return compunit_primary_filetab (cust);
}
/* Traversal function for dw2_forget_cached_source_info. */
int (*callback) (struct symtab *, void *),
void *data)
{
- struct symtab *last_made = objfile->symtabs;
+ struct compunit_symtab *last_made = objfile->compunit_symtabs;
/* Don't visit already-expanded CUs. */
- if (per_cu->v.quick->symtab)
+ if (per_cu->v.quick->compunit_symtab)
return 0;
/* This may expand more than one symtab, and we want to iterate over
dw2_instantiate_symtab (per_cu);
return iterate_over_some_symtabs (name, real_path, callback, data,
- objfile->symtabs, last_made);
+ objfile->compunit_symtabs, last_made);
}
/* Implementation of the map_symtabs_matching_filename method. */
for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
{
int j;
- struct dwarf2_per_cu_data *per_cu = dw2_get_primary_cu (i);
+ struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
struct quick_file_names *file_data;
/* We only need to look at symtabs not already expanded. */
- if (per_cu->v.quick->symtab)
+ if (per_cu->v.quick->compunit_symtab)
continue;
file_data = dw2_get_file_names (per_cu);
continue;
}
- per_cu = dw2_get_cu (cu_index);
+ per_cu = dw2_get_cutu (cu_index);
/* Skip if already read in. */
- if (per_cu->v.quick->symtab)
+ if (per_cu->v.quick->compunit_symtab)
continue;
/* Check static vs global. */
return NULL;
}
-static struct symtab *
+static struct compunit_symtab *
dw2_lookup_symbol (struct objfile *objfile, int block_index,
const char *name, domain_enum domain)
{
- struct symtab *stab_best = NULL;
+ struct compunit_symtab *stab_best = NULL;
struct mapped_index *index;
dw2_setup (objfile);
while ((per_cu = dw2_symtab_iter_next (&iter)) != NULL)
{
- struct symbol *sym = NULL;
- struct symtab *stab = dw2_instantiate_symtab (per_cu);
+ struct symbol *sym, *with_opaque = NULL;
+ struct compunit_symtab *stab = dw2_instantiate_symtab (per_cu);
+ const struct blockvector *bv = COMPUNIT_BLOCKVECTOR (stab);
+ struct block *block = BLOCKVECTOR_BLOCK (bv, block_index);
+
+ sym = block_find_symbol (block, name, domain,
+ block_find_non_opaque_type_preferred,
+ &with_opaque);
/* Some caution must be observed with overloaded functions
and methods, since the index will not contain any overload
information (but NAME might contain it). */
- if (stab->primary)
- {
- struct blockvector *bv = BLOCKVECTOR (stab);
- struct block *block = BLOCKVECTOR_BLOCK (bv, block_index);
-
- sym = lookup_block_symbol (block, name, domain);
- }
-
- if (sym && strcmp_iw (SYMBOL_SEARCH_NAME (sym), name) == 0)
- {
- if (!TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)))
- return stab;
- stab_best = stab;
- }
+ if (sym != NULL
+ && strcmp_iw (SYMBOL_SEARCH_NAME (sym), name) == 0)
+ return stab;
+ if (with_opaque != NULL
+ && strcmp_iw (SYMBOL_SEARCH_NAME (with_opaque), name) == 0)
+ stab_best = stab;
/* Keep looking through other CUs. */
}
count = 0;
for (i = 0; i < total; ++i)
{
- struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
+ struct dwarf2_per_cu_data *per_cu = dw2_get_cutu (i);
- if (!per_cu->v.quick->symtab)
+ if (!per_cu->v.quick->compunit_symtab)
++count;
}
printf_filtered (_(" Number of read CUs: %d\n"), total - count);
for (i = 0; i < (dwarf2_per_objfile->n_comp_units
+ dwarf2_per_objfile->n_type_units); ++i)
{
- struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
+ struct dwarf2_per_cu_data *per_cu = dw2_get_cutu (i);
dw2_instantiate_symtab (per_cu);
}
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 dwarf2_per_cu_data *per_cu = dw2_get_cutu (i);
struct quick_file_names *file_data;
/* We only need to look at symtabs not already expanded. */
- if (per_cu->v.quick->symtab)
+ if (per_cu->v.quick->compunit_symtab)
continue;
file_data = dw2_get_file_names (per_cu);
static void
dw2_map_matching_symbols (struct objfile *objfile,
- const char * name, domain_enum namespace,
+ const char * name, domain_enum domain,
int global,
int (*callback) (struct block *,
struct symbol *, void *),
static void
dw2_expand_symtabs_matching
(struct objfile *objfile,
- int (*file_matcher) (const char *, void *, int basenames),
- int (*name_matcher) (const char *, void *),
+ expand_symtabs_file_matcher_ftype *file_matcher,
+ expand_symtabs_symbol_matcher_ftype *symbol_matcher,
+ expand_symtabs_exp_notify_ftype *expansion_notify,
enum search_domain kind,
void *data)
{
for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
{
int j;
- struct dwarf2_per_cu_data *per_cu = dw2_get_primary_cu (i);
+ struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
struct quick_file_names *file_data;
void **slot;
+ QUIT;
+
per_cu->v.quick->mark = 0;
/* We only need to look at symtabs not already expanded. */
- if (per_cu->v.quick->symtab)
+ if (per_cu->v.quick->compunit_symtab)
continue;
file_data = dw2_get_file_names (per_cu);
offset_type *vec, vec_len, vec_idx;
int global_seen = 0;
+ QUIT;
+
if (index->symbol_table[idx] == 0 && index->symbol_table[idx + 1] == 0)
continue;
name = index->constant_pool + MAYBE_SWAP (index->symbol_table[idx]);
- if (! (*name_matcher) (name, data))
+ if (! (*symbol_matcher) (name, data))
continue;
/* The name was matched, now expand corresponding CUs that were
continue;
}
- per_cu = dw2_get_cu (cu_index);
+ per_cu = dw2_get_cutu (cu_index);
if (file_matcher == NULL || per_cu->v.quick->mark)
- dw2_instantiate_symtab (per_cu);
+ {
+ int symtab_was_null =
+ (per_cu->v.quick->compunit_symtab == NULL);
+
+ dw2_instantiate_symtab (per_cu);
+
+ if (expansion_notify != NULL
+ && symtab_was_null
+ && per_cu->v.quick->compunit_symtab != NULL)
+ {
+ expansion_notify (per_cu->v.quick->compunit_symtab,
+ data);
+ }
+ }
}
}
}
-/* A helper for dw2_find_pc_sect_symtab which finds the most specific
+/* A helper for dw2_find_pc_sect_compunit_symtab which finds the most specific
symtab. */
-static struct symtab *
-recursively_find_pc_sect_symtab (struct symtab *symtab, CORE_ADDR pc)
+static struct compunit_symtab *
+recursively_find_pc_sect_compunit_symtab (struct compunit_symtab *cust,
+ CORE_ADDR pc)
{
int i;
- if (BLOCKVECTOR (symtab) != NULL
- && blockvector_contains_pc (BLOCKVECTOR (symtab), pc))
- return symtab;
+ if (COMPUNIT_BLOCKVECTOR (cust) != NULL
+ && blockvector_contains_pc (COMPUNIT_BLOCKVECTOR (cust), pc))
+ return cust;
- if (symtab->includes == NULL)
+ if (cust->includes == NULL)
return NULL;
- for (i = 0; symtab->includes[i]; ++i)
+ for (i = 0; cust->includes[i]; ++i)
{
- struct symtab *s = symtab->includes[i];
+ struct compunit_symtab *s = cust->includes[i];
- s = recursively_find_pc_sect_symtab (s, pc);
+ s = recursively_find_pc_sect_compunit_symtab (s, pc);
if (s != NULL)
return s;
}
return NULL;
}
-static struct symtab *
-dw2_find_pc_sect_symtab (struct objfile *objfile,
- struct minimal_symbol *msymbol,
- CORE_ADDR pc,
- struct obj_section *section,
- int warn_if_readin)
+static struct compunit_symtab *
+dw2_find_pc_sect_compunit_symtab (struct objfile *objfile,
+ struct bound_minimal_symbol msymbol,
+ CORE_ADDR pc,
+ struct obj_section *section,
+ int warn_if_readin)
{
struct dwarf2_per_cu_data *data;
- struct symtab *result;
+ struct compunit_symtab *result;
dw2_setup (objfile);
if (!data)
return NULL;
- if (warn_if_readin && data->v.quick->symtab)
+ if (warn_if_readin && data->v.quick->compunit_symtab)
warning (_("(Internal error: pc %s in read in CU, but not in symtab.)"),
paddress (get_objfile_arch (objfile), pc));
- result = recursively_find_pc_sect_symtab (dw2_instantiate_symtab (data), pc);
+ result
+ = recursively_find_pc_sect_compunit_symtab (dw2_instantiate_symtab (data),
+ pc);
gdb_assert (result != NULL);
return result;
}
for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
{
- struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
+ struct dwarf2_per_cu_data *per_cu = dw2_get_cutu (i);
- if (per_cu->v.quick->symtab)
+ if (per_cu->v.quick->compunit_symtab)
{
void **slot = htab_find_slot (visited, per_cu->v.quick->file_names,
INSERT);
for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
{
int j;
- struct dwarf2_per_cu_data *per_cu = dw2_get_primary_cu (i);
+ struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
struct quick_file_names *file_data;
void **slot;
/* We only need to look at symtabs not already expanded. */
- if (per_cu->v.quick->symtab)
+ if (per_cu->v.quick->compunit_symtab)
continue;
file_data = dw2_get_file_names (per_cu);
dw2_expand_symtabs_with_fullname,
dw2_map_matching_symbols,
dw2_expand_symtabs_matching,
- dw2_find_pc_sect_symtab,
+ dw2_find_pc_sect_compunit_symtab,
dw2_map_symbol_filenames
};
for (i = 0; i < (dwarf2_per_objfile->n_comp_units
+ dwarf2_per_objfile->n_type_units); ++i)
{
- struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
+ struct dwarf2_per_cu_data *per_cu = dw2_get_cutu (i);
per_cu->v.quick = OBSTACK_ZALLOC (&objfile->objfile_obstack,
struct dwarf2_per_cu_quick_data);
void
dwarf2_build_psymtabs (struct objfile *objfile)
{
- volatile struct gdb_exception except;
if (objfile->global_psymbols.size == 0 && objfile->static_psymbols.size == 0)
{
init_psymbol_list (objfile, 1024);
}
- TRY_CATCH (except, RETURN_MASK_ERROR)
+ TRY
{
/* This isn't really ideal: all the data we allocate on the
objfile's obstack is still uselessly kept around. However,
dwarf2_build_psymtabs_hard (objfile);
discard_cleanups (cleanups);
}
- if (except.reason < 0)
- exception_print (gdb_stderr, except);
+ CATCH (except, RETURN_MASK_ERROR)
+ {
+ exception_print (gdb_stderr, except);
+ }
+ END_CATCH
}
/* Return the total length of the CU described by HEADER. */
attr = dwarf2_attr (die, DW_AT_entry_pc, cu);
if (attr)
{
- cu->base_address = DW_ADDR (attr);
+ cu->base_address = attr_value_as_address (attr);
cu->base_known = 1;
}
else
attr = dwarf2_attr (die, DW_AT_low_pc, cu);
if (attr)
{
- cu->base_address = DW_ADDR (attr);
+ cu->base_address = attr_value_as_address (attr);
cu->base_known = 1;
}
}
subpst->n_global_syms = 0;
subpst->statics_offset = 0;
subpst->n_static_syms = 0;
- subpst->symtab = NULL;
+ subpst->compunit_symtab = NULL;
subpst->read_symtab = pst->read_symtab;
subpst->readin = 0;
return; /* No linetable, so no includes. */
/* NOTE: pst->dirname is DW_AT_comp_dir (if present). */
- dwarf_decode_lines (lh, pst->dirname, cu, pst, 1);
+ dwarf_decode_lines (lh, pst->dirname, cu, pst, pst->textlow, 1);
free_line_header (lh);
}
? &dwo_file->sections.abbrev
: &dwarf2_per_objfile->abbrev);
- if (dwarf2_read_debug)
+ if (dwarf_read_debug)
fprintf_unfiltered (gdb_stdlog, "Reading .debug_types%s for %s:\n",
dwo_file ? ".dwo" : "",
get_section_file_name (abbrev_section));
}
*slot = dwo_file ? (void *) dwo_tu : (void *) sig_type;
- if (dwarf2_read_debug > 1)
+ if (dwarf_read_debug > 1)
fprintf_unfiltered (gdb_stdlog, " offset 0x%x, signature %s\n",
offset.sect_off,
hex_string (signature));
dwarf2_per_objfile->signatured_types = types_htab;
- dwarf2_per_objfile->n_type_units = htab_elements (types_htab);
+ dwarf2_per_objfile->n_type_units
+ = dwarf2_per_objfile->n_allocated_type_units
+ = htab_elements (types_htab);
dwarf2_per_objfile->all_type_units
= xmalloc (dwarf2_per_objfile->n_type_units
* sizeof (struct signatured_type *));
return 1;
}
+/* Add an entry for signature SIG to dwarf2_per_objfile->signatured_types.
+ If SLOT is non-NULL, it is the entry to use in the hash table.
+ Otherwise we find one. */
+
+static struct signatured_type *
+add_type_unit (ULONGEST sig, void **slot)
+{
+ struct objfile *objfile = dwarf2_per_objfile->objfile;
+ int n_type_units = dwarf2_per_objfile->n_type_units;
+ struct signatured_type *sig_type;
+
+ gdb_assert (n_type_units <= dwarf2_per_objfile->n_allocated_type_units);
+ ++n_type_units;
+ if (n_type_units > dwarf2_per_objfile->n_allocated_type_units)
+ {
+ if (dwarf2_per_objfile->n_allocated_type_units == 0)
+ dwarf2_per_objfile->n_allocated_type_units = 1;
+ dwarf2_per_objfile->n_allocated_type_units *= 2;
+ dwarf2_per_objfile->all_type_units
+ = xrealloc (dwarf2_per_objfile->all_type_units,
+ dwarf2_per_objfile->n_allocated_type_units
+ * sizeof (struct signatured_type *));
+ ++dwarf2_per_objfile->tu_stats.nr_all_type_units_reallocs;
+ }
+ dwarf2_per_objfile->n_type_units = n_type_units;
+
+ sig_type = OBSTACK_ZALLOC (&objfile->objfile_obstack,
+ struct signatured_type);
+ dwarf2_per_objfile->all_type_units[n_type_units - 1] = sig_type;
+ sig_type->signature = sig;
+ sig_type->per_cu.is_debug_types = 1;
+ if (dwarf2_per_objfile->using_index)
+ {
+ sig_type->per_cu.v.quick =
+ OBSTACK_ZALLOC (&objfile->objfile_obstack,
+ struct dwarf2_per_cu_quick_data);
+ }
+
+ if (slot == NULL)
+ {
+ slot = htab_find_slot (dwarf2_per_objfile->signatured_types,
+ sig_type, INSERT);
+ }
+ gdb_assert (*slot == NULL);
+ *slot = sig_type;
+ /* The rest of sig_type must be filled in by the caller. */
+ return sig_type;
+}
+
/* Subroutine of lookup_dwo_signatured_type and lookup_dwp_signatured_type.
Fill in SIG_ENTRY with DWO_ENTRY. */
/* Make sure we're not clobbering something we don't expect to. */
gdb_assert (! sig_entry->per_cu.queued);
gdb_assert (sig_entry->per_cu.cu == NULL);
- gdb_assert (sig_entry->per_cu.v.quick != NULL);
- gdb_assert (sig_entry->per_cu.v.quick->symtab == NULL);
+ if (dwarf2_per_objfile->using_index)
+ {
+ gdb_assert (sig_entry->per_cu.v.quick != NULL);
+ gdb_assert (sig_entry->per_cu.v.quick->compunit_symtab == NULL);
+ }
+ else
+ gdb_assert (sig_entry->per_cu.v.psymtab == NULL);
gdb_assert (sig_entry->signature == dwo_entry->signature);
gdb_assert (sig_entry->type_offset_in_section.sect_off == 0);
gdb_assert (sig_entry->type_unit_group == NULL);
struct dwo_file *dwo_file;
struct dwo_unit find_dwo_entry, *dwo_entry;
struct signatured_type find_sig_entry, *sig_entry;
+ void **slot;
gdb_assert (cu->dwo_unit && dwarf2_per_objfile->using_index);
- /* Note: cu->dwo_unit is the dwo_unit that references this TU, not the
- dwo_unit of the TU itself. */
- dwo_file = cu->dwo_unit->dwo_file;
+ /* If TU skeletons have been removed then we may not have read in any
+ TUs yet. */
+ if (dwarf2_per_objfile->signatured_types == NULL)
+ {
+ dwarf2_per_objfile->signatured_types
+ = allocate_signatured_type_table (objfile);
+ }
/* We only ever need to read in one copy of a signatured type.
- Just use the global signatured_types array. If this is the first time
- we're reading this type, replace the recorded data from .gdb_index with
- this TU. */
+ Use the global signatured_types array to do our own comdat-folding
+ of types. If this is the first time we're reading this TU, and
+ the TU has an entry in .gdb_index, replace the recorded data from
+ .gdb_index with this TU. */
- if (dwarf2_per_objfile->signatured_types == NULL)
- return NULL;
find_sig_entry.signature = sig;
- sig_entry = htab_find (dwarf2_per_objfile->signatured_types, &find_sig_entry);
- if (sig_entry == NULL)
- return NULL;
+ slot = htab_find_slot (dwarf2_per_objfile->signatured_types,
+ &find_sig_entry, INSERT);
+ sig_entry = *slot;
/* We can get here with the TU already read, *or* in the process of being
- read. Don't reassign it if that's the case. Also note that if the TU is
- already being read, it may not have come from a DWO, the program may be
- a mix of Fission-compiled code and non-Fission-compiled code. */
- /* Have we already tried to read this TU? */
- if (sig_entry->per_cu.tu_read)
+ read. Don't reassign the global entry to point to this DWO if that's
+ the case. Also note that if the TU is already being read, it may not
+ have come from a DWO, the program may be a mix of Fission-compiled
+ code and non-Fission-compiled code. */
+
+ /* Have we already tried to read this TU?
+ Note: sig_entry can be NULL if the skeleton TU was removed (thus it
+ needn't exist in the global table yet). */
+ if (sig_entry != NULL && sig_entry->per_cu.tu_read)
return sig_entry;
+ /* Note: cu->dwo_unit is the dwo_unit that references this TU, not the
+ dwo_unit of the TU itself. */
+ dwo_file = cu->dwo_unit->dwo_file;
+
/* Ok, this is the first time we're reading this TU. */
if (dwo_file->tus == NULL)
return NULL;
if (dwo_entry == NULL)
return NULL;
+ /* If the global table doesn't have an entry for this TU, add one. */
+ if (sig_entry == NULL)
+ sig_entry = add_type_unit (sig, slot);
+
fill_in_sig_entry_from_dwo_entry (objfile, sig_entry, dwo_entry);
sig_entry->per_cu.tu_read = 1;
return sig_entry;
}
-/* Subroutine of lookup_dwp_signatured_type.
- Add an entry for signature SIG to dwarf2_per_objfile->signatured_types. */
-
-static struct signatured_type *
-add_type_unit (ULONGEST sig)
-{
- struct objfile *objfile = dwarf2_per_objfile->objfile;
- int n_type_units = dwarf2_per_objfile->n_type_units;
- struct signatured_type *sig_type;
- void **slot;
-
- ++n_type_units;
- dwarf2_per_objfile->all_type_units =
- xrealloc (dwarf2_per_objfile->all_type_units,
- n_type_units * sizeof (struct signatured_type *));
- dwarf2_per_objfile->n_type_units = n_type_units;
- sig_type = OBSTACK_ZALLOC (&objfile->objfile_obstack,
- struct signatured_type);
- dwarf2_per_objfile->all_type_units[n_type_units - 1] = sig_type;
- sig_type->signature = sig;
- sig_type->per_cu.is_debug_types = 1;
- sig_type->per_cu.v.quick =
- OBSTACK_ZALLOC (&objfile->objfile_obstack,
- struct dwarf2_per_cu_quick_data);
- slot = htab_find_slot (dwarf2_per_objfile->signatured_types,
- sig_type, INSERT);
- gdb_assert (*slot == NULL);
- *slot = sig_type;
- /* The rest of sig_type must be filled in by the caller. */
- return sig_type;
-}
-
/* Subroutine of lookup_signatured_type.
Look up the type for signature SIG, and if we can't find SIG in .gdb_index
- then try the DWP file.
- Normally this "can't happen", but if there's a bug in signature
- generation and/or the DWP file is built incorrectly, it can happen.
- Using the type directly from the DWP file means we don't have the stub
- which has some useful attributes (e.g., DW_AT_comp_dir), but they're
- not critical. [Eventually the stub may go away for type units anyway.] */
+ then try the DWP file. If the TU stub (skeleton) has been removed then
+ it won't be in .gdb_index. */
static struct signatured_type *
lookup_dwp_signatured_type (struct dwarf2_cu *cu, ULONGEST sig)
struct dwp_file *dwp_file = get_dwp_file ();
struct dwo_unit *dwo_entry;
struct signatured_type find_sig_entry, *sig_entry;
+ void **slot;
gdb_assert (cu->dwo_unit && dwarf2_per_objfile->using_index);
gdb_assert (dwp_file != NULL);
- if (dwarf2_per_objfile->signatured_types != NULL)
+ /* If TU skeletons have been removed then we may not have read in any
+ TUs yet. */
+ if (dwarf2_per_objfile->signatured_types == NULL)
{
- find_sig_entry.signature = sig;
- sig_entry = htab_find (dwarf2_per_objfile->signatured_types,
- &find_sig_entry);
- if (sig_entry != NULL)
- return sig_entry;
+ dwarf2_per_objfile->signatured_types
+ = allocate_signatured_type_table (objfile);
}
- /* This is the "shouldn't happen" case.
- Try the DWP file and hope for the best. */
+ find_sig_entry.signature = sig;
+ slot = htab_find_slot (dwarf2_per_objfile->signatured_types,
+ &find_sig_entry, INSERT);
+ sig_entry = *slot;
+
+ /* Have we already tried to read this TU?
+ Note: sig_entry can be NULL if the skeleton TU was removed (thus it
+ needn't exist in the global table yet). */
+ if (sig_entry != NULL)
+ return sig_entry;
+
if (dwp_file->tus == NULL)
return NULL;
dwo_entry = lookup_dwo_unit_in_dwp (dwp_file, NULL,
if (dwo_entry == NULL)
return NULL;
- sig_entry = add_type_unit (sig);
+ sig_entry = add_type_unit (sig, slot);
fill_in_sig_entry_from_dwo_entry (objfile, sig_entry, dwo_entry);
- /* The caller will signal a complaint if we return NULL.
- Here we don't return NULL but we still want to complain. */
- complaint (&symfile_complaints,
- _("Bad type signature %s referenced by %s at 0x%x,"
- " coping by using copy in DWP [in module %s]"),
- hex_string (sig),
- cu->per_cu->is_debug_types ? "TU" : "CU",
- cu->per_cu->offset.sect_off,
- objfile_name (objfile));
-
return sig_entry;
}
from it to the DIE in the DWO. If NULL we are skipping the stub.
STUB_COMP_DIR is similar to STUB_COMP_UNIT_DIE: When reading a TU directly
from the DWO file, bypassing the stub, it contains the DW_AT_comp_dir
- attribute of the referencing CU. Exactly one of STUB_COMP_UNIT_DIE and
- COMP_DIR must be non-NULL.
+ attribute of the referencing CU. At most one of STUB_COMP_UNIT_DIE and
+ STUB_COMP_DIR may be non-NULL.
*RESULT_READER,*RESULT_INFO_PTR,*RESULT_COMP_UNIT_DIE,*RESULT_HAS_CHILDREN
are filled in with the info of the DIE from the DWO file.
ABBREV_TABLE_PROVIDED is non-zero if the caller of init_cutu_and_read_dies
struct dwarf2_section_info *section;
bfd *abfd;
const gdb_byte *begin_info_ptr, *info_ptr;
- const char *comp_dir_string;
ULONGEST signature; /* Or dwo_id. */
struct attribute *comp_dir, *stmt_list, *low_pc, *high_pc, *ranges;
int i,num_extra_attrs;
struct dwarf2_section_info *dwo_abbrev_section;
struct attribute *attr;
- struct attribute comp_dir_attr;
struct die_info *comp_unit_die;
- /* Both can't be provided. */
- gdb_assert (! (stub_comp_unit_die && stub_comp_dir));
+ /* At most one of these may be provided. */
+ gdb_assert ((stub_comp_unit_die != NULL) + (stub_comp_dir != NULL) <= 1);
/* These attributes aren't processed until later:
DW_AT_stmt_list, DW_AT_low_pc, DW_AT_high_pc, DW_AT_ranges.
- However, the attribute is found in the stub which we won't have later.
- In order to not impose this complication on the rest of the code,
- we read them here and copy them to the DWO CU/TU die. */
+ DW_AT_comp_dir is used now, to find the DWO file, but it is also
+ referenced later. However, these attributes are found in the stub
+ which we won't have later. In order to not impose this complication
+ on the rest of the code, we read them here and copy them to the
+ DWO CU/TU die. */
stmt_list = NULL;
low_pc = NULL;
comp_unit_die->attrs[i++] = *comp_dir;
comp_unit_die->num_attrs += num_extra_attrs;
- if (dwarf2_die_debug)
+ if (dwarf_die_debug)
{
fprintf_unfiltered (gdb_stdlog,
"Read die from %s@0x%x of %s:\n",
get_section_name (section),
(unsigned) (begin_info_ptr - section->buffer),
bfd_get_filename (abfd));
- dump_die (comp_unit_die, dwarf2_die_debug);
+ dump_die (comp_unit_die, dwarf_die_debug);
}
/* Save the comp_dir attribute. If there is no DWP file then we'll read
}
/* Subroutine of init_cutu_and_read_dies to simplify it.
- Read a TU directly from a DWO file, bypassing the stub. */
+ See it for a description of the parameters.
+ Read a TU directly from a DWO file, bypassing the stub.
+
+ Note: This function could be a little bit simpler if we shared cleanups
+ with our caller, init_cutu_and_read_dies. That's generally a fragile thing
+ to do, so we keep this function self-contained. Or we could move this
+ into our caller, but it's complex enough already. */
static void
-init_tu_and_read_dwo_dies (struct dwarf2_per_cu_data *this_cu, int keep,
+init_tu_and_read_dwo_dies (struct dwarf2_per_cu_data *this_cu,
+ int use_existing_cu, int keep,
die_reader_func_ftype *die_reader_func,
void *data)
{
struct dwarf2_cu *cu;
struct signatured_type *sig_type;
- struct cleanup *cleanups, *free_cu_cleanup;
+ struct cleanup *cleanups, *free_cu_cleanup = NULL;
struct die_reader_specs reader;
const gdb_byte *info_ptr;
struct die_info *comp_unit_die;
cleanups = make_cleanup (null_cleanup, NULL);
- gdb_assert (this_cu->cu == NULL);
- cu = xmalloc (sizeof (*cu));
- init_one_comp_unit (cu, this_cu);
- /* If an error occurs while loading, release our storage. */
- free_cu_cleanup = make_cleanup (free_heap_comp_unit, cu);
+ if (use_existing_cu && this_cu->cu != NULL)
+ {
+ gdb_assert (this_cu->cu->dwo_unit == sig_type->dwo_unit);
+ cu = this_cu->cu;
+ /* There's no need to do the rereading_dwo_cu handling that
+ init_cutu_and_read_dies does since we don't read the stub. */
+ }
+ else
+ {
+ /* If !use_existing_cu, this_cu->cu must be NULL. */
+ gdb_assert (this_cu->cu == NULL);
+ cu = xmalloc (sizeof (*cu));
+ init_one_comp_unit (cu, this_cu);
+ /* If an error occurs while loading, release our storage. */
+ free_cu_cleanup = make_cleanup (free_heap_comp_unit, cu);
+ }
+
+ /* A future optimization, if needed, would be to use an existing
+ abbrev table. When reading DWOs with skeletonless TUs, all the TUs
+ could share abbrev tables. */
if (read_cutu_die_from_dwo (this_cu, sig_type->dwo_unit,
0 /* abbrev_table_provided */,
/* All the "real" work is done here. */
die_reader_func (&reader, info_ptr, comp_unit_die, has_children, data);
- /* This duplicates some code in init_cutu_and_read_dies,
+ /* This duplicates the code in init_cutu_and_read_dies,
but the alternative is making the latter more complex.
This function is only for the special case of using DWO files directly:
no point in overly complicating the general case just to handle this. */
- if (keep)
+ if (free_cu_cleanup != NULL)
{
- /* We've successfully allocated this compilation unit. Let our
- caller clean it up when finished with it. */
- discard_cleanups (free_cu_cleanup);
+ if (keep)
+ {
+ /* We've successfully allocated this compilation unit. Let our
+ caller clean it up when finished with it. */
+ discard_cleanups (free_cu_cleanup);
- /* We can only discard free_cu_cleanup and all subsequent cleanups.
- So we have to manually free the abbrev table. */
- dwarf2_free_abbrev_table (cu);
+ /* We can only discard free_cu_cleanup and all subsequent cleanups.
+ So we have to manually free the abbrev table. */
+ dwarf2_free_abbrev_table (cu);
- /* Link this CU into read_in_chain. */
- this_cu->cu->read_in_chain = dwarf2_per_objfile->read_in_chain;
- dwarf2_per_objfile->read_in_chain = this_cu;
+ /* Link this CU into read_in_chain. */
+ this_cu->cu->read_in_chain = dwarf2_per_objfile->read_in_chain;
+ dwarf2_per_objfile->read_in_chain = this_cu;
+ }
+ else
+ do_cleanups (free_cu_cleanup);
}
- else
- do_cleanups (free_cu_cleanup);
do_cleanups (cleanups);
}
before we can reread the DWO file (this only applies to CUs, not TUs). */
int rereading_dwo_cu = 0;
- if (dwarf2_die_debug)
+ if (dwarf_die_debug)
fprintf_unfiltered (gdb_stdlog, "Reading %s unit at offset 0x%x\n",
this_cu->is_debug_types ? "type" : "comp",
this_cu->offset.sect_off);
/* Narrow down the scope of possibilities to have to understand. */
gdb_assert (this_cu->is_debug_types);
gdb_assert (abbrev_table == NULL);
- gdb_assert (!use_existing_cu);
- init_tu_and_read_dwo_dies (this_cu, keep, die_reader_func, data);
+ init_tu_and_read_dwo_dies (this_cu, use_existing_cu, keep,
+ die_reader_func, data);
return;
}
if (use_existing_cu && this_cu->cu != NULL)
{
cu = this_cu->cu;
-
/* If this CU is from a DWO file we need to start over, we need to
refetch the attributes from the skeleton CU.
This could be optimized by retrieving those attributes from when we
{
/* If !use_existing_cu, this_cu->cu must be NULL. */
gdb_assert (this_cu->cu == NULL);
-
cu = xmalloc (sizeof (*cu));
init_one_comp_unit (cu, this_cu);
-
/* If an error occurs while loading, release our storage. */
free_cu_cleanup = make_cleanup (free_heap_comp_unit, cu);
}
do_cleanups (cleanups);
}
-/* Read CU/TU THIS_CU in section SECTION,
- but do not follow DW_AT_GNU_dwo_name if present.
- DWOP_FILE, if non-NULL, is the DWO/DWP file to read (the caller is assumed
- to have already done the lookup to find the DWO/DWP file).
+/* Read CU/TU THIS_CU but do not follow DW_AT_GNU_dwo_name if present.
+ DWO_FILE, if non-NULL, is the DWO file to read (the caller is assumed
+ to have already done the lookup to find the DWO file).
The caller is required to fill in THIS_CU->section, THIS_CU->offset, and
THIS_CU->is_debug_types, but nothing else.
static void
init_cutu_and_read_dies_no_follow (struct dwarf2_per_cu_data *this_cu,
- struct dwarf2_section_info *abbrev_section,
struct dwo_file *dwo_file,
die_reader_func_ftype *die_reader_func,
void *data)
struct objfile *objfile = dwarf2_per_objfile->objfile;
struct dwarf2_section_info *section = this_cu->section;
bfd *abfd = get_section_bfd_owner (section);
+ struct dwarf2_section_info *abbrev_section;
struct dwarf2_cu cu;
const gdb_byte *begin_info_ptr, *info_ptr;
struct die_reader_specs reader;
struct die_info *comp_unit_die;
int has_children;
- if (dwarf2_die_debug)
+ if (dwarf_die_debug)
fprintf_unfiltered (gdb_stdlog, "Reading %s unit at offset 0x%x\n",
this_cu->is_debug_types ? "type" : "comp",
this_cu->offset.sect_off);
gdb_assert (this_cu->cu == NULL);
+ abbrev_section = (dwo_file != NULL
+ ? &dwo_file->sections.abbrev
+ : get_abbrev_section_for_cu (this_cu));
+
/* This is cheap if the section is already read in. */
dwarf2_read_section (objfile, section);
die_reader_func_ftype *die_reader_func,
void *data)
{
- init_cutu_and_read_dies_no_follow (this_cu,
- get_abbrev_section_for_cu (this_cu),
- NULL,
- die_reader_func, data);
+ init_cutu_and_read_dies_no_follow (this_cu, NULL, die_reader_func, data);
}
\f
/* Type Unit Groups.
return tu_group;
}
+\f
+/* Partial symbol tables. */
-/* Struct used to sort TUs by their abbreviation table offset. */
-
-struct tu_abbrev_offset
-{
- struct signatured_type *sig_type;
- sect_offset abbrev_offset;
-};
-
-/* Helper routine for build_type_unit_groups, passed to qsort. */
-
-static int
-sort_tu_by_abbrev_offset (const void *ap, const void *bp)
-{
- const struct tu_abbrev_offset * const *a = ap;
- const struct tu_abbrev_offset * const *b = bp;
- unsigned int aoff = (*a)->abbrev_offset.sect_off;
- unsigned int boff = (*b)->abbrev_offset.sect_off;
-
- return (aoff > boff) - (aoff < boff);
-}
-
-/* A helper function to add a type_unit_group to a table. */
-
-static int
-add_type_unit_group_to_table (void **slot, void *datum)
-{
- struct type_unit_group *tu_group = *slot;
- struct type_unit_group ***datap = datum;
-
- **datap = tu_group;
- ++*datap;
-
- return 1;
-}
-
-/* Efficiently read all the type units, calling init_cutu_and_read_dies on
- each one passing FUNC,DATA.
-
- The efficiency is because we sort TUs by the abbrev table they use and
- only read each abbrev table once. In one program there are 200K TUs
- sharing 8K abbrev tables.
-
- The main purpose of this function is to support building the
- dwarf2_per_objfile->type_unit_groups table.
- TUs typically share the DW_AT_stmt_list of the CU they came from, so we
- can collapse the search space by grouping them by stmt_list.
- The savings can be significant, in the same program from above the 200K TUs
- share 8K stmt_list tables.
-
- FUNC is expected to call get_type_unit_group, which will create the
- struct type_unit_group if necessary and add it to
- dwarf2_per_objfile->type_unit_groups. */
-
-static void
-build_type_unit_groups (die_reader_func_ftype *func, void *data)
-{
- struct objfile *objfile = dwarf2_per_objfile->objfile;
- struct tu_stats *tu_stats = &dwarf2_per_objfile->tu_stats;
- struct cleanup *cleanups;
- struct abbrev_table *abbrev_table;
- sect_offset abbrev_offset;
- struct tu_abbrev_offset *sorted_by_abbrev;
- struct type_unit_group **iter;
- int i;
-
- /* It's up to the caller to not call us multiple times. */
- gdb_assert (dwarf2_per_objfile->type_unit_groups == NULL);
-
- if (dwarf2_per_objfile->n_type_units == 0)
- return;
-
- /* TUs typically share abbrev tables, and there can be way more TUs than
- abbrev tables. Sort by abbrev table to reduce the number of times we
- read each abbrev table in.
- Alternatives are to punt or to maintain a cache of abbrev tables.
- This is simpler and efficient enough for now.
-
- Later we group TUs by their DW_AT_stmt_list value (as this defines the
- symtab to use). Typically TUs with the same abbrev offset have the same
- stmt_list value too so in practice this should work well.
-
- The basic algorithm here is:
-
- sort TUs by abbrev table
- for each TU with same abbrev table:
- read abbrev table if first user
- read TU top level DIE
- [IWBN if DWO skeletons had DW_AT_stmt_list]
- call FUNC */
-
- if (dwarf2_read_debug)
- fprintf_unfiltered (gdb_stdlog, "Building type unit groups ...\n");
-
- /* Sort in a separate table to maintain the order of all_type_units
- for .gdb_index: TU indices directly index all_type_units. */
- sorted_by_abbrev = XNEWVEC (struct tu_abbrev_offset,
- dwarf2_per_objfile->n_type_units);
- for (i = 0; i < dwarf2_per_objfile->n_type_units; ++i)
- {
- struct signatured_type *sig_type = dwarf2_per_objfile->all_type_units[i];
-
- sorted_by_abbrev[i].sig_type = sig_type;
- sorted_by_abbrev[i].abbrev_offset =
- read_abbrev_offset (sig_type->per_cu.section,
- sig_type->per_cu.offset);
- }
- cleanups = make_cleanup (xfree, sorted_by_abbrev);
- qsort (sorted_by_abbrev, dwarf2_per_objfile->n_type_units,
- sizeof (struct tu_abbrev_offset), sort_tu_by_abbrev_offset);
-
- /* Note: In the .gdb_index case, get_type_unit_group may have already been
- called any number of times, so we don't reset tu_stats here. */
-
- abbrev_offset.sect_off = ~(unsigned) 0;
- abbrev_table = NULL;
- make_cleanup (abbrev_table_free_cleanup, &abbrev_table);
-
- for (i = 0; i < dwarf2_per_objfile->n_type_units; ++i)
- {
- const struct tu_abbrev_offset *tu = &sorted_by_abbrev[i];
-
- /* Switch to the next abbrev table if necessary. */
- if (abbrev_table == NULL
- || tu->abbrev_offset.sect_off != abbrev_offset.sect_off)
- {
- if (abbrev_table != NULL)
- {
- abbrev_table_free (abbrev_table);
- /* Reset to NULL in case abbrev_table_read_table throws
- an error: abbrev_table_free_cleanup will get called. */
- abbrev_table = NULL;
- }
- abbrev_offset = tu->abbrev_offset;
- abbrev_table =
- abbrev_table_read_table (&dwarf2_per_objfile->abbrev,
- abbrev_offset);
- ++tu_stats->nr_uniq_abbrev_tables;
- }
-
- init_cutu_and_read_dies (&tu->sig_type->per_cu, abbrev_table, 0, 0,
- func, data);
- }
-
- /* type_unit_groups can be NULL if there is an error in the debug info.
- Just create an empty table so the rest of gdb doesn't have to watch
- for this error case. */
- if (dwarf2_per_objfile->type_unit_groups == NULL)
- {
- dwarf2_per_objfile->type_unit_groups =
- allocate_type_unit_groups_table ();
- dwarf2_per_objfile->n_type_unit_groups = 0;
- }
-
- /* Create a vector of pointers to primary type units to make it easy to
- iterate over them and CUs. See dw2_get_primary_cu. */
- dwarf2_per_objfile->n_type_unit_groups =
- htab_elements (dwarf2_per_objfile->type_unit_groups);
- dwarf2_per_objfile->all_type_unit_groups =
- obstack_alloc (&objfile->objfile_obstack,
- dwarf2_per_objfile->n_type_unit_groups
- * sizeof (struct type_unit_group *));
- iter = &dwarf2_per_objfile->all_type_unit_groups[0];
- htab_traverse_noresize (dwarf2_per_objfile->type_unit_groups,
- add_type_unit_group_to_table, &iter);
- gdb_assert (iter - &dwarf2_per_objfile->all_type_unit_groups[0]
- == dwarf2_per_objfile->n_type_unit_groups);
-
- do_cleanups (cleanups);
-
- if (dwarf2_read_debug)
- {
- fprintf_unfiltered (gdb_stdlog, "Done building type unit groups:\n");
- fprintf_unfiltered (gdb_stdlog, " %d TUs\n",
- dwarf2_per_objfile->n_type_units);
- fprintf_unfiltered (gdb_stdlog, " %d uniq abbrev tables\n",
- tu_stats->nr_uniq_abbrev_tables);
- fprintf_unfiltered (gdb_stdlog, " %d symtabs from stmt_list entries\n",
- tu_stats->nr_symtabs);
- fprintf_unfiltered (gdb_stdlog, " %d symtab sharers\n",
- tu_stats->nr_symtab_sharers);
- fprintf_unfiltered (gdb_stdlog, " %d type units without a stmt_list\n",
- tu_stats->nr_stmt_less_type_units);
- }
-}
-\f
-/* Partial symbol tables. */
-
-/* Create a psymtab named NAME and assign it to PER_CU.
+/* Create a psymtab named NAME and assign it to PER_CU.
The caller must fill in the following details:
dirname, textlow, texthigh. */
{
struct dwarf2_cu *cu = reader->cu;
struct objfile *objfile = cu->objfile;
+ struct gdbarch *gdbarch = get_objfile_arch (objfile);
struct dwarf2_per_cu_data *per_cu = cu->per_cu;
struct attribute *attr;
CORE_ADDR baseaddr;
/* Store the contiguous range if it is not empty; it can be empty for
CUs with no code. */
addrmap_set_empty (objfile->psymtabs_addrmap,
- best_lowpc + baseaddr,
- best_highpc + baseaddr - 1, pst);
+ gdbarch_adjust_dwarf2_addr (gdbarch,
+ best_lowpc + baseaddr),
+ gdbarch_adjust_dwarf2_addr (gdbarch,
+ best_highpc + baseaddr) - 1,
+ pst);
/* Check if comp unit has_children.
If so, read the rest of the partial symbols from this comp unit.
best_highpc = highpc;
}
}
- pst->textlow = best_lowpc + baseaddr;
- pst->texthigh = best_highpc + baseaddr;
+ pst->textlow = gdbarch_adjust_dwarf2_addr (gdbarch, best_lowpc + baseaddr);
+ pst->texthigh = gdbarch_adjust_dwarf2_addr (gdbarch, best_highpc + baseaddr);
pst->n_global_syms = objfile->global_psymbols.next -
(objfile->global_psymbols.list + pst->globals_offset);
and build a psymtab for each of them. */
dwarf2_build_include_psymtabs (cu, comp_unit_die, pst);
- if (dwarf2_read_debug)
+ if (dwarf_read_debug)
{
struct gdbarch *gdbarch = get_objfile_arch (objfile);
attr = dwarf2_attr_no_follow (type_unit_die, DW_AT_stmt_list);
tu_group = get_type_unit_group (cu, attr);
- VEC_safe_push (sig_type_ptr, tu_group->tus, sig_type);
+ VEC_safe_push (sig_type_ptr, tu_group->tus, sig_type);
+
+ prepare_one_comp_unit (cu, type_unit_die, language_minimal);
+ cu->list_in_scope = &file_symbols;
+ pst = create_partial_symtab (per_cu, "");
+ pst->anonymous = 1;
+
+ first_die = load_partial_dies (reader, info_ptr, 1);
+
+ lowpc = (CORE_ADDR) -1;
+ highpc = (CORE_ADDR) 0;
+ scan_partial_symbols (first_die, &lowpc, &highpc, 0, cu);
+
+ pst->n_global_syms = objfile->global_psymbols.next -
+ (objfile->global_psymbols.list + pst->globals_offset);
+ pst->n_static_syms = objfile->static_psymbols.next -
+ (objfile->static_psymbols.list + pst->statics_offset);
+ sort_pst_symbols (objfile, pst);
+}
+
+/* Struct used to sort TUs by their abbreviation table offset. */
+
+struct tu_abbrev_offset
+{
+ struct signatured_type *sig_type;
+ sect_offset abbrev_offset;
+};
+
+/* Helper routine for build_type_psymtabs_1, passed to qsort. */
+
+static int
+sort_tu_by_abbrev_offset (const void *ap, const void *bp)
+{
+ const struct tu_abbrev_offset * const *a = ap;
+ const struct tu_abbrev_offset * const *b = bp;
+ unsigned int aoff = (*a)->abbrev_offset.sect_off;
+ unsigned int boff = (*b)->abbrev_offset.sect_off;
+
+ return (aoff > boff) - (aoff < boff);
+}
+
+/* Efficiently read all the type units.
+ This does the bulk of the work for build_type_psymtabs.
+
+ The efficiency is because we sort TUs by the abbrev table they use and
+ only read each abbrev table once. In one program there are 200K TUs
+ sharing 8K abbrev tables.
+
+ The main purpose of this function is to support building the
+ dwarf2_per_objfile->type_unit_groups table.
+ TUs typically share the DW_AT_stmt_list of the CU they came from, so we
+ can collapse the search space by grouping them by stmt_list.
+ The savings can be significant, in the same program from above the 200K TUs
+ share 8K stmt_list tables.
+
+ FUNC is expected to call get_type_unit_group, which will create the
+ struct type_unit_group if necessary and add it to
+ dwarf2_per_objfile->type_unit_groups. */
+
+static void
+build_type_psymtabs_1 (void)
+{
+ struct objfile *objfile = dwarf2_per_objfile->objfile;
+ struct tu_stats *tu_stats = &dwarf2_per_objfile->tu_stats;
+ struct cleanup *cleanups;
+ struct abbrev_table *abbrev_table;
+ sect_offset abbrev_offset;
+ struct tu_abbrev_offset *sorted_by_abbrev;
+ struct type_unit_group **iter;
+ int i;
+
+ /* It's up to the caller to not call us multiple times. */
+ gdb_assert (dwarf2_per_objfile->type_unit_groups == NULL);
+
+ if (dwarf2_per_objfile->n_type_units == 0)
+ return;
+
+ /* TUs typically share abbrev tables, and there can be way more TUs than
+ abbrev tables. Sort by abbrev table to reduce the number of times we
+ read each abbrev table in.
+ Alternatives are to punt or to maintain a cache of abbrev tables.
+ This is simpler and efficient enough for now.
+
+ Later we group TUs by their DW_AT_stmt_list value (as this defines the
+ symtab to use). Typically TUs with the same abbrev offset have the same
+ stmt_list value too so in practice this should work well.
+
+ The basic algorithm here is:
+
+ sort TUs by abbrev table
+ for each TU with same abbrev table:
+ read abbrev table if first user
+ read TU top level DIE
+ [IWBN if DWO skeletons had DW_AT_stmt_list]
+ call FUNC */
+
+ if (dwarf_read_debug)
+ fprintf_unfiltered (gdb_stdlog, "Building type unit groups ...\n");
+
+ /* Sort in a separate table to maintain the order of all_type_units
+ for .gdb_index: TU indices directly index all_type_units. */
+ sorted_by_abbrev = XNEWVEC (struct tu_abbrev_offset,
+ dwarf2_per_objfile->n_type_units);
+ for (i = 0; i < dwarf2_per_objfile->n_type_units; ++i)
+ {
+ struct signatured_type *sig_type = dwarf2_per_objfile->all_type_units[i];
+
+ sorted_by_abbrev[i].sig_type = sig_type;
+ sorted_by_abbrev[i].abbrev_offset =
+ read_abbrev_offset (sig_type->per_cu.section,
+ sig_type->per_cu.offset);
+ }
+ cleanups = make_cleanup (xfree, sorted_by_abbrev);
+ qsort (sorted_by_abbrev, dwarf2_per_objfile->n_type_units,
+ sizeof (struct tu_abbrev_offset), sort_tu_by_abbrev_offset);
+
+ abbrev_offset.sect_off = ~(unsigned) 0;
+ abbrev_table = NULL;
+ make_cleanup (abbrev_table_free_cleanup, &abbrev_table);
+
+ for (i = 0; i < dwarf2_per_objfile->n_type_units; ++i)
+ {
+ const struct tu_abbrev_offset *tu = &sorted_by_abbrev[i];
+
+ /* Switch to the next abbrev table if necessary. */
+ if (abbrev_table == NULL
+ || tu->abbrev_offset.sect_off != abbrev_offset.sect_off)
+ {
+ if (abbrev_table != NULL)
+ {
+ abbrev_table_free (abbrev_table);
+ /* Reset to NULL in case abbrev_table_read_table throws
+ an error: abbrev_table_free_cleanup will get called. */
+ abbrev_table = NULL;
+ }
+ abbrev_offset = tu->abbrev_offset;
+ abbrev_table =
+ abbrev_table_read_table (&dwarf2_per_objfile->abbrev,
+ abbrev_offset);
+ ++tu_stats->nr_uniq_abbrev_tables;
+ }
+
+ init_cutu_and_read_dies (&tu->sig_type->per_cu, abbrev_table, 0, 0,
+ build_type_psymtabs_reader, NULL);
+ }
- prepare_one_comp_unit (cu, type_unit_die, language_minimal);
- cu->list_in_scope = &file_symbols;
- pst = create_partial_symtab (per_cu, "");
- pst->anonymous = 1;
+ do_cleanups (cleanups);
+}
- first_die = load_partial_dies (reader, info_ptr, 1);
+/* Print collected type unit statistics. */
- lowpc = (CORE_ADDR) -1;
- highpc = (CORE_ADDR) 0;
- scan_partial_symbols (first_die, &lowpc, &highpc, 0, cu);
+static void
+print_tu_stats (void)
+{
+ struct tu_stats *tu_stats = &dwarf2_per_objfile->tu_stats;
- pst->n_global_syms = objfile->global_psymbols.next -
- (objfile->global_psymbols.list + pst->globals_offset);
- pst->n_static_syms = objfile->static_psymbols.next -
- (objfile->static_psymbols.list + pst->statics_offset);
- sort_pst_symbols (objfile, pst);
+ fprintf_unfiltered (gdb_stdlog, "Type unit statistics:\n");
+ fprintf_unfiltered (gdb_stdlog, " %d TUs\n",
+ dwarf2_per_objfile->n_type_units);
+ fprintf_unfiltered (gdb_stdlog, " %d uniq abbrev tables\n",
+ tu_stats->nr_uniq_abbrev_tables);
+ fprintf_unfiltered (gdb_stdlog, " %d symtabs from stmt_list entries\n",
+ tu_stats->nr_symtabs);
+ fprintf_unfiltered (gdb_stdlog, " %d symtab sharers\n",
+ tu_stats->nr_symtab_sharers);
+ fprintf_unfiltered (gdb_stdlog, " %d type units without a stmt_list\n",
+ tu_stats->nr_stmt_less_type_units);
+ fprintf_unfiltered (gdb_stdlog, " %d all_type_units reallocs\n",
+ tu_stats->nr_all_type_units_reallocs);
}
/* Traversal function for build_type_psymtabs. */
if (! create_all_type_units (objfile))
return;
- build_type_unit_groups (build_type_psymtabs_reader, NULL);
+ build_type_psymtabs_1 ();
+}
- /* Now that all TUs have been processed we can fill in the dependencies. */
- htab_traverse_noresize (dwarf2_per_objfile->type_unit_groups,
- build_type_psymtab_dependencies, NULL);
+/* Traversal function for process_skeletonless_type_unit.
+ Read a TU in a DWO file and build partial symbols for it. */
+
+static int
+process_skeletonless_type_unit (void **slot, void *info)
+{
+ struct dwo_unit *dwo_unit = (struct dwo_unit *) *slot;
+ struct objfile *objfile = info;
+ struct signatured_type find_entry, *entry;
+
+ /* If this TU doesn't exist in the global table, add it and read it in. */
+
+ if (dwarf2_per_objfile->signatured_types == NULL)
+ {
+ dwarf2_per_objfile->signatured_types
+ = allocate_signatured_type_table (objfile);
+ }
+
+ find_entry.signature = dwo_unit->signature;
+ slot = htab_find_slot (dwarf2_per_objfile->signatured_types, &find_entry,
+ INSERT);
+ /* If we've already seen this type there's nothing to do. What's happening
+ is we're doing our own version of comdat-folding here. */
+ if (*slot != NULL)
+ return 1;
+
+ /* This does the job that create_all_type_units would have done for
+ this TU. */
+ entry = add_type_unit (dwo_unit->signature, slot);
+ fill_in_sig_entry_from_dwo_entry (objfile, entry, dwo_unit);
+ *slot = entry;
+
+ /* This does the job that build_type_psymtabs_1 would have done. */
+ init_cutu_and_read_dies (&entry->per_cu, NULL, 0, 0,
+ build_type_psymtabs_reader, NULL);
+
+ return 1;
+}
+
+/* Traversal function for process_skeletonless_type_units. */
+
+static int
+process_dwo_file_for_skeletonless_type_units (void **slot, void *info)
+{
+ struct dwo_file *dwo_file = (struct dwo_file *) *slot;
+
+ if (dwo_file->tus != NULL)
+ {
+ htab_traverse_noresize (dwo_file->tus,
+ process_skeletonless_type_unit, info);
+ }
+
+ return 1;
+}
+
+/* Scan all TUs of DWO files, verifying we've processed them.
+ This is needed in case a TU was emitted without its skeleton.
+ Note: This can't be done until we know what all the DWO files are. */
+
+static void
+process_skeletonless_type_units (struct objfile *objfile)
+{
+ /* Skeletonless TUs in DWP files without .gdb_index is not supported yet. */
+ if (get_dwp_file () == NULL
+ && dwarf2_per_objfile->dwo_files != NULL)
+ {
+ htab_traverse_noresize (dwarf2_per_objfile->dwo_files,
+ process_dwo_file_for_skeletonless_type_units,
+ objfile);
+ }
}
/* A cleanup function that clears objfile's psymtabs_addrmap field. */
for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
{
- struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
+ struct dwarf2_per_cu_data *per_cu = dw2_get_cutu (i);
struct partial_symtab *pst = per_cu->v.psymtab;
int j;
struct obstack temp_obstack;
int i;
- if (dwarf2_read_debug)
+ if (dwarf_read_debug)
{
fprintf_unfiltered (gdb_stdlog, "Building psymtabs of objfile %s ...\n",
objfile_name (objfile));
for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
{
- struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
+ struct dwarf2_per_cu_data *per_cu = dw2_get_cutu (i);
process_psymtab_comp_unit (per_cu, 0, language_minimal);
}
+ /* This has to wait until we read the CUs, we need the list of DWOs. */
+ process_skeletonless_type_units (objfile);
+
+ /* Now that all TUs have been processed we can fill in the dependencies. */
+ if (dwarf2_per_objfile->type_unit_groups != NULL)
+ {
+ htab_traverse_noresize (dwarf2_per_objfile->type_unit_groups,
+ build_type_psymtab_dependencies, NULL);
+ }
+
+ if (dwarf_read_debug)
+ print_tu_stats ();
+
set_partial_user (objfile);
objfile->psymtabs_addrmap = addrmap_create_fixed (objfile->psymtabs_addrmap,
do_cleanups (back_to);
- if (dwarf2_read_debug)
+ if (dwarf_read_debug)
fprintf_unfiltered (gdb_stdlog, "Done building psymtabs of %s\n",
objfile_name (objfile));
}
const gdb_byte *info_ptr;
bfd *abfd = get_section_bfd_owner (section);
- if (dwarf2_read_debug)
+ if (dwarf_read_debug)
fprintf_unfiltered (gdb_stdlog, "Reading %s for %s\n",
get_section_name (section),
get_section_file_name (section));
}
/* Process all loaded DIEs for compilation unit CU, starting at
- FIRST_DIE. The caller should pass NEED_PC == 1 if the compilation
+ FIRST_DIE. The caller should pass SET_ADDRMAP == 1 if the compilation
unit DIE did not have PC info (DW_AT_low_pc and DW_AT_high_pc, or
- DW_AT_ranges). If NEED_PC is set, then this function will set
- *LOWPC and *HIGHPC to the lowest and highest PC values found in CU
- and record the covered ranges in the addrmap. */
+ DW_AT_ranges). See the comments of add_partial_subprogram on how
+ SET_ADDRMAP is used and how *LOWPC and *HIGHPC are updated. */
static void
scan_partial_symbols (struct partial_die_info *first_die, CORE_ADDR *lowpc,
- CORE_ADDR *highpc, int need_pc, struct dwarf2_cu *cu)
+ CORE_ADDR *highpc, int set_addrmap,
+ struct dwarf2_cu *cu)
{
struct partial_die_info *pdi;
switch (pdi->tag)
{
case DW_TAG_subprogram:
- add_partial_subprogram (pdi, lowpc, highpc, need_pc, cu);
+ add_partial_subprogram (pdi, lowpc, highpc, set_addrmap, cu);
break;
case DW_TAG_constant:
case DW_TAG_variable:
add_partial_symbol (pdi, cu);
break;
case DW_TAG_namespace:
- add_partial_namespace (pdi, lowpc, highpc, need_pc, cu);
+ add_partial_namespace (pdi, lowpc, highpc, set_addrmap, cu);
break;
case DW_TAG_module:
- add_partial_module (pdi, lowpc, highpc, need_pc, cu);
+ add_partial_module (pdi, lowpc, highpc, set_addrmap, cu);
break;
case DW_TAG_imported_unit:
{
add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
{
struct objfile *objfile = cu->objfile;
+ struct gdbarch *gdbarch = get_objfile_arch (objfile);
CORE_ADDR addr = 0;
const char *actual_name = NULL;
CORE_ADDR baseaddr;
switch (pdi->tag)
{
case DW_TAG_subprogram:
+ addr = gdbarch_adjust_dwarf2_addr (gdbarch, pdi->lowpc + baseaddr);
if (pdi->is_external || cu->language == language_ada)
{
/* brobecker/2007-12-26: Normally, only "external" DIEs are part
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,
- mst_text, objfile); */
+ /* prim_record_minimal_symbol (actual_name, addr, mst_text,
+ objfile); */
add_psymbol_to_list (actual_name, strlen (actual_name),
built_actual_name != NULL,
VAR_DOMAIN, LOC_BLOCK,
&objfile->global_psymbols,
- 0, pdi->lowpc + baseaddr,
- cu->language, objfile);
+ 0, addr, cu->language, objfile);
}
else
{
- /* prim_record_minimal_symbol (actual_name, pdi->lowpc + baseaddr,
- mst_file_text, objfile); */
+ /* prim_record_minimal_symbol (actual_name, addr, mst_file_text,
+ objfile); */
add_psymbol_to_list (actual_name, strlen (actual_name),
built_actual_name != NULL,
VAR_DOMAIN, LOC_BLOCK,
&objfile->static_psymbols,
- 0, pdi->lowpc + baseaddr,
- cu->language, objfile);
+ 0, addr, cu->language, objfile);
}
break;
case DW_TAG_constant:
}
else
{
- /* Static Variable. Skip symbols without location descriptors. */
- if (pdi->d.locdesc == NULL)
+ int has_loc = pdi->d.locdesc != NULL;
+
+ /* Static Variable. Skip symbols whose value we cannot know (those
+ without location descriptors or constant values). */
+ if (!has_loc && !pdi->has_const_value)
{
xfree (built_actual_name);
return;
}
+
/* prim_record_minimal_symbol (actual_name, addr + baseaddr,
mst_file_data, objfile); */
add_psymbol_to_list (actual_name, strlen (actual_name),
built_actual_name != NULL,
VAR_DOMAIN, LOC_STATIC,
&objfile->static_psymbols,
- 0, addr + baseaddr,
+ 0,
+ has_loc ? addr + baseaddr : (CORE_ADDR) 0,
cu->language, objfile);
}
break;
static void
add_partial_namespace (struct partial_die_info *pdi,
CORE_ADDR *lowpc, CORE_ADDR *highpc,
- int need_pc, struct dwarf2_cu *cu)
+ int set_addrmap, struct dwarf2_cu *cu)
{
/* Add a symbol for the namespace. */
/* Now scan partial symbols in that namespace. */
if (pdi->has_children)
- scan_partial_symbols (pdi->die_child, lowpc, highpc, need_pc, cu);
+ scan_partial_symbols (pdi->die_child, lowpc, highpc, set_addrmap, cu);
}
/* Read a partial die corresponding to a Fortran module. */
static void
add_partial_module (struct partial_die_info *pdi, CORE_ADDR *lowpc,
- CORE_ADDR *highpc, int need_pc, struct dwarf2_cu *cu)
+ CORE_ADDR *highpc, int set_addrmap, struct dwarf2_cu *cu)
{
/* Add a symbol for the namespace. */
/* Now scan partial symbols in that module. */
if (pdi->has_children)
- scan_partial_symbols (pdi->die_child, lowpc, highpc, need_pc, cu);
+ scan_partial_symbols (pdi->die_child, lowpc, highpc, set_addrmap, cu);
}
/* Read a partial die corresponding to a subprogram and create a partial
symbol for that subprogram. When the CU language allows it, this
routine also defines a partial symbol for each nested subprogram
- that this subprogram contains.
+ that this subprogram contains. If SET_ADDRMAP is true, record the
+ covered ranges in the addrmap. Set *LOWPC and *HIGHPC to the lowest
+ and highest PC values found in PDI.
- DIE my also be a lexical block, in which case we simply search
- recursively for suprograms defined inside that lexical block.
+ PDI may also be a lexical block, in which case we simply search
+ recursively for subprograms defined inside that lexical block.
Again, this is only performed when the CU language allows this
type of definitions. */
static void
add_partial_subprogram (struct partial_die_info *pdi,
CORE_ADDR *lowpc, CORE_ADDR *highpc,
- int need_pc, struct dwarf2_cu *cu)
+ int set_addrmap, struct dwarf2_cu *cu)
{
if (pdi->tag == DW_TAG_subprogram)
{
*lowpc = pdi->lowpc;
if (pdi->highpc > *highpc)
*highpc = pdi->highpc;
- if (need_pc)
+ if (set_addrmap)
{
- CORE_ADDR baseaddr;
struct objfile *objfile = cu->objfile;
+ struct gdbarch *gdbarch = get_objfile_arch (objfile);
+ CORE_ADDR baseaddr;
+ CORE_ADDR highpc;
+ CORE_ADDR lowpc;
baseaddr = ANOFFSET (objfile->section_offsets,
SECT_OFF_TEXT (objfile));
- addrmap_set_empty (objfile->psymtabs_addrmap,
- pdi->lowpc + baseaddr,
- pdi->highpc - 1 + baseaddr,
+ lowpc = gdbarch_adjust_dwarf2_addr (gdbarch,
+ pdi->lowpc + baseaddr);
+ highpc = gdbarch_adjust_dwarf2_addr (gdbarch,
+ pdi->highpc + baseaddr);
+ addrmap_set_empty (objfile->psymtabs_addrmap, lowpc, highpc - 1,
cu->per_cu->v.psymtab);
}
}
fixup_partial_die (pdi, cu);
if (pdi->tag == DW_TAG_subprogram
|| pdi->tag == DW_TAG_lexical_block)
- add_partial_subprogram (pdi, lowpc, highpc, need_pc, cu);
+ add_partial_subprogram (pdi, lowpc, highpc, set_addrmap, cu);
pdi = pdi->die_sibling;
}
}
abbrev = abbrev_table_lookup_abbrev (cu->abbrev_table, abbrev_number);
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 %s"
+ " at offset 0x%x [in module %s]"),
+ abbrev_number, cu->per_cu->is_debug_types ? "TU" : "CU",
+ cu->header.offset.sect_off, bfd_get_filename (abfd));
}
return abbrev;
if (sibling_ptr < info_ptr)
complaint (&symfile_complaints,
_("DW_AT_sibling points backwards"));
+ else if (sibling_ptr > reader->buffer_end)
+ dwarf2_section_buffer_overflow_complaint (reader->die_section);
else
return sibling_ptr;
}
{
struct dwarf2_queue_item *item, *next_item;
- if (dwarf2_read_debug)
+ if (dwarf_read_debug)
{
fprintf_unfiltered (gdb_stdlog,
"Expanding one or more symtabs of objfile %s ...\n",
for (item = dwarf2_queue; item != NULL; dwarf2_queue = item = next_item)
{
if (dwarf2_per_objfile->using_index
- ? !item->per_cu->v.quick->symtab
+ ? !item->per_cu->v.quick->compunit_symtab
: (item->per_cu->v.psymtab && !item->per_cu->v.psymtab->readin))
{
struct dwarf2_per_cu_data *per_cu = item->per_cu;
debug_print_threshold = 1;
}
- if (dwarf2_read_debug >= debug_print_threshold)
+ if (dwarf_read_debug >= debug_print_threshold)
fprintf_unfiltered (gdb_stdlog, "Expanding symtab of %s\n", buf);
if (per_cu->is_debug_types)
else
process_full_comp_unit (per_cu, item->pretend_language);
- if (dwarf2_read_debug >= debug_print_threshold)
+ if (dwarf_read_debug >= debug_print_threshold)
fprintf_unfiltered (gdb_stdlog, "Done expanding %s\n", buf);
}
dwarf2_queue_tail = NULL;
- if (dwarf2_read_debug)
+ if (dwarf_read_debug)
{
fprintf_unfiltered (gdb_stdlog, "Done expanding symtabs of %s.\n",
objfile_name (dwarf2_per_objfile->objfile));
struct fn_fieldlist *fn_flp
= &TYPE_FN_FIELDLIST (mi->type, mi->fnfield_index);
physname = dwarf2_physname (mi->name, mi->die, cu);
- fn_flp->fn_fields[mi->index].physname = physname ? physname : "";
+ TYPE_FN_FIELD_PHYSNAME (fn_flp->fn_fields, mi->index)
+ = physname ? physname : "";
}
}
if (strcmp (package_name, this_package_name) != 0)
complaint (&symfile_complaints,
_("Symtab %s has objects from two different Go packages: %s and %s"),
- (SYMBOL_SYMTAB (sym)
- ? symtab_to_filename_for_display (SYMBOL_SYMTAB (sym))
+ (symbol_symtab (sym) != NULL
+ ? symtab_to_filename_for_display
+ (symbol_symtab (sym))
: objfile_name (cu->objfile)),
this_package_name, package_name);
xfree (this_package_name);
if (package_name != NULL)
{
struct objfile *objfile = cu->objfile;
- const char *saved_package_name = obstack_copy0 (&objfile->objfile_obstack,
- package_name,
- strlen (package_name));
+ const char *saved_package_name
+ = obstack_copy0 (&objfile->per_bfd->storage_obstack,
+ package_name,
+ strlen (package_name));
struct type *type = init_type (TYPE_CODE_MODULE, 0, 0,
saved_package_name, objfile);
struct symbol *sym;
/* Return the symtab for PER_CU. This works properly regardless of
whether we're using the index or psymtabs. */
-static struct symtab *
-get_symtab (struct dwarf2_per_cu_data *per_cu)
+static struct compunit_symtab *
+get_compunit_symtab (struct dwarf2_per_cu_data *per_cu)
{
return (dwarf2_per_objfile->using_index
- ? per_cu->v.quick->symtab
- : per_cu->v.psymtab->symtab);
+ ? per_cu->v.quick->compunit_symtab
+ : per_cu->v.psymtab->compunit_symtab);
}
/* A helper function for computing the list of all symbol tables
included by PER_CU. */
static void
-recursively_compute_inclusions (VEC (symtab_ptr) **result,
+recursively_compute_inclusions (VEC (compunit_symtab_ptr) **result,
htab_t all_children, htab_t all_type_symtabs,
struct dwarf2_per_cu_data *per_cu,
- struct symtab *immediate_parent)
+ struct compunit_symtab *immediate_parent)
{
void **slot;
int ix;
- struct symtab *symtab;
+ struct compunit_symtab *cust;
struct dwarf2_per_cu_data *iter;
slot = htab_find_slot (all_children, per_cu, INSERT);
*slot = per_cu;
/* Only add a CU if it has a symbol table. */
- symtab = get_symtab (per_cu);
- if (symtab != NULL)
+ cust = get_compunit_symtab (per_cu);
+ if (cust != NULL)
{
/* If this is a type unit only add its symbol table if we haven't
seen it yet (type unit per_cu's can share symtabs). */
if (per_cu->is_debug_types)
{
- slot = htab_find_slot (all_type_symtabs, symtab, INSERT);
+ slot = htab_find_slot (all_type_symtabs, cust, INSERT);
if (*slot == NULL)
{
- *slot = symtab;
- VEC_safe_push (symtab_ptr, *result, symtab);
- if (symtab->user == NULL)
- symtab->user = immediate_parent;
+ *slot = cust;
+ VEC_safe_push (compunit_symtab_ptr, *result, cust);
+ if (cust->user == NULL)
+ cust->user = immediate_parent;
}
}
else
{
- VEC_safe_push (symtab_ptr, *result, symtab);
- if (symtab->user == NULL)
- symtab->user = immediate_parent;
+ VEC_safe_push (compunit_symtab_ptr, *result, cust);
+ if (cust->user == NULL)
+ cust->user = immediate_parent;
}
}
++ix)
{
recursively_compute_inclusions (result, all_children,
- all_type_symtabs, iter, symtab);
+ all_type_symtabs, iter, cust);
}
}
-/* Compute the symtab 'includes' fields for the symtab related to
+/* Compute the compunit_symtab 'includes' fields for the compunit_symtab of
PER_CU. */
static void
-compute_symtab_includes (struct dwarf2_per_cu_data *per_cu)
+compute_compunit_symtab_includes (struct dwarf2_per_cu_data *per_cu)
{
gdb_assert (! per_cu->is_debug_types);
{
int ix, len;
struct dwarf2_per_cu_data *per_cu_iter;
- struct symtab *symtab_iter;
- VEC (symtab_ptr) *result_symtabs = NULL;
+ struct compunit_symtab *compunit_symtab_iter;
+ VEC (compunit_symtab_ptr) *result_symtabs = NULL;
htab_t all_children, all_type_symtabs;
- struct symtab *symtab = get_symtab (per_cu);
+ struct compunit_symtab *cust = get_compunit_symtab (per_cu);
/* If we don't have a symtab, we can just skip this case. */
- if (symtab == NULL)
+ if (cust == NULL)
return;
all_children = htab_create_alloc (1, htab_hash_pointer, htab_eq_pointer,
{
recursively_compute_inclusions (&result_symtabs, all_children,
all_type_symtabs, per_cu_iter,
- symtab);
+ cust);
}
/* Now we have a transitive closure of all the included symtabs. */
- len = VEC_length (symtab_ptr, result_symtabs);
- symtab->includes
+ len = VEC_length (compunit_symtab_ptr, result_symtabs);
+ cust->includes
= obstack_alloc (&dwarf2_per_objfile->objfile->objfile_obstack,
(len + 1) * sizeof (struct symtab *));
for (ix = 0;
- VEC_iterate (symtab_ptr, result_symtabs, ix, symtab_iter);
+ VEC_iterate (compunit_symtab_ptr, result_symtabs, ix,
+ compunit_symtab_iter);
++ix)
- symtab->includes[ix] = symtab_iter;
- symtab->includes[len] = NULL;
+ cust->includes[ix] = compunit_symtab_iter;
+ cust->includes[len] = NULL;
- VEC_free (symtab_ptr, result_symtabs);
+ VEC_free (compunit_symtab_ptr, result_symtabs);
htab_delete (all_children);
htab_delete (all_type_symtabs);
}
++ix)
{
if (! iter->is_debug_types)
- compute_symtab_includes (iter);
+ compute_compunit_symtab_includes (iter);
}
VEC_free (dwarf2_per_cu_ptr, dwarf2_per_objfile->just_read_cus);
{
struct dwarf2_cu *cu = per_cu->cu;
struct objfile *objfile = per_cu->objfile;
+ struct gdbarch *gdbarch = get_objfile_arch (objfile);
CORE_ADDR lowpc, highpc;
- struct symtab *symtab;
+ struct compunit_symtab *cust;
struct cleanup *back_to, *delayed_list_cleanup;
CORE_ADDR baseaddr;
struct block *static_block;
+ CORE_ADDR addr;
baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
it, by scanning the DIE's below the compilation unit. */
get_scope_pc_bounds (cu->dies, &lowpc, &highpc, cu);
- static_block
- = end_symtab_get_static_block (highpc + baseaddr, objfile, 0, 1);
+ addr = gdbarch_adjust_dwarf2_addr (gdbarch, highpc + baseaddr);
+ static_block = end_symtab_get_static_block (addr, 0, 1);
/* If the comp unit has DW_AT_ranges, it may have discontiguous ranges.
Also, DW_AT_ranges may record ranges not belonging to any child DIEs
this comp unit. */
dwarf2_record_block_ranges (cu->dies, static_block, baseaddr, cu);
- symtab = end_symtab_from_static_block (static_block, objfile,
- SECT_OFF_TEXT (objfile), 0);
+ cust = end_symtab_from_static_block (static_block,
+ SECT_OFF_TEXT (objfile), 0);
- if (symtab != NULL)
+ if (cust != NULL)
{
int gcc_4_minor = producer_is_gcc_ge_4 (cu->producer);
/* 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;
+ if (!(cu->language == language_c
+ && COMPUNIT_FILETABS (cust)->language != language_c))
+ COMPUNIT_FILETABS (cust)->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
options - this waits on GCC PR other/32998 (-frecord-gcc-switches).
*/
if (cu->has_loclist && gcc_4_minor >= 5)
- symtab->locations_valid = 1;
+ cust->locations_valid = 1;
if (gcc_4_minor >= 5)
- symtab->epilogue_unwind_valid = 1;
+ cust->epilogue_unwind_valid = 1;
- symtab->call_site_htab = cu->call_site_htab;
+ cust->call_site_htab = cu->call_site_htab;
}
if (dwarf2_per_objfile->using_index)
- per_cu->v.quick->symtab = symtab;
+ per_cu->v.quick->compunit_symtab = cust;
else
{
struct partial_symtab *pst = per_cu->v.psymtab;
- pst->symtab = symtab;
+ pst->compunit_symtab = cust;
pst->readin = 1;
}
{
struct dwarf2_cu *cu = per_cu->cu;
struct objfile *objfile = per_cu->objfile;
- struct symtab *symtab;
+ struct compunit_symtab *cust;
struct cleanup *back_to, *delayed_list_cleanup;
struct signatured_type *sig_type;
If this is the first TU to use this symtab, complete the construction
of it with end_expandable_symtab. Otherwise, complete the addition of
this TU's symbols to the existing symtab. */
- if (sig_type->type_unit_group->primary_symtab == NULL)
+ if (sig_type->type_unit_group->compunit_symtab == NULL)
{
- symtab = end_expandable_symtab (0, objfile, SECT_OFF_TEXT (objfile));
- sig_type->type_unit_group->primary_symtab = symtab;
+ cust = end_expandable_symtab (0, SECT_OFF_TEXT (objfile));
+ sig_type->type_unit_group->compunit_symtab = cust;
- if (symtab != NULL)
+ if (cust != NULL)
{
/* 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;
+ if (!(cu->language == language_c
+ && COMPUNIT_FILETABS (cust)->language != language_c))
+ COMPUNIT_FILETABS (cust)->language = cu->language;
}
}
else
{
- augment_type_symtab (objfile,
- sig_type->type_unit_group->primary_symtab);
- symtab = sig_type->type_unit_group->primary_symtab;
+ augment_type_symtab ();
+ cust = sig_type->type_unit_group->compunit_symtab;
}
if (dwarf2_per_objfile->using_index)
- per_cu->v.quick->symtab = symtab;
+ per_cu->v.quick->compunit_symtab = cust;
else
{
struct partial_symtab *pst = per_cu->v.psymtab;
- pst->symtab = symtab;
+ pst->compunit_symtab = cust;
pst->readin = 1;
}
}
}
+/* Reset the in_process bit of a die. */
+
+static void
+reset_die_in_process (void *arg)
+{
+ struct die_info *die = arg;
+
+ die->in_process = 0;
+}
+
/* Process a die and its children. */
static void
process_die (struct die_info *die, struct dwarf2_cu *cu)
{
+ struct cleanup *in_process;
+
+ /* We should only be processing those not already in process. */
+ gdb_assert (!die->in_process);
+
+ die->in_process = 1;
+ in_process = make_cleanup (reset_die_in_process,die);
+
switch (die->tag)
{
case DW_TAG_padding:
new_symbol (die, NULL, cu);
break;
}
+
+ do_cleanups (in_process);
}
\f
/* DWARF name computation. */
case DW_TAG_enumeration_type:
case DW_TAG_enumerator:
case DW_TAG_subprogram:
+ case DW_TAG_inlined_subroutine:
case DW_TAG_member:
case DW_TAG_imported_declaration:
return 1;
long length;
const char *prefix;
struct ui_file *buf;
+ char *intermediate_name;
+ const char *canonical_name = NULL;
prefix = determine_prefix (die, cu);
buf = mem_fileopen ();
}
}
- name = ui_file_obsavestring (buf, &objfile->objfile_obstack,
- &length);
+ intermediate_name = ui_file_xstrdup (buf, &length);
ui_file_delete (buf);
if (cu->language == language_cplus)
- {
- const char *cname
- = dwarf2_canonicalize_name (name, cu,
- &objfile->objfile_obstack);
+ canonical_name
+ = dwarf2_canonicalize_name (intermediate_name, cu,
+ &objfile->per_bfd->storage_obstack);
+
+ /* If we only computed INTERMEDIATE_NAME, or if
+ INTERMEDIATE_NAME is already canonical, then we need to
+ copy it to the appropriate obstack. */
+ if (canonical_name == NULL || canonical_name == intermediate_name)
+ name = obstack_copy0 (&objfile->per_bfd->storage_obstack,
+ intermediate_name,
+ strlen (intermediate_name));
+ else
+ name = canonical_name;
- if (cname != NULL)
- name = cname;
- }
+ xfree (intermediate_name);
}
}
/* Return the fully qualified name of DIE, based on its DW_AT_name.
If scope qualifiers are appropriate they will be added. The result
- will be allocated on the objfile_obstack, or NULL if the DIE does
+ will be allocated on the storage_obstack, or NULL if the DIE does
not have a name. NAME may either be from a previous call to
dwarf2_name or NULL.
retval = canon;
if (need_copy)
- retval = obstack_copy0 (&objfile->objfile_obstack, retval, strlen (retval));
+ retval = obstack_copy0 (&objfile->per_bfd->storage_obstack,
+ retval, strlen (retval));
do_cleanups (back_to);
return retval;
/* Handle DW_AT_stmt_list for a compilation unit.
DIE is the DW_TAG_compile_unit die for CU.
- COMP_DIR is the compilation directory.
- WANT_LINE_INFO is non-zero if the pc/line-number mapping is needed. */
+ COMP_DIR is the compilation directory. LOWPC is passed to
+ dwarf_decode_lines. See dwarf_decode_lines comments about it. */
static void
handle_DW_AT_stmt_list (struct die_info *die, struct dwarf2_cu *cu,
- const char *comp_dir) /* ARI: editCase function */
+ const char *comp_dir, CORE_ADDR lowpc) /* ARI: editCase function */
{
+ struct objfile *objfile = dwarf2_per_objfile->objfile;
struct attribute *attr;
+ unsigned int line_offset;
+ struct line_header line_header_local;
+ hashval_t line_header_local_hash;
+ unsigned u;
+ void **slot;
+ int decode_mapping;
gdb_assert (! cu->per_cu->is_debug_types);
attr = dwarf2_attr (die, DW_AT_stmt_list, cu);
- if (attr)
+ if (attr == NULL)
+ return;
+
+ line_offset = DW_UNSND (attr);
+
+ /* The line header hash table is only created if needed (it exists to
+ prevent redundant reading of the line table for partial_units).
+ If we're given a partial_unit, we'll need it. If we're given a
+ compile_unit, then use the line header hash table if it's already
+ created, but don't create one just yet. */
+
+ if (dwarf2_per_objfile->line_header_hash == NULL
+ && die->tag == DW_TAG_partial_unit)
+ {
+ dwarf2_per_objfile->line_header_hash
+ = htab_create_alloc_ex (127, line_header_hash_voidp,
+ line_header_eq_voidp,
+ free_line_header_voidp,
+ &objfile->objfile_obstack,
+ hashtab_obstack_allocate,
+ dummy_obstack_deallocate);
+ }
+
+ line_header_local.offset.sect_off = line_offset;
+ line_header_local.offset_in_dwz = cu->per_cu->is_dwz;
+ line_header_local_hash = line_header_hash (&line_header_local);
+ if (dwarf2_per_objfile->line_header_hash != NULL)
{
- unsigned int line_offset = DW_UNSND (attr);
- struct line_header *line_header
- = dwarf_decode_line_header (line_offset, cu);
+ slot = htab_find_slot_with_hash (dwarf2_per_objfile->line_header_hash,
+ &line_header_local,
+ line_header_local_hash, NO_INSERT);
- if (line_header)
+ /* For DW_TAG_compile_unit we need info like symtab::linetable which
+ is not present in *SLOT (since if there is something in *SLOT then
+ it will be for a partial_unit). */
+ if (die->tag == DW_TAG_partial_unit && slot != NULL)
{
- cu->line_header = line_header;
- make_cleanup (free_cu_line_header, cu);
- dwarf_decode_lines (line_header, comp_dir, cu, NULL, 1);
+ gdb_assert (*slot != NULL);
+ cu->line_header = *slot;
+ return;
}
}
+
+ /* dwarf_decode_line_header does not yet provide sufficient information.
+ We always have to call also dwarf_decode_lines for it. */
+ cu->line_header = dwarf_decode_line_header (line_offset, cu);
+ if (cu->line_header == NULL)
+ return;
+
+ if (dwarf2_per_objfile->line_header_hash == NULL)
+ slot = NULL;
+ else
+ {
+ slot = htab_find_slot_with_hash (dwarf2_per_objfile->line_header_hash,
+ &line_header_local,
+ line_header_local_hash, INSERT);
+ gdb_assert (slot != NULL);
+ }
+ if (slot != NULL && *slot == NULL)
+ {
+ /* This newly decoded line number information unit will be owned
+ by line_header_hash hash table. */
+ *slot = cu->line_header;
+ }
+ else
+ {
+ /* We cannot free any current entry in (*slot) as that struct line_header
+ may be already used by multiple CUs. Create only temporary decoded
+ line_header for this CU - it may happen at most once for each line
+ number information unit. And if we're not using line_header_hash
+ then this is what we want as well. */
+ gdb_assert (die->tag != DW_TAG_partial_unit);
+ make_cleanup (free_cu_line_header, cu);
+ }
+ decode_mapping = (die->tag != DW_TAG_partial_unit);
+ dwarf_decode_lines (cu->line_header, comp_dir, cu, NULL, lowpc,
+ decode_mapping);
}
/* Process DW_TAG_compile_unit or DW_TAG_partial_unit. */
read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
{
struct objfile *objfile = dwarf2_per_objfile->objfile;
+ struct gdbarch *gdbarch = get_objfile_arch (objfile);
struct cleanup *back_to = make_cleanup (null_cleanup, 0);
CORE_ADDR lowpc = ((CORE_ADDR) -1);
CORE_ADDR highpc = ((CORE_ADDR) 0);
from finish_block. */
if (lowpc == ((CORE_ADDR) -1))
lowpc = highpc;
- lowpc += baseaddr;
- highpc += baseaddr;
+ lowpc = gdbarch_adjust_dwarf2_addr (gdbarch, lowpc + baseaddr);
find_file_and_directory (die, cu, &name, &comp_dir);
/* Decode line number information if present. We do this before
processing child DIEs, so that the line header table is available
for DW_AT_decl_file. */
- handle_DW_AT_stmt_list (die, cu, comp_dir);
+ handle_DW_AT_stmt_list (die, cu, comp_dir, lowpc);
/* Process all dies in compilation unit. */
if (die->child != NULL)
complaint (&symfile_complaints,
_("CU refers to both DW_AT_GNU_macros and DW_AT_macro_info"));
- dwarf_decode_macros (cu, DW_UNSND (attr), comp_dir, 1);
+ dwarf_decode_macros (cu, DW_UNSND (attr), 1);
}
else
{
{
unsigned int macro_offset = DW_UNSND (attr);
- dwarf_decode_macros (cu, macro_offset, comp_dir, 0);
+ dwarf_decode_macros (cu, macro_offset, 0);
}
}
do it again, we could fake it and just recreate the part we need
(file name,index -> symtab mapping). If data shows this optimization
is useful we can do it then. */
- first_time = tu_group->primary_symtab == NULL;
+ first_time = tu_group->compunit_symtab == NULL;
/* We have to handle the case of both a missing DW_AT_stmt_list or bad
debug info. */
else
{
gdb_assert (tu_group->symtabs == NULL);
- restart_symtab (0);
+ restart_symtab (tu_group->compunit_symtab, "", 0);
}
- /* Note: The primary symtab will get allocated at the end. */
return;
}
if (first_time)
{
- dwarf2_start_symtab (cu, "", NULL, 0);
+ struct compunit_symtab *cust = dwarf2_start_symtab (cu, "", NULL, 0);
tu_group->num_symtabs = lh->num_file_names;
tu_group->symtabs = XNEWVEC (struct symtab *, lh->num_file_names);
const char *dir = NULL;
struct file_entry *fe = &lh->file_names[i];
- if (fe->dir_index)
+ if (fe->dir_index && lh->include_dirs != NULL)
dir = lh->include_dirs[fe->dir_index - 1];
- dwarf2_start_subfile (fe->name, dir, NULL);
-
- /* Note: We don't have to watch for the main subfile here, type units
- don't have DW_AT_name. */
+ dwarf2_start_subfile (fe->name, dir);
if (current_subfile->symtab == NULL)
{
/* NOTE: start_subfile will recognize when it's been passed
a file it has already seen. So we can't assume there's a
- simple mapping from lh->file_names to subfiles,
+ simple mapping from lh->file_names to subfiles, plus
lh->file_names may contain dups. */
- current_subfile->symtab = allocate_symtab (current_subfile->name,
- objfile);
+ current_subfile->symtab
+ = allocate_symtab (cust, current_subfile->name);
}
fe->symtab = current_subfile->symtab;
}
else
{
- restart_symtab (0);
+ restart_symtab (tu_group->compunit_symtab, "", 0);
for (i = 0; i < lh->num_file_names; ++i)
{
dwo_unit->offset = offset;
dwo_unit->length = cu->per_cu->length;
- if (dwarf2_read_debug)
+ if (dwarf_read_debug)
fprintf_unfiltered (gdb_stdlog, " offset 0x%x, dwo_id %s\n",
offset.sect_off, hex_string (dwo_unit->signature));
}
not present, in which case section->asection will be NULL. */
abfd = get_section_bfd_owner (section);
- if (dwarf2_read_debug)
+ if (dwarf_read_debug)
{
fprintf_unfiltered (gdb_stdlog, "Reading %s for %s:\n",
get_section_name (section),
per_cu.offset.sect_off = info_ptr - section->buffer;
per_cu.section = section;
- init_cutu_and_read_dies_no_follow (&per_cu,
- &dwo_file->sections.abbrev,
- dwo_file,
+ init_cutu_and_read_dies_no_follow (&per_cu, dwo_file,
create_dwo_cu_reader,
&create_dwo_cu_data);
gdb_assert (dwp_file->version == 1);
- if (dwarf2_read_debug)
+ if (dwarf_read_debug)
{
fprintf_unfiltered (gdb_stdlog, "Reading %s %s/%s in DWP V1 file: %s\n",
kind,
/* Create one if necessary. */
if (*dwo_file_slot == NULL)
{
- if (dwarf2_read_debug)
+ if (dwarf_read_debug)
{
fprintf_unfiltered (gdb_stdlog, "Creating virtual DWO: %s\n",
virtual_dwo_name);
}
else
{
- if (dwarf2_read_debug)
+ if (dwarf_read_debug)
{
fprintf_unfiltered (gdb_stdlog, "Using existing virtual DWO: %s\n",
virtual_dwo_name);
gdb_assert (dwp_file->version == 2);
- if (dwarf2_read_debug)
+ if (dwarf_read_debug)
{
fprintf_unfiltered (gdb_stdlog, "Reading %s %s/%s in DWP V2 file: %s\n",
kind,
/* Create one if necessary. */
if (*dwo_file_slot == NULL)
{
- if (dwarf2_read_debug)
+ if (dwarf_read_debug)
{
fprintf_unfiltered (gdb_stdlog, "Creating virtual DWO: %s\n",
virtual_dwo_name);
}
else
{
- if (dwarf2_read_debug)
+ if (dwarf_read_debug)
{
fprintf_unfiltered (gdb_stdlog, "Using existing virtual DWO: %s\n",
virtual_dwo_name);
If IS_DWP is TRUE, we're opening a DWP file, otherwise a DWO file.
SEARCH_CWD is true if the current directory is to be searched.
It will be searched before debug-file-directory.
+ If successful, the file is added to the bfd include table of the
+ objfile's bfd (see gdb_bfd_record_inclusion).
If unable to find/open the file, return NULL.
NOTE: This function is derived from symfile_bfd_open. */
return NULL;
}
+ /* Success. Record the bfd as having been included by the objfile's bfd.
+ This is important because things like demangled_names_hash lives in the
+ objfile's per_bfd space and may have references to things like symbol
+ names that live in the DWO/DWP file's per_bfd space. PR 16426. */
+ gdb_bfd_record_inclusion (dwarf2_per_objfile->objfile->obfd, sym_bfd);
+
return sym_bfd;
}
dbfd = open_dwo_file (dwo_name, comp_dir);
if (dbfd == NULL)
{
- if (dwarf2_read_debug)
+ if (dwarf_read_debug)
fprintf_unfiltered (gdb_stdlog, "DWO file not found: %s\n", dwo_name);
return NULL;
}
discard_cleanups (cleanups);
- if (dwarf2_read_debug)
+ if (dwarf_read_debug)
fprintf_unfiltered (gdb_stdlog, "DWO file found: %s\n", dwo_name);
return dwo_file;
if (dbfd == NULL)
{
- if (dwarf2_read_debug)
+ if (dwarf_read_debug)
fprintf_unfiltered (gdb_stdlog, "DWP file not found: %s\n", dwp_name);
do_cleanups (cleanups);
return NULL;
if (dwp_file->cus->version != dwp_file->tus->version)
{
/* Technically speaking, we should try to limp along, but this is
- pretty bizarre. */
- error (_("Dwarf Error: DWP file CU version %d doesn't match"
- " TU version %d [in DWP file %s]"),
- dwp_file->cus->version, dwp_file->tus->version, dwp_name);
+ pretty bizarre. We use pulongest here because that's the established
+ portability solution (e.g, we cannot use %u for uint32_t). */
+ error (_("Dwarf Error: DWP file CU version %s doesn't match"
+ " TU version %s [in DWP file %s]"),
+ pulongest (dwp_file->cus->version),
+ pulongest (dwp_file->tus->version), dwp_name);
}
dwp_file->version = dwp_file->cus->version;
dwp_file->loaded_cus = allocate_dwp_loaded_cutus_table (objfile);
dwp_file->loaded_tus = allocate_dwp_loaded_cutus_table (objfile);
- if (dwarf2_read_debug)
+ if (dwarf_read_debug)
{
fprintf_unfiltered (gdb_stdlog, "DWP file found: %s\n", dwp_file->name);
fprintf_unfiltered (gdb_stdlog,
if (dwo_cutu != NULL)
{
- if (dwarf2_read_debug)
+ if (dwarf_read_debug)
{
fprintf_unfiltered (gdb_stdlog,
"Virtual DWO %s %s found: @%s\n",
if (dwo_cutu != NULL)
{
- if (dwarf2_read_debug)
+ if (dwarf_read_debug)
{
fprintf_unfiltered (gdb_stdlog, "DWO %s %s(%s) found: @%s\n",
kind, dwo_name, hex_string (signature),
someone deleted the DWO/DWP file, or the search path isn't set up
correctly to find the file. */
- if (dwarf2_read_debug)
+ if (dwarf_read_debug)
{
fprintf_unfiltered (gdb_stdlog, "DWO %s %s(%s) not found\n",
kind, dwo_name, hex_string (signature));
cleanups = make_cleanup (xfree, offsets);
offsets_end = offsets;
- child_die = die->child;
- while (child_die && child_die->tag)
+ for (child_die = die->child;
+ child_die && child_die->tag;
+ child_die = sibling_die (child_die))
{
+ struct die_info *child_origin_die;
+ struct dwarf2_cu *child_origin_cu;
+
+ /* We are trying to process concrete instance entries:
+ DW_TAG_GNU_call_site DIEs indeed have a DW_AT_abstract_origin tag, but
+ it's not relevant to our analysis here. i.e. detecting DIEs that are
+ present in the abstract instance but not referenced in the concrete
+ one. */
+ if (child_die->tag == DW_TAG_GNU_call_site)
+ continue;
+
/* For each CHILD_DIE, find the corresponding child of
ORIGIN_DIE. If there is more than one layer of
DW_AT_abstract_origin, follow them all; there shouldn't be,
but GCC versions at least through 4.4 generate this (GCC PR
40573). */
- struct die_info *child_origin_die = child_die;
- struct dwarf2_cu *child_origin_cu = cu;
-
+ child_origin_die = child_die;
+ child_origin_cu = cu;
while (1)
{
attr = dwarf2_attr (child_origin_die, DW_AT_abstract_origin,
else
*offsets_end++ = child_origin_die->offset;
}
- child_die = sibling_die (child_die);
}
qsort (offsets, offsets_end - offsets, sizeof (*offsets),
unsigned_int_compar);
if (offsetp >= offsets_end
|| offsetp->sect_off > origin_child_die->offset.sect_off)
{
- /* Found that ORIGIN_CHILD_DIE is really not referenced. */
- process_die (origin_child_die, origin_cu);
+ /* Found that ORIGIN_CHILD_DIE is really not referenced.
+ Check whether we're already processing ORIGIN_CHILD_DIE.
+ This can happen with mutually referenced abstract_origins.
+ PR 16581. */
+ if (!origin_child_die->in_process)
+ process_die (origin_child_die, origin_cu);
}
origin_child_die = sibling_die (origin_child_die);
}
read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
{
struct objfile *objfile = cu->objfile;
- struct context_stack *new;
+ struct gdbarch *gdbarch = get_objfile_arch (objfile);
+ struct context_stack *newobj;
CORE_ADDR lowpc;
CORE_ADDR highpc;
struct die_info *child_die;
return;
}
- lowpc += baseaddr;
- highpc += baseaddr;
+ lowpc = gdbarch_adjust_dwarf2_addr (gdbarch, lowpc + baseaddr);
+ highpc = gdbarch_adjust_dwarf2_addr (gdbarch, highpc + baseaddr);
/* If we have any template arguments, then we must allocate a
different sort of symbol. */
}
}
- new = push_context (0, lowpc);
- new->name = new_symbol_full (die, read_type_die (die, cu), cu,
+ newobj = push_context (0, lowpc);
+ newobj->name = new_symbol_full (die, read_type_die (die, cu), cu,
(struct symbol *) templ_func);
/* If there is a location expression for DW_AT_frame_base, record
it. */
attr = dwarf2_attr (die, DW_AT_frame_base, cu);
if (attr)
- dwarf2_symbol_mark_computed (attr, new->name, cu, 1);
+ dwarf2_symbol_mark_computed (attr, newobj->name, cu, 1);
cu->list_in_scope = &local_symbols;
}
}
- new = pop_context ();
+ newobj = pop_context ();
/* Make a block for the local symbols within. */
- block = finish_block (new->name, &local_symbols, new->old_blocks,
- lowpc, highpc, objfile);
+ block = finish_block (newobj->name, &local_symbols, newobj->old_blocks,
+ lowpc, highpc);
/* For C++, set the block's scope. */
if ((cu->language == language_cplus || cu->language == language_fortran)
/* If we have address ranges, record them. */
dwarf2_record_block_ranges (die, block, baseaddr, cu);
+ gdbarch_make_symbol_special (gdbarch, newobj->name, objfile);
+
/* Attach template arguments to function. */
if (! VEC_empty (symbolp, template_args))
{
a function declares a class that has methods). This means that
when we finish processing a function scope, we may need to go
back to building a containing block's symbol lists. */
- local_symbols = new->locals;
- using_directives = new->using_directives;
+ local_symbols = newobj->locals;
+ using_directives = newobj->using_directives;
/* If we've finished processing a top-level function, subsequent
symbols go in the file symbol list. */
read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu)
{
struct objfile *objfile = cu->objfile;
- struct context_stack *new;
+ struct gdbarch *gdbarch = get_objfile_arch (objfile);
+ struct context_stack *newobj;
CORE_ADDR lowpc, highpc;
struct die_info *child_die;
CORE_ADDR baseaddr;
describe ranges. */
if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, cu, NULL))
return;
- lowpc += baseaddr;
- highpc += baseaddr;
+ lowpc = gdbarch_adjust_dwarf2_addr (gdbarch, lowpc + baseaddr);
+ highpc = gdbarch_adjust_dwarf2_addr (gdbarch, highpc + baseaddr);
push_context (0, lowpc);
if (die->child != NULL)
child_die = sibling_die (child_die);
}
}
- new = pop_context ();
+ inherit_abstract_dies (die, cu);
+ newobj = pop_context ();
if (local_symbols != NULL || using_directives != NULL)
{
struct block *block
- = finish_block (0, &local_symbols, new->old_blocks, new->start_addr,
- highpc, objfile);
+ = finish_block (0, &local_symbols, newobj->old_blocks,
+ newobj->start_addr, highpc);
/* Note that recording ranges after traversing children, as we
do here, means that recording a parent's ranges entails
to do. */
dwarf2_record_block_ranges (die, block, baseaddr, cu);
}
- local_symbols = new->locals;
- using_directives = new->using_directives;
+ local_symbols = newobj->locals;
+ using_directives = newobj->using_directives;
}
/* Read in DW_TAG_GNU_call_site and insert it to CU->call_site_htab. */
die->offset.sect_off, objfile_name (objfile));
return;
}
- pc = DW_ADDR (attr) + baseaddr;
+ pc = attr_value_as_address (attr) + baseaddr;
+ pc = gdbarch_adjust_dwarf2_addr (gdbarch, pc);
if (cu->call_site_htab == NULL)
cu->call_site_htab = htab_create_alloc_ex (16, core_addr_hash, core_addr_eq,
"low pc, for referencing DIE 0x%x [in module %s]"),
die->offset.sect_off, objfile_name (objfile));
else
- SET_FIELD_PHYSADDR (call_site->target, lowpc + baseaddr);
+ {
+ lowpc = gdbarch_adjust_dwarf2_addr (gdbarch, lowpc + baseaddr);
+ SET_FIELD_PHYSADDR (call_site->target, lowpc);
+ }
}
}
else
struct partial_symtab *ranges_pst)
{
struct objfile *objfile = cu->objfile;
+ struct gdbarch *gdbarch = get_objfile_arch (objfile);
struct comp_unit_head *cu_header = &cu->header;
bfd *obfd = objfile->obfd;
unsigned int addr_size = cu_header->addr_size;
}
if (ranges_pst != NULL)
- addrmap_set_empty (objfile->psymtabs_addrmap,
- range_beginning + baseaddr,
- range_end - 1 + baseaddr,
- ranges_pst);
+ {
+ CORE_ADDR lowpc;
+ CORE_ADDR highpc;
+
+ lowpc = gdbarch_adjust_dwarf2_addr (gdbarch,
+ range_beginning + baseaddr);
+ highpc = gdbarch_adjust_dwarf2_addr (gdbarch,
+ range_end + baseaddr);
+ addrmap_set_empty (objfile->psymtabs_addrmap, lowpc, highpc - 1,
+ ranges_pst);
+ }
/* FIXME: This is recording everything as a low-high
segment of consecutive addresses. We should have a
attr = dwarf2_attr (die, DW_AT_low_pc, cu);
if (attr)
{
- low = DW_ADDR (attr);
- if (attr_high->form == DW_FORM_addr
- || attr_high->form == DW_FORM_GNU_addr_index)
- high = DW_ADDR (attr_high);
- else
- high = low + DW_UNSND (attr_high);
+ low = attr_value_as_address (attr);
+ high = attr_value_as_address (attr_high);
+ if (cu->header.version >= 4 && attr_form_is_constant (attr_high))
+ high += low;
}
else
/* Found high w/o low attribute. */
CORE_ADDR baseaddr, struct dwarf2_cu *cu)
{
struct objfile *objfile = cu->objfile;
+ struct gdbarch *gdbarch = get_objfile_arch (objfile);
struct attribute *attr;
struct attribute *attr_high;
attr = dwarf2_attr (die, DW_AT_low_pc, cu);
if (attr)
{
- CORE_ADDR low = DW_ADDR (attr);
- CORE_ADDR high;
- if (attr_high->form == DW_FORM_addr
- || attr_high->form == DW_FORM_GNU_addr_index)
- high = DW_ADDR (attr_high);
- else
- high = low + DW_UNSND (attr_high);
+ CORE_ADDR low = attr_value_as_address (attr);
+ CORE_ADDR high = attr_value_as_address (attr_high);
- record_block_range (block, baseaddr + low, baseaddr + high - 1);
+ if (cu->header.version >= 4 && attr_form_is_constant (attr_high))
+ high += low;
+
+ low = gdbarch_adjust_dwarf2_addr (gdbarch, low + baseaddr);
+ high = gdbarch_adjust_dwarf2_addr (gdbarch, high + baseaddr);
+ record_block_range (block, low, high - 1);
}
}
continue;
}
+ start = gdbarch_adjust_dwarf2_addr (gdbarch, start);
+ end = gdbarch_adjust_dwarf2_addr (gdbarch, end);
record_block_range (block, start, end - 1);
}
}
check_producer (struct dwarf2_cu *cu)
{
const char *cs;
- int major, minor, release;
+ int major, minor;
if (cu->producer == NULL)
{
combination. gcc-4.5.x -gdwarf-4 binaries have DW_AT_accessibility
interpreted incorrectly by GDB now - GCC PR debug/48229. */
}
- else if (strncmp (cu->producer, "GNU ", strlen ("GNU ")) == 0)
+ else if (producer_is_gcc (cu->producer, &major, &minor))
{
- /* Skip any identifier after "GNU " - such as "C++" or "Java". */
-
- cs = &cu->producer[strlen ("GNU ")];
- while (*cs && !isdigit (*cs))
- cs++;
- if (sscanf (cs, "%d.%d.%d", &major, &minor, &release) != 3)
- {
- /* Not recognized as GCC. */
- }
- else
- {
- cu->producer_is_gxx_lt_4_6 = major < 4 || (major == 4 && minor < 6);
- cu->producer_is_gcc_lt_4_3 = major < 4 || (major == 4 && minor < 3);
- }
+ cu->producer_is_gxx_lt_4_6 = major < 4 || (major == 4 && minor < 6);
+ cu->producer_is_gcc_lt_4_3 = major < 4 || (major == 4 && minor < 3);
}
- else if (strncmp (cu->producer, "Intel(R) C", strlen ("Intel(R) C")) == 0)
+ else if (startswith (cu->producer, "Intel(R) C"))
cu->producer_is_icc = 1;
else
{
dwarf2_is_constructor (struct die_info *die, struct dwarf2_cu *cu)
{
const char *fieldname;
- const char *typename;
+ const char *type_name;
int len;
if (die->parent == NULL)
return 0;
fieldname = dwarf2_name (die, cu);
- typename = dwarf2_name (die->parent, cu);
- if (fieldname == NULL || typename == NULL)
+ type_name = dwarf2_name (die->parent, cu);
+ if (fieldname == NULL || type_name == NULL)
return 0;
len = strlen (fieldname);
- return (strncmp (fieldname, typename, len) == 0
- && (typename[len] == '\0' || typename[len] == '<'));
+ return (strncmp (fieldname, type_name, len) == 0
+ && (type_name[len] == '\0' || type_name[len] == '<'));
}
/* Add a member function to the proper fieldlist. */
dwarf2_complex_location_expr_complaint ();
if (!fnp->fcontext)
- fnp->fcontext = TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (this_type, 0));
+ {
+ /* If there is no `this' field and no DW_AT_containing_type,
+ we cannot actually find a base class context for the
+ vtable! */
+ if (TYPE_NFIELDS (this_type) == 0
+ || !TYPE_FIELD_ARTIFICIAL (this_type, 0))
+ {
+ complaint (&symfile_complaints,
+ _("cannot determine context for virtual member "
+ "function \"%s\" (offset %d)"),
+ fieldname, die->offset.sect_off);
+ }
+ else
+ {
+ fnp->fcontext
+ = TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (this_type, 0));
+ }
+ }
}
else if (attr_form_is_section_offset (attr))
{
/* Look for the C++ and Java forms of the vtable. */
if ((cu->language == language_java
- && strncmp (name, vtable, sizeof (vtable) - 1) == 0)
- || (strncmp (name, vptr, sizeof (vptr) - 1) == 0
+ && startswith (name, vtable))
+ || (startswith (name, vptr)
&& is_cplus_marker (name[sizeof (vptr) - 1])))
return 1;
static void
quirk_gcc_member_function_pointer (struct type *type, struct objfile *objfile)
{
- struct type *pfn_type, *domain_type, *new_type;
+ struct type *pfn_type, *self_type, *new_type;
/* Check for a structure with no name and two children. */
if (TYPE_CODE (type) != TYPE_CODE_STRUCT || TYPE_NFIELDS (type) != 2)
|| TYPE_CODE (TYPE_FIELD_TYPE (pfn_type, 0)) != TYPE_CODE_PTR)
return;
- domain_type = TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (pfn_type, 0));
+ self_type = TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (pfn_type, 0));
new_type = alloc_type (objfile);
- smash_to_method_type (new_type, domain_type, TYPE_TARGET_TYPE (pfn_type),
+ smash_to_method_type (new_type, self_type, TYPE_TARGET_TYPE (pfn_type),
TYPE_FIELDS (pfn_type), TYPE_NFIELDS (pfn_type),
TYPE_VARARGS (pfn_type));
smash_to_methodptr_type (type, new_type);
/* Called when we find the DIE that starts a structure or union scope
(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_scope.
+ processed until process_structure_scope. A symbol table entry for
+ the type will also not be done until process_structure_scope (assuming
+ the type has a name).
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.
-
- However, if the structure is incomplete (an opaque struct/union)
- then suppress creating a symbol table entry for it since gdb only
- wants to find the one with the complete definition. Note that if
- it is complete, we just call new_symbol, which does it's own
- checking about whether the struct/union is anonymous or not (and
- suppresses creating a symbol table entry itself). */
+ user defined types. */
static struct type *
read_structure_type (struct die_info *die, struct dwarf2_cu *cu)
}
else
{
- TYPE_CODE (type) = TYPE_CODE_CLASS;
+ TYPE_CODE (type) = TYPE_CODE_STRUCT;
}
if (cu->language == language_cplus && die->tag == DW_TAG_class_type)
TYPE_LENGTH (type) = 0;
}
- if (producer_is_icc (cu))
+ if (producer_is_icc (cu) && (TYPE_LENGTH (type) == 0))
{
/* ICC does not output the required DW_AT_declaration
on incomplete types, but gives them a size of zero. */
+ TYPE_STUB (type) = 1;
}
else
TYPE_STUB_SUPPORTED (type) = 1;
process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
{
struct objfile *objfile = cu->objfile;
- struct die_info *child_die = die->child;
+ struct die_info *child_die;
struct type *type;
type = get_die_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);
{
struct type *t = die_containing_type (die, cu);
- TYPE_VPTR_BASETYPE (type) = t;
+ set_type_vptr_basetype (type, t);
if (type == t)
{
int i;
if (is_vtable_name (fieldname, cu))
{
- TYPE_VPTR_FIELDNO (type) = i;
+ set_type_vptr_fieldno (type, i);
break;
}
}
}
else
{
- TYPE_VPTR_FIELDNO (type) = TYPE_VPTR_FIELDNO (t);
+ set_type_vptr_fieldno (type, TYPE_VPTR_FIELDNO (t));
}
}
else if (cu->producer
- && strncmp (cu->producer,
- "IBM(R) XL C/C++ Advanced Edition", 32) == 0)
+ && startswith (cu->producer, "IBM(R) XL C/C++ Advanced Edition"))
{
/* The IBM XLC compiler does not provide direct indication
of the containing type, but the vtable pointer is
{
if (strcmp (TYPE_FIELD_NAME (type, i), "__vfp") == 0)
{
- TYPE_VPTR_FIELDNO (type) = i;
- TYPE_VPTR_BASETYPE (type) = type;
+ set_type_vptr_fieldno (type, i);
+ set_type_vptr_basetype (type, type);
break;
}
}
current die is a declaration. Normally, of course, a declaration
won't have any children at all. */
+ child_die = die->child;
+
while (child_die != NULL && child_die->tag)
{
if (child_die->tag == DW_TAG_member
new_symbol (die, type, cu);
}
+/* Assuming DIE is an enumeration type, and TYPE is its associated type,
+ update TYPE using some information only available in DIE's children. */
+
+static void
+update_enumeration_type_from_children (struct die_info *die,
+ struct type *type,
+ struct dwarf2_cu *cu)
+{
+ struct obstack obstack;
+ struct die_info *child_die;
+ int unsigned_enum = 1;
+ int flag_enum = 1;
+ ULONGEST mask = 0;
+ struct cleanup *old_chain;
+
+ obstack_init (&obstack);
+ old_chain = make_cleanup_obstack_free (&obstack);
+
+ for (child_die = die->child;
+ child_die != NULL && child_die->tag;
+ child_die = sibling_die (child_die))
+ {
+ struct attribute *attr;
+ LONGEST value;
+ const gdb_byte *bytes;
+ struct dwarf2_locexpr_baton *baton;
+ const char *name;
+
+ if (child_die->tag != DW_TAG_enumerator)
+ continue;
+
+ attr = dwarf2_attr (child_die, DW_AT_const_value, cu);
+ if (attr == NULL)
+ continue;
+
+ name = dwarf2_name (child_die, cu);
+ if (name == NULL)
+ name = "<anonymous enumerator>";
+
+ dwarf2_const_value_attr (attr, type, name, &obstack, cu,
+ &value, &bytes, &baton);
+ if (value < 0)
+ {
+ unsigned_enum = 0;
+ flag_enum = 0;
+ }
+ else if ((mask & value) != 0)
+ flag_enum = 0;
+ else
+ mask |= value;
+
+ /* If we already know that the enum type is neither unsigned, nor
+ a flag type, no need to look at the rest of the enumerates. */
+ if (!unsigned_enum && !flag_enum)
+ break;
+ }
+
+ if (unsigned_enum)
+ TYPE_UNSIGNED (type) = 1;
+ if (flag_enum)
+ TYPE_FLAG_ENUM (type) = 1;
+
+ do_cleanups (old_chain);
+}
+
/* Given a DW_AT_enumeration_type die, set its type. We do not
complete the type's fields yet, or create any symbols. */
if (name != NULL)
TYPE_TAG_NAME (type) = name;
+ attr = dwarf2_attr (die, DW_AT_type, cu);
+ if (attr != NULL)
+ {
+ struct type *underlying_type = die_type (die, cu);
+
+ TYPE_TARGET_TYPE (type) = underlying_type;
+ }
+
attr = dwarf2_attr (die, DW_AT_byte_size, cu);
if (attr)
{
if (die_is_declaration (die, cu))
TYPE_STUB (type) = 1;
+ /* Finish the creation of this type by using the enum's children.
+ We must call this even when the underlying type has been provided
+ so that we can determine if we're looking at a "flag" enum. */
+ update_enumeration_type_from_children (die, type, cu);
+
+ /* If this type has an underlying type that is not a stub, then we
+ may use its attributes. We always use the "unsigned" attribute
+ in this situation, because ordinarily we guess whether the type
+ is unsigned -- but the guess can be wrong and the underlying type
+ can tell us the reality. However, we defer to a local size
+ attribute if one exists, because this lets the compiler override
+ the underlying type if needed. */
+ if (TYPE_TARGET_TYPE (type) != NULL && !TYPE_STUB (TYPE_TARGET_TYPE (type)))
+ {
+ TYPE_UNSIGNED (type) = TYPE_UNSIGNED (TYPE_TARGET_TYPE (type));
+ if (TYPE_LENGTH (type) == 0)
+ TYPE_LENGTH (type) = TYPE_LENGTH (TYPE_TARGET_TYPE (type));
+ }
+
+ TYPE_DECLARED_CLASS (type) = dwarf2_flag_true_p (die, DW_AT_enum_class, cu);
+
return set_die_type (die, type, cu);
}
struct symbol *sym;
struct field *fields = NULL;
int num_fields = 0;
- int unsigned_enum = 1;
const char *name;
- int flag_enum = 1;
- ULONGEST mask = 0;
child_die = die->child;
while (child_die && child_die->tag)
if (name)
{
sym = new_symbol (child_die, this_type, cu);
- if (SYMBOL_VALUE (sym) < 0)
- {
- unsigned_enum = 0;
- flag_enum = 0;
- }
- else if ((mask & SYMBOL_VALUE (sym)) != 0)
- flag_enum = 0;
- else
- mask |= SYMBOL_VALUE (sym);
if ((num_fields % DW_FIELD_ALLOC_CHUNK) == 0)
{
sizeof (struct field) * num_fields);
xfree (fields);
}
- if (unsigned_enum)
- TYPE_UNSIGNED (this_type) = 1;
- if (flag_enum)
- TYPE_FLAG_ENUM (this_type) = 1;
}
/* If we are reading an enum from a .debug_types unit, and the enum
int ndim = 0;
struct cleanup *back_to;
const char *name;
+ unsigned int bit_stride = 0;
element_type = die_type (die, cu);
if (type)
return type;
+ attr = dwarf2_attr (die, DW_AT_byte_stride, cu);
+ if (attr != NULL)
+ bit_stride = DW_UNSND (attr) * 8;
+
+ attr = dwarf2_attr (die, DW_AT_bit_stride, cu);
+ if (attr != NULL)
+ bit_stride = DW_UNSND (attr);
+
/* Irix 6.2 native cc creates array types without children for
arrays with unspecified length. */
if (die->child == NULL)
{
index_type = objfile_type (objfile)->builtin_int;
- range_type = create_range_type (NULL, index_type, 0, -1);
- type = create_array_type (NULL, element_type, range_type);
+ range_type = create_static_range_type (NULL, index_type, 0, -1);
+ type = create_array_type_with_stride (NULL, element_type, range_type,
+ bit_stride);
return set_die_type (die, type, cu);
}
int i = 0;
while (i < ndim)
- type = create_array_type (NULL, type, range_types[i++]);
+ type = create_array_type_with_stride (NULL, type, range_types[i++],
+ bit_stride);
}
else
{
while (ndim-- > 0)
- type = create_array_type (NULL, type, range_types[ndim]);
+ type = create_array_type_with_stride (NULL, type, range_types[ndim],
+ bit_stride);
}
/* Understand Dwarf2 support for vector types (like they occur on
current_die != NULL;
current_die = dwarf2_extension (die, &cu))
{
- name = dwarf2_name (current_die, cu);
+ /* We don't use dwarf2_name here so that we can detect the absence
+ of a name -> anonymous namespace. */
+ struct attribute *attr = dwarf2_attr (die, DW_AT_name, cu);
+
+ if (attr != NULL)
+ name = DW_STRING (attr);
if (name != NULL)
break;
}
return set_die_type (die, type, cu);
}
+/* Add the given cv-qualifiers to the element type of the array. GCC
+ outputs DWARF type qualifiers that apply to an array, not the
+ element type. But GDB relies on the array element type to carry
+ the cv-qualifiers. This mimics section 6.7.3 of the C99
+ specification. */
+
+static struct type *
+add_array_cv_type (struct die_info *die, struct dwarf2_cu *cu,
+ struct type *base_type, int cnst, int voltl)
+{
+ 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);
+ cnst |= TYPE_CONST (el_type);
+ voltl |= TYPE_VOLATILE (el_type);
+ TYPE_TARGET_TYPE (inner_array) = make_cv_type (cnst, voltl, el_type, NULL);
+
+ return set_die_type (die, base_type, cu);
+}
+
static struct type *
read_tag_const_type (struct die_info *die, struct dwarf2_cu *cu)
{
/* 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;
+ return add_array_cv_type (die, cu, base_type, 1, 0);
- base_type = copy_type (base_type);
- inner_array = base_type;
+ cv_type = make_cv_type (1, TYPE_VOLATILE (base_type), base_type, 0);
+ return set_die_type (die, cv_type, cu);
+}
- 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);
- }
+static struct type *
+read_tag_volatile_type (struct die_info *die, struct dwarf2_cu *cu)
+{
+ struct type *base_type, *cv_type;
- el_type = TYPE_TARGET_TYPE (inner_array);
- TYPE_TARGET_TYPE (inner_array) =
- make_cv_type (1, TYPE_VOLATILE (el_type), el_type, NULL);
+ base_type = die_type (die, cu);
- return set_die_type (die, base_type, cu);
- }
+ /* The die_type call above may have already set the type for this DIE. */
+ cv_type = get_die_type (die, cu);
+ if (cv_type)
+ return cv_type;
- cv_type = make_cv_type (1, TYPE_VOLATILE (base_type), base_type, 0);
+ /* In case the volatile 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)
+ return add_array_cv_type (die, cu, base_type, 0, 1);
+
+ cv_type = make_cv_type (TYPE_CONST (base_type), 1, base_type, 0);
return set_die_type (die, cv_type, cu);
}
+/* Handle DW_TAG_restrict_type. */
+
static struct type *
-read_tag_volatile_type (struct die_info *die, struct dwarf2_cu *cu)
+read_tag_restrict_type (struct die_info *die, struct dwarf2_cu *cu)
{
struct type *base_type, *cv_type;
if (cv_type)
return cv_type;
- cv_type = make_cv_type (TYPE_CONST (base_type), 1, base_type, 0);
+ cv_type = make_restrict_type (base_type);
return set_die_type (die, cv_type, cu);
}
-/* Handle DW_TAG_restrict_type. */
+/* Handle DW_TAG_atomic_type. */
static struct type *
-read_tag_restrict_type (struct die_info *die, struct dwarf2_cu *cu)
+read_tag_atomic_type (struct die_info *die, struct dwarf2_cu *cu)
{
struct type *base_type, *cv_type;
if (cv_type)
return cv_type;
- cv_type = make_restrict_type (base_type);
+ cv_type = make_atomic_type (base_type);
return set_die_type (die, cv_type, cu);
}
}
index_type = objfile_type (objfile)->builtin_int;
- range_type = create_range_type (NULL, index_type, 1, length);
+ range_type = create_static_range_type (NULL, index_type, 1, length);
char_type = language_string_char_type (cu->language_defn, gdbarch);
type = create_string_type (NULL, char_type, range_type);
else
TYPE_CALLING_CONVENTION (ftype) = DW_CC_normal;
+ /* Record whether the function returns normally to its caller or not
+ if the DWARF producer set that information. */
+ attr = dwarf2_attr (die, DW_AT_noreturn, cu);
+ if (attr && (DW_UNSND (attr) != 0))
+ TYPE_NO_RETURN (ftype) = 1;
+
/* 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. */
type_flags |= TYPE_FLAG_UNSIGNED;
if (cu->language == language_fortran
&& name
- && strncmp (name, "character(", sizeof ("character(") - 1) == 0)
+ && startswith (name, "character("))
code = TYPE_CODE_CHAR;
break;
case DW_ATE_signed_char:
return set_die_type (die, type, cu);
}
+/* Parse dwarf attribute if it's a block, reference or constant and put the
+ resulting value of the attribute into struct bound_prop.
+ Returns 1 if ATTR could be resolved into PROP, 0 otherwise. */
+
+static int
+attr_to_dynamic_prop (const struct attribute *attr, struct die_info *die,
+ struct dwarf2_cu *cu, struct dynamic_prop *prop)
+{
+ struct dwarf2_property_baton *baton;
+ struct obstack *obstack = &cu->objfile->objfile_obstack;
+
+ if (attr == NULL || prop == NULL)
+ return 0;
+
+ if (attr_form_is_block (attr))
+ {
+ baton = obstack_alloc (obstack, sizeof (*baton));
+ baton->referenced_type = NULL;
+ baton->locexpr.per_cu = cu->per_cu;
+ baton->locexpr.size = DW_BLOCK (attr)->size;
+ baton->locexpr.data = DW_BLOCK (attr)->data;
+ prop->data.baton = baton;
+ prop->kind = PROP_LOCEXPR;
+ gdb_assert (prop->data.baton != NULL);
+ }
+ else if (attr_form_is_ref (attr))
+ {
+ struct dwarf2_cu *target_cu = cu;
+ struct die_info *target_die;
+ struct attribute *target_attr;
+
+ target_die = follow_die_ref (die, attr, &target_cu);
+ target_attr = dwarf2_attr (target_die, DW_AT_location, target_cu);
+ if (target_attr == NULL)
+ target_attr = dwarf2_attr (target_die, DW_AT_data_member_location,
+ target_cu);
+ if (target_attr == NULL)
+ return 0;
+
+ switch (target_attr->name)
+ {
+ case DW_AT_location:
+ if (attr_form_is_section_offset (target_attr))
+ {
+ baton = obstack_alloc (obstack, sizeof (*baton));
+ baton->referenced_type = die_type (target_die, target_cu);
+ fill_in_loclist_baton (cu, &baton->loclist, target_attr);
+ prop->data.baton = baton;
+ prop->kind = PROP_LOCLIST;
+ gdb_assert (prop->data.baton != NULL);
+ }
+ else if (attr_form_is_block (target_attr))
+ {
+ baton = obstack_alloc (obstack, sizeof (*baton));
+ baton->referenced_type = die_type (target_die, target_cu);
+ baton->locexpr.per_cu = cu->per_cu;
+ baton->locexpr.size = DW_BLOCK (target_attr)->size;
+ baton->locexpr.data = DW_BLOCK (target_attr)->data;
+ prop->data.baton = baton;
+ prop->kind = PROP_LOCEXPR;
+ gdb_assert (prop->data.baton != NULL);
+ }
+ else
+ {
+ dwarf2_invalid_attrib_class_complaint ("DW_AT_location",
+ "dynamic property");
+ return 0;
+ }
+ break;
+ case DW_AT_data_member_location:
+ {
+ LONGEST offset;
+
+ if (!handle_data_member_location (target_die, target_cu,
+ &offset))
+ return 0;
+
+ baton = obstack_alloc (obstack, sizeof (*baton));
+ baton->referenced_type = read_type_die (target_die->parent,
+ target_cu);
+ baton->offset_info.offset = offset;
+ baton->offset_info.type = die_type (target_die, target_cu);
+ prop->data.baton = baton;
+ prop->kind = PROP_ADDR_OFFSET;
+ break;
+ }
+ }
+ }
+ else if (attr_form_is_constant (attr))
+ {
+ prop->data.const_val = dwarf2_get_attr_constant_value (attr, 0);
+ prop->kind = PROP_CONST;
+ }
+ else
+ {
+ dwarf2_invalid_attrib_class_complaint (dwarf_form_name (attr->form),
+ dwarf2_name (die, cu));
+ return 0;
+ }
+
+ return 1;
+}
+
/* Read the given DW_AT_subrange DIE. */
static struct type *
struct type *base_type, *orig_base_type;
struct type *range_type;
struct attribute *attr;
- LONGEST low, high;
+ struct dynamic_prop low, high;
int low_default_is_valid;
+ int high_bound_is_count = 0;
const char *name;
LONGEST negative_mask;
if (range_type)
return range_type;
+ low.kind = PROP_CONST;
+ high.kind = PROP_CONST;
+ high.data.const_val = 0;
+
/* Set LOW_DEFAULT_IS_VALID if current language and DWARF version allow
omitting DW_AT_lower_bound. */
switch (cu->language)
{
case language_c:
case language_cplus:
- low = 0;
+ low.data.const_val = 0;
low_default_is_valid = 1;
break;
case language_fortran:
- low = 1;
+ low.data.const_val = 1;
low_default_is_valid = 1;
break;
case language_d:
case language_java:
case language_objc:
- low = 0;
+ low.data.const_val = 0;
low_default_is_valid = (cu->header.version >= 4);
break;
case language_ada:
case language_m2:
case language_pascal:
- low = 1;
+ low.data.const_val = 1;
low_default_is_valid = (cu->header.version >= 4);
break;
default:
- low = 0;
+ low.data.const_val = 0;
low_default_is_valid = 0;
break;
}
- /* FIXME: For variable sized arrays either of these could be
- a variable rather than a constant value. We'll allow it,
- but we don't know how to handle it. */
attr = dwarf2_attr (die, DW_AT_lower_bound, cu);
if (attr)
- low = dwarf2_get_attr_constant_value (attr, low);
+ attr_to_dynamic_prop (attr, die, cu, &low);
else if (!low_default_is_valid)
complaint (&symfile_complaints, _("Missing DW_AT_lower_bound "
"- DIE at 0x%x [in module %s]"),
die->offset.sect_off, objfile_name (cu->objfile));
attr = dwarf2_attr (die, DW_AT_upper_bound, cu);
- if (attr)
- {
- if (attr_form_is_block (attr) || attr_form_is_ref (attr))
- {
- /* GCC encodes arrays with unspecified or dynamic length
- with a DW_FORM_block1 attribute or a reference attribute.
- FIXME: GDB does not yet know how to handle dynamic
- arrays properly, treat them as arrays with unspecified
- length for now.
-
- FIXME: jimb/2003-09-22: GDB does not really know
- how to handle arrays of unspecified length
- either; we just represent them as zero-length
- arrays. Choose an appropriate upper bound given
- the lower bound we've computed above. */
- high = low - 1;
- }
- else
- high = dwarf2_get_attr_constant_value (attr, 1);
- }
- else
+ if (!attr_to_dynamic_prop (attr, die, cu, &high))
{
attr = dwarf2_attr (die, DW_AT_count, cu);
- if (attr)
- {
- int count = dwarf2_get_attr_constant_value (attr, 1);
- high = low + count - 1;
- }
- else
+ if (attr_to_dynamic_prop (attr, die, cu, &high))
{
- /* Unspecified array length. */
- high = low - 1;
+ /* If bounds are constant do the final calculation here. */
+ if (low.kind == PROP_CONST && high.kind == PROP_CONST)
+ high.data.const_val = low.data.const_val + high.data.const_val - 1;
+ else
+ high_bound_is_count = 1;
}
}
}
}
+ /* Normally, the DWARF producers are expected to use a signed
+ constant form (Eg. DW_FORM_sdata) to express negative bounds.
+ But this is unfortunately not always the case, as witnessed
+ with GCC, for instance, where the ambiguous DW_FORM_dataN form
+ is used instead. To work around that ambiguity, we treat
+ the bounds as signed, and thus sign-extend their values, when
+ the base type is signed. */
negative_mask =
(LONGEST) -1 << (TYPE_LENGTH (base_type) * TARGET_CHAR_BIT - 1);
- if (!TYPE_UNSIGNED (base_type) && (low & negative_mask))
- low |= negative_mask;
- if (!TYPE_UNSIGNED (base_type) && (high & negative_mask))
- high |= negative_mask;
+ if (low.kind == PROP_CONST
+ && !TYPE_UNSIGNED (base_type) && (low.data.const_val & negative_mask))
+ low.data.const_val |= negative_mask;
+ if (high.kind == PROP_CONST
+ && !TYPE_UNSIGNED (base_type) && (high.data.const_val & negative_mask))
+ high.data.const_val |= negative_mask;
- range_type = create_range_type (NULL, orig_base_type, low, high);
+ range_type = create_range_type (NULL, orig_base_type, &low, &high);
- /* Mark arrays with dynamic length at least as an array of unspecified
- length. GDB could check the boundary but before it gets implemented at
- least allow accessing the array elements. */
- if (attr && attr_form_is_block (attr))
- TYPE_HIGH_BOUND_UNDEFINED (range_type) = 1;
+ if (high_bound_is_count)
+ TYPE_RANGE_DATA (range_type)->flag_upper_bound_is_count = 1;
/* Ada expects an empty array on no boundary attributes. */
if (attr == NULL && cu->language != language_ada)
- TYPE_HIGH_BOUND_UNDEFINED (range_type) = 1;
+ TYPE_HIGH_BOUND_KIND (range_type) = PROP_UNDEFINED;
name = dwarf2_name (die, cu);
if (name)
struct die_info *die = read_die_and_siblings_1 (reader, info_ptr,
new_info_ptr, parent);
- if (dwarf2_die_debug)
+ if (dwarf_die_debug)
{
fprintf_unfiltered (gdb_stdlog,
"Read die from %s@0x%x of %s:\n",
get_section_name (reader->die_section),
(unsigned) (info_ptr - reader->die_section->buffer),
bfd_get_filename (reader->abfd));
- dump_die (die, dwarf2_die_debug);
+ dump_die (die, dwarf_die_debug);
}
return die;
result = read_full_die_1 (reader, diep, info_ptr, has_children, 0);
- if (dwarf2_die_debug)
+ if (dwarf_die_debug)
{
fprintf_unfiltered (gdb_stdlog,
"Read die from %s@0x%x of %s:\n",
get_section_name (reader->die_section),
(unsigned) (info_ptr - reader->die_section->buffer),
bfd_get_filename (reader->abfd));
- dump_die (*diep, dwarf2_die_debug);
+ dump_die (*diep, dwarf_die_debug);
}
return result;
/* Same as abbrev_table_free but as a cleanup.
We pass in a pointer to the pointer to the table so that we can
set the pointer to NULL when we're done. It also simplifies
- build_type_unit_groups. */
+ build_type_psymtabs_1. */
static void
abbrev_table_free_cleanup (void *table_ptr)
default:
part_die->name
= dwarf2_canonicalize_name (DW_STRING (&attr), cu,
- &objfile->objfile_obstack);
+ &objfile->per_bfd->storage_obstack);
break;
}
break;
break;
case DW_AT_low_pc:
has_low_pc_attr = 1;
- part_die->lowpc = DW_ADDR (&attr);
+ part_die->lowpc = attr_value_as_address (&attr);
break;
case DW_AT_high_pc:
has_high_pc_attr = 1;
- if (attr.form == DW_FORM_addr
- || attr.form == DW_FORM_GNU_addr_index)
- part_die->highpc = DW_ADDR (&attr);
- else
- {
- high_pc_relative = 1;
- part_die->highpc = DW_UNSND (&attr);
- }
+ part_die->highpc = attr_value_as_address (&attr);
+ if (cu->header.version >= 4 && attr_form_is_constant (&attr))
+ high_pc_relative = 1;
break;
case DW_AT_location:
/* Support the .debug_loc offsets. */
if (sibling_ptr < info_ptr)
complaint (&symfile_complaints,
_("DW_AT_sibling points backwards"));
+ else if (sibling_ptr > reader->buffer_end)
+ dwarf2_section_buffer_overflow_complaint (reader->die_section);
else
part_die->sibling = sibling_ptr;
}
case DW_AT_byte_size:
part_die->has_byte_size = 1;
break;
+ case DW_AT_const_value:
+ part_die->has_const_value = 1;
+ break;
case DW_AT_calling_convention:
/* DWARF doesn't provide a way to identify a program's source-level
entry point. DW_AT_calling_convention attributes are only meant
practice. */
if (DW_UNSND (&attr) == DW_CC_program
&& cu->language == language_fortran)
- {
- 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;
- }
+ set_objfile_main_name (objfile, part_die->name, language_fortran);
break;
case DW_AT_inline:
if (DW_UNSND (&attr) == DW_INL_inlined
if (actual_class_name != NULL)
{
struct_pdi->name
- = obstack_copy0 (&cu->objfile->objfile_obstack,
+ = obstack_copy0 (&cu->objfile->per_bfd->storage_obstack,
actual_class_name,
strlen (actual_class_name));
xfree (actual_class_name);
else
base = demangled;
- part_die->name = obstack_copy0 (&cu->objfile->objfile_obstack,
- base, strlen (base));
+ part_die->name
+ = obstack_copy0 (&cu->objfile->per_bfd->storage_obstack,
+ base, strlen (base));
xfree (demangled);
}
}
const gdb_byte *info_ptr)
{
struct dwarf2_cu *cu = reader->cu;
+ struct objfile *objfile = cu->objfile;
+ struct gdbarch *gdbarch = get_objfile_arch (objfile);
bfd *abfd = reader->abfd;
struct comp_unit_head *cu_header = &cu->header;
unsigned int bytes_read;
break;
case DW_FORM_addr:
DW_ADDR (attr) = read_address (abfd, info_ptr, cu, &bytes_read);
+ DW_ADDR (attr) = gdbarch_adjust_dwarf2_addr (gdbarch, DW_ADDR (attr));
info_ptr += bytes_read;
break;
case DW_FORM_block2:
ULONGEST str_index =
read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
- DW_STRING (attr) = read_str_index (reader, cu, str_index);
+ DW_STRING (attr) = read_str_index (reader, str_index);
DW_STRING_IS_CANONICAL (attr) = 0;
info_ptr += bytes_read;
}
This is only used by the Fission support. */
static const char *
-read_str_index (const struct die_reader_specs *reader,
- struct dwarf2_cu *cu, ULONGEST str_index)
+read_str_index (const struct die_reader_specs *reader, ULONGEST str_index)
{
struct objfile *objfile = dwarf2_per_objfile->objfile;
- const char *dwo_name = objfile_name (objfile);
+ const char *objf_name = objfile_name (objfile);
bfd *abfd = objfile->obfd;
+ struct dwarf2_cu *cu = reader->cu;
struct dwarf2_section_info *str_section = &reader->dwo_file->sections.str;
struct dwarf2_section_info *str_offsets_section =
&reader->dwo_file->sections.str_offsets;
if (str_section->buffer == NULL)
error (_("%s used without .debug_str.dwo section"
" in CU at offset 0x%lx [in module %s]"),
- form_name, (long) cu->header.offset.sect_off, dwo_name);
+ form_name, (long) cu->header.offset.sect_off, objf_name);
if (str_offsets_section->buffer == NULL)
error (_("%s used without .debug_str_offsets.dwo section"
" in CU at offset 0x%lx [in module %s]"),
- form_name, (long) cu->header.offset.sect_off, dwo_name);
+ form_name, (long) cu->header.offset.sect_off, objf_name);
if (str_index * cu->header.offset_size >= str_offsets_section->size)
error (_("%s pointing outside of .debug_str_offsets.dwo"
" section in CU at offset 0x%lx [in module %s]"),
- form_name, (long) cu->header.offset.sect_off, dwo_name);
+ form_name, (long) cu->header.offset.sect_off, objf_name);
info_ptr = (str_offsets_section->buffer
+ str_index * cu->header.offset_size);
if (cu->header.offset_size == 4)
if (str_offset >= str_section->size)
error (_("Offset from %s pointing outside of"
" .debug_str.dwo section in CU at offset 0x%lx [in module %s]"),
- form_name, (long) cu->header.offset.sect_off, dwo_name);
+ form_name, (long) cu->header.offset.sect_off, objf_name);
return (const char *) (str_section->buffer + str_offset);
}
{
case DW_LANG_C89:
case DW_LANG_C99:
+ case DW_LANG_C11:
case DW_LANG_C:
case DW_LANG_UPC:
cu->language = language_c;
break;
case DW_LANG_C_plus_plus:
+ case DW_LANG_C_plus_plus_11:
+ case DW_LANG_C_plus_plus_14:
cu->language = language_cplus;
break;
case DW_LANG_D:
case DW_LANG_Fortran77:
case DW_LANG_Fortran90:
case DW_LANG_Fortran95:
+ case DW_LANG_Fortran03:
+ case DW_LANG_Fortran08:
cu->language = language_fortran;
break;
case DW_LANG_Go:
xfree (lh);
}
+/* Stub for free_line_header to match void * callback types. */
+
+static void
+free_line_header_voidp (void *arg)
+{
+ struct line_header *lh = arg;
+
+ free_line_header (lh);
+}
+
/* Add an entry to LH's include directory table. */
static void
add_include_dir (struct line_header *lh, const char *include_dir)
{
+ if (dwarf_line_debug >= 2)
+ fprintf_unfiltered (gdb_stdlog, "Adding dir %u: %s\n",
+ lh->num_include_dirs + 1, include_dir);
+
/* Grow the array if necessary. */
if (lh->include_dirs_size == 0)
{
{
struct file_entry *fe;
+ if (dwarf_line_debug >= 2)
+ fprintf_unfiltered (gdb_stdlog, "Adding file %u: %s\n",
+ lh->num_file_names + 1, name);
+
/* Grow the array if necessary. */
if (lh->file_names_size == 0)
{
fe->symtab = NULL;
}
-/* A convenience function to find the proper .debug_line section for a
- CU. */
+/* A convenience function to find the proper .debug_line section for a CU. */
static struct dwarf2_section_info *
get_debug_line_section (struct dwarf2_cu *cu)
/* Read the statement program header starting at OFFSET in
.debug_line, or .debug_line.dwo. Return a pointer
to a struct line_header, allocated using xmalloc.
+ Returns NULL if there is a problem reading the header, e.g., if it
+ has a version we don't understand.
NOTE: the strings in the include directory and file name tables of
the returned object point into the dwarf line section buffer,
back_to = make_cleanup ((make_cleanup_ftype *) free_line_header,
(void *) lh);
+ lh->offset.sect_off = offset;
+ lh->offset_in_dwz = cu->per_cu->is_dwz;
+
line_ptr = section->buffer + offset;
/* Read in the header. */
lh->statement_program_end = line_ptr + lh->total_length;
lh->version = read_2_bytes (abfd, line_ptr);
line_ptr += 2;
+ if (lh->version > 4)
+ {
+ /* This is a version we don't understand. The format could have
+ changed in ways we don't handle properly so just punt. */
+ complaint (&symfile_complaints,
+ _("unsupported version in .debug_line section"));
+ return NULL;
+ }
lh->header_length = read_offset_1 (abfd, line_ptr, offset_size);
line_ptr += offset_size;
lh->minimum_instruction_length = read_1_byte (abfd, line_ptr);
char *copied_name = NULL;
int file_is_pst;
- if (fe.dir_index)
+ if (fe.dir_index && lh->include_dirs != NULL)
dir_name = lh->include_dirs[fe.dir_index - 1];
if (!IS_ABSOLUTE_PATH (include_name)
include_name = "hello.c"
dir_name = "."
DW_AT_comp_dir = comp_dir = "/tmp"
- DW_AT_name = "./hello.c" */
+ DW_AT_name = "./hello.c"
+
+ */
if (dir_name != NULL)
{
return include_name;
}
+/* State machine to track the state of the line number program. */
+
+typedef struct
+{
+ /* These are part of the standard DWARF line number state machine. */
+
+ unsigned char op_index;
+ unsigned int file;
+ unsigned int line;
+ CORE_ADDR address;
+ int is_stmt;
+ unsigned int discriminator;
+
+ /* Additional bits of state we need to track. */
+
+ /* The last file that we called dwarf2_start_subfile for.
+ This is only used for TLLs. */
+ unsigned int last_file;
+ /* The last file a line number was recorded for. */
+ struct subfile *last_subfile;
+
+ /* The function to call to record a line. */
+ record_line_ftype *record_line;
+
+ /* The last line number that was recorded, used to coalesce
+ consecutive entries for the same line. This can happen, for
+ example, when discriminators are present. PR 17276. */
+ unsigned int last_line;
+ int line_has_non_zero_discriminator;
+} lnp_state_machine;
+
+/* There's a lot of static state to pass to dwarf_record_line.
+ This keeps it all together. */
+
+typedef struct
+{
+ /* The gdbarch. */
+ struct gdbarch *gdbarch;
+
+ /* The line number header. */
+ struct line_header *line_header;
+
+ /* Non-zero if we're recording lines.
+ Otherwise we're building partial symtabs and are just interested in
+ finding include files mentioned by the line number program. */
+ int record_lines_p;
+} lnp_reader_state;
+
/* Ignore this record_line request. */
static void
return;
}
+/* Return non-zero if we should add LINE to the line number table.
+ LINE is the line to add, LAST_LINE is the last line that was added,
+ LAST_SUBFILE is the subfile for LAST_LINE.
+ LINE_HAS_NON_ZERO_DISCRIMINATOR is non-zero if LINE has ever
+ had a non-zero discriminator.
+
+ We have to be careful in the presence of discriminators.
+ E.g., for this line:
+
+ for (i = 0; i < 100000; i++);
+
+ clang can emit four line number entries for that one line,
+ each with a different discriminator.
+ See gdb.dwarf2/dw2-single-line-discriminators.exp for an example.
+
+ However, we want gdb to coalesce all four entries into one.
+ Otherwise the user could stepi into the middle of the line and
+ gdb would get confused about whether the pc really was in the
+ middle of the line.
+
+ Things are further complicated by the fact that two consecutive
+ line number entries for the same line is a heuristic used by gcc
+ to denote the end of the prologue. So we can't just discard duplicate
+ entries, we have to be selective about it. The heuristic we use is
+ that we only collapse consecutive entries for the same line if at least
+ one of those entries has a non-zero discriminator. PR 17276.
+
+ Note: Addresses in the line number state machine can never go backwards
+ within one sequence, thus this coalescing is ok. */
+
+static int
+dwarf_record_line_p (unsigned int line, unsigned int last_line,
+ int line_has_non_zero_discriminator,
+ struct subfile *last_subfile)
+{
+ if (current_subfile != last_subfile)
+ return 1;
+ if (line != last_line)
+ return 1;
+ /* Same line for the same file that we've seen already.
+ As a last check, for pr 17276, only record the line if the line
+ has never had a non-zero discriminator. */
+ if (!line_has_non_zero_discriminator)
+ return 1;
+ return 0;
+}
+
+/* Use P_RECORD_LINE to record line number LINE beginning at address ADDRESS
+ in the line table of subfile SUBFILE. */
+
+static void
+dwarf_record_line_1 (struct gdbarch *gdbarch, struct subfile *subfile,
+ unsigned int line, CORE_ADDR address,
+ record_line_ftype p_record_line)
+{
+ CORE_ADDR addr = gdbarch_addr_bits_remove (gdbarch, address);
+
+ if (dwarf_line_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog,
+ "Recording line %u, file %s, address %s\n",
+ line, lbasename (subfile->name),
+ paddress (gdbarch, address));
+ }
+
+ (*p_record_line) (subfile, line, addr);
+}
+
+/* Subroutine of dwarf_decode_lines_1 to simplify it.
+ Mark the end of a set of line number records.
+ The arguments are the same as for dwarf_record_line_1.
+ If SUBFILE is NULL the request is ignored. */
+
+static void
+dwarf_finish_line (struct gdbarch *gdbarch, struct subfile *subfile,
+ CORE_ADDR address, record_line_ftype p_record_line)
+{
+ if (subfile == NULL)
+ return;
+
+ if (dwarf_line_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog,
+ "Finishing current line, file %s, address %s\n",
+ lbasename (subfile->name),
+ paddress (gdbarch, address));
+ }
+
+ dwarf_record_line_1 (gdbarch, subfile, 0, address, p_record_line);
+}
+
+/* Record the line in STATE.
+ END_SEQUENCE is non-zero if we're processing the end of a sequence. */
+
+static void
+dwarf_record_line (lnp_reader_state *reader, lnp_state_machine *state,
+ int end_sequence)
+{
+ const struct line_header *lh = reader->line_header;
+ unsigned int file, line, discriminator;
+ int is_stmt;
+
+ file = state->file;
+ line = state->line;
+ is_stmt = state->is_stmt;
+ discriminator = state->discriminator;
+
+ if (dwarf_line_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog,
+ "Processing actual line %u: file %u,"
+ " address %s, is_stmt %u, discrim %u\n",
+ line, file,
+ paddress (reader->gdbarch, state->address),
+ is_stmt, discriminator);
+ }
+
+ if (file == 0 || file - 1 >= lh->num_file_names)
+ dwarf2_debug_line_missing_file_complaint ();
+ /* For now we ignore lines not starting on an instruction boundary.
+ But not when processing end_sequence for compatibility with the
+ previous version of the code. */
+ else if (state->op_index == 0 || end_sequence)
+ {
+ lh->file_names[file - 1].included_p = 1;
+ if (reader->record_lines_p && is_stmt)
+ {
+ if (state->last_subfile != current_subfile)
+ {
+ dwarf_finish_line (reader->gdbarch, state->last_subfile,
+ state->address, state->record_line);
+ }
+
+ if (!end_sequence)
+ {
+ if (dwarf_record_line_p (line, state->last_line,
+ state->line_has_non_zero_discriminator,
+ state->last_subfile))
+ {
+ dwarf_record_line_1 (reader->gdbarch, current_subfile,
+ line, state->address,
+ state->record_line);
+ }
+ state->last_subfile = current_subfile;
+ state->last_line = line;
+ }
+ }
+ }
+}
+
+/* Initialize STATE for the start of a line number program. */
+
+static void
+init_lnp_state_machine (lnp_state_machine *state,
+ const lnp_reader_state *reader)
+{
+ memset (state, 0, sizeof (*state));
+
+ /* Just starting, there is no "last file". */
+ state->last_file = 0;
+ state->last_subfile = NULL;
+
+ state->record_line = record_line;
+
+ state->last_line = 0;
+ state->line_has_non_zero_discriminator = 0;
+
+ /* Initialize these according to the DWARF spec. */
+ state->op_index = 0;
+ state->file = 1;
+ state->line = 1;
+ /* Call `gdbarch_adjust_dwarf2_line' on the initial 0 address as if there
+ was a line entry for it so that the backend has a chance to adjust it
+ and also record it in case it needs it. This is currently used by MIPS
+ code, cf. `mips_adjust_dwarf2_line'. */
+ state->address = gdbarch_adjust_dwarf2_line (reader->gdbarch, 0, 0);
+ state->is_stmt = reader->line_header->default_is_stmt;
+ state->discriminator = 0;
+}
+
+/* Check address and if invalid nop-out the rest of the lines in this
+ sequence. */
+
+static void
+check_line_address (struct dwarf2_cu *cu, lnp_state_machine *state,
+ const gdb_byte *line_ptr,
+ CORE_ADDR lowpc, CORE_ADDR address)
+{
+ /* If address < lowpc then it's not a usable value, it's outside the
+ pc range of the CU. However, we restrict the test to only address
+ values of zero to preserve GDB's previous behaviour which is to
+ handle the specific case of a function being GC'd by the linker. */
+
+ if (address == 0 && address < lowpc)
+ {
+ /* This line table is for a function which has been
+ GCd by the linker. Ignore it. PR gdb/12528 */
+
+ struct objfile *objfile = cu->objfile;
+ long line_offset = line_ptr - get_debug_line_section (cu)->buffer;
+
+ complaint (&symfile_complaints,
+ _(".debug_line address at offset 0x%lx is 0 [in module %s]"),
+ line_offset, objfile_name (objfile));
+ state->record_line = noop_record_line;
+ /* Note: sm.record_line is left as noop_record_line
+ until we see DW_LNE_end_sequence. */
+ }
+}
+
/* Subroutine of dwarf_decode_lines to simplify it.
- Process the line number information in LH. */
+ Process the line number information in LH.
+ If DECODE_FOR_PST_P is non-zero, all we do is process the line number
+ program in order to set included_p for every referenced header. */
static void
-dwarf_decode_lines_1 (struct line_header *lh, const char *comp_dir,
- struct dwarf2_cu *cu, struct partial_symtab *pst)
+dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu,
+ const int decode_for_pst_p, CORE_ADDR lowpc)
{
const gdb_byte *line_ptr, *extended_end;
const gdb_byte *line_end;
unsigned int bytes_read, extended_len;
- unsigned char op_code, extended_op, adj_opcode;
+ unsigned char op_code, extended_op;
CORE_ADDR baseaddr;
struct objfile *objfile = cu->objfile;
bfd *abfd = objfile->obfd;
struct gdbarch *gdbarch = get_objfile_arch (objfile);
- const int decode_for_pst_p = (pst != NULL);
- struct subfile *last_subfile = NULL;
- void (*p_record_line) (struct subfile *subfile, int line, CORE_ADDR pc)
- = record_line;
+ /* Non-zero if we're recording line info (as opposed to building partial
+ symtabs). */
+ int record_lines_p = !decode_for_pst_p;
+ /* A collection of things we need to pass to dwarf_record_line. */
+ lnp_reader_state reader_state;
baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
line_ptr = lh->statement_program_start;
line_end = lh->statement_program_end;
+ reader_state.gdbarch = gdbarch;
+ reader_state.line_header = lh;
+ reader_state.record_lines_p = record_lines_p;
+
/* Read the statement sequences until there's nothing left. */
while (line_ptr < line_end)
{
- /* state machine registers */
- CORE_ADDR address = 0;
- unsigned int file = 1;
- unsigned int line = 1;
- unsigned int column = 0;
- int is_stmt = lh->default_is_stmt;
- int basic_block = 0;
+ /* The DWARF line number program state machine. */
+ lnp_state_machine state_machine;
int end_sequence = 0;
- CORE_ADDR addr;
- unsigned char op_index = 0;
- if (!decode_for_pst_p && lh->num_file_names >= file)
+ /* Reset the state machine at the start of each sequence. */
+ init_lnp_state_machine (&state_machine, &reader_state);
+
+ if (record_lines_p && lh->num_file_names >= state_machine.file)
{
/* Start a subfile for the current file of the state machine. */
/* lh->include_dirs and lh->file_names are 0-based, but the
directory and file name numbers in the statement program
are 1-based. */
- struct file_entry *fe = &lh->file_names[file - 1];
+ struct file_entry *fe = &lh->file_names[state_machine.file - 1];
const char *dir = NULL;
- if (fe->dir_index)
+ if (fe->dir_index && lh->include_dirs != NULL)
dir = lh->include_dirs[fe->dir_index - 1];
- dwarf2_start_subfile (fe->name, dir, comp_dir);
+ dwarf2_start_subfile (fe->name, dir);
}
/* Decode the table. */
- while (!end_sequence)
+ while (line_ptr < line_end && !end_sequence)
{
op_code = read_1_byte (abfd, line_ptr);
line_ptr += 1;
- if (line_ptr > line_end)
- {
- dwarf2_debug_line_missing_end_sequence_complaint ();
- break;
- }
if (op_code >= lh->opcode_base)
{
- /* Special operand. */
+ /* Special opcode. */
+ unsigned char adj_opcode;
+ CORE_ADDR addr_adj;
+ int line_delta;
+
adj_opcode = op_code - lh->opcode_base;
- address += (((op_index + (adj_opcode / lh->line_range))
+ addr_adj = (((state_machine.op_index
+ + (adj_opcode / lh->line_range))
/ lh->maximum_ops_per_instruction)
* lh->minimum_instruction_length);
- op_index = ((op_index + (adj_opcode / lh->line_range))
- % lh->maximum_ops_per_instruction);
- line += lh->line_base + (adj_opcode % lh->line_range);
- if (lh->num_file_names < file || file == 0)
- dwarf2_debug_line_missing_file_complaint ();
- /* For now we ignore lines not starting on an
- instruction boundary. */
- else if (op_index == 0)
- {
- lh->file_names[file - 1].included_p = 1;
- if (!decode_for_pst_p && is_stmt)
- {
- if (last_subfile != current_subfile)
- {
- addr = gdbarch_addr_bits_remove (gdbarch, address);
- if (last_subfile)
- (*p_record_line) (last_subfile, 0, addr);
- last_subfile = current_subfile;
- }
- /* Append row to matrix using current values. */
- addr = gdbarch_addr_bits_remove (gdbarch, address);
- (*p_record_line) (current_subfile, line, addr);
- }
- }
- basic_block = 0;
+ state_machine.address
+ += gdbarch_adjust_dwarf2_line (gdbarch, addr_adj, 1);
+ state_machine.op_index = ((state_machine.op_index
+ + (adj_opcode / lh->line_range))
+ % lh->maximum_ops_per_instruction);
+ line_delta = lh->line_base + (adj_opcode % lh->line_range);
+ state_machine.line += line_delta;
+ if (line_delta != 0)
+ state_machine.line_has_non_zero_discriminator
+ = state_machine.discriminator != 0;
+
+ dwarf_record_line (&reader_state, &state_machine, 0);
+ state_machine.discriminator = 0;
}
else switch (op_code)
{
switch (extended_op)
{
case DW_LNE_end_sequence:
- p_record_line = record_line;
+ state_machine.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 - get_debug_line_section (cu)->buffer;
-
- complaint (&symfile_complaints,
- _(".debug_line address at offset 0x%lx is 0 "
- "[in module %s]"),
- line_offset, objfile_name (objfile));
- p_record_line = noop_record_line;
- }
+ {
+ CORE_ADDR address
+ = read_address (abfd, line_ptr, cu, &bytes_read);
- op_index = 0;
- line_ptr += bytes_read;
- address += baseaddr;
+ line_ptr += bytes_read;
+ check_line_address (cu, &state_machine, line_ptr,
+ lowpc, address);
+ state_machine.op_index = 0;
+ address += baseaddr;
+ state_machine.address
+ = gdbarch_adjust_dwarf2_line (gdbarch, address, 0);
+ }
break;
case DW_LNE_define_file:
{
break;
case DW_LNE_set_discriminator:
/* The discriminator is not interesting to the debugger;
- just ignore it. */
- line_ptr = extended_end;
+ just ignore it. We still need to check its value though:
+ if there are consecutive entries for the same
+ (non-prologue) line we want to coalesce them.
+ PR 17276. */
+ state_machine.discriminator
+ = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+ state_machine.line_has_non_zero_discriminator
+ |= state_machine.discriminator != 0;
+ line_ptr += bytes_read;
break;
default:
complaint (&symfile_complaints,
}
break;
case DW_LNS_copy:
- if (lh->num_file_names < file || file == 0)
- dwarf2_debug_line_missing_file_complaint ();
- else
- {
- lh->file_names[file - 1].included_p = 1;
- if (!decode_for_pst_p && is_stmt)
- {
- if (last_subfile != current_subfile)
- {
- addr = gdbarch_addr_bits_remove (gdbarch, address);
- if (last_subfile)
- (*p_record_line) (last_subfile, 0, addr);
- last_subfile = current_subfile;
- }
- addr = gdbarch_addr_bits_remove (gdbarch, address);
- (*p_record_line) (current_subfile, line, addr);
- }
- }
- basic_block = 0;
+ dwarf_record_line (&reader_state, &state_machine, 0);
+ state_machine.discriminator = 0;
break;
case DW_LNS_advance_pc:
{
CORE_ADDR adjust
= read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+ CORE_ADDR addr_adj;
- address += (((op_index + adjust)
+ addr_adj = (((state_machine.op_index + adjust)
/ lh->maximum_ops_per_instruction)
* lh->minimum_instruction_length);
- op_index = ((op_index + adjust)
- % lh->maximum_ops_per_instruction);
+ state_machine.address
+ += gdbarch_adjust_dwarf2_line (gdbarch, addr_adj, 1);
+ state_machine.op_index = ((state_machine.op_index + adjust)
+ % lh->maximum_ops_per_instruction);
line_ptr += bytes_read;
}
break;
case DW_LNS_advance_line:
- line += read_signed_leb128 (abfd, line_ptr, &bytes_read);
- line_ptr += bytes_read;
+ {
+ int line_delta
+ = read_signed_leb128 (abfd, line_ptr, &bytes_read);
+
+ state_machine.line += line_delta;
+ if (line_delta != 0)
+ state_machine.line_has_non_zero_discriminator
+ = state_machine.discriminator != 0;
+ line_ptr += bytes_read;
+ }
break;
case DW_LNS_set_file:
- {
- /* The arrays lh->include_dirs and lh->file_names are
- 0-based, but the directory and file name numbers in
- the statement program are 1-based. */
- struct file_entry *fe;
- const char *dir = NULL;
-
- file = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
- line_ptr += bytes_read;
- if (lh->num_file_names < file || file == 0)
- dwarf2_debug_line_missing_file_complaint ();
- else
- {
- fe = &lh->file_names[file - 1];
- if (fe->dir_index)
- dir = lh->include_dirs[fe->dir_index - 1];
- if (!decode_for_pst_p)
- {
- last_subfile = current_subfile;
- dwarf2_start_subfile (fe->name, dir, comp_dir);
- }
- }
- }
+ {
+ /* The arrays lh->include_dirs and lh->file_names are
+ 0-based, but the directory and file name numbers in
+ the statement program are 1-based. */
+ struct file_entry *fe;
+ const char *dir = NULL;
+
+ state_machine.file = read_unsigned_leb128 (abfd, line_ptr,
+ &bytes_read);
+ line_ptr += bytes_read;
+ if (state_machine.file == 0
+ || state_machine.file - 1 >= lh->num_file_names)
+ dwarf2_debug_line_missing_file_complaint ();
+ else
+ {
+ fe = &lh->file_names[state_machine.file - 1];
+ if (fe->dir_index && lh->include_dirs != NULL)
+ dir = lh->include_dirs[fe->dir_index - 1];
+ if (record_lines_p)
+ {
+ state_machine.last_subfile = current_subfile;
+ state_machine.line_has_non_zero_discriminator
+ = state_machine.discriminator != 0;
+ dwarf2_start_subfile (fe->name, dir);
+ }
+ }
+ }
break;
case DW_LNS_set_column:
- column = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+ (void) read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
line_ptr += bytes_read;
break;
case DW_LNS_negate_stmt:
- is_stmt = (!is_stmt);
+ state_machine.is_stmt = (!state_machine.is_stmt);
break;
case DW_LNS_set_basic_block:
- basic_block = 1;
break;
/* Add to the address register of the state machine the
address increment value corresponding to special opcode
case DW_LNS_const_add_pc:
{
CORE_ADDR adjust = (255 - lh->opcode_base) / lh->line_range;
+ CORE_ADDR addr_adj;
- address += (((op_index + adjust)
+ addr_adj = (((state_machine.op_index + adjust)
/ lh->maximum_ops_per_instruction)
* lh->minimum_instruction_length);
- op_index = ((op_index + adjust)
- % lh->maximum_ops_per_instruction);
+ state_machine.address
+ += gdbarch_adjust_dwarf2_line (gdbarch, addr_adj, 1);
+ state_machine.op_index = ((state_machine.op_index + adjust)
+ % lh->maximum_ops_per_instruction);
}
break;
case DW_LNS_fixed_advance_pc:
- address += read_2_bytes (abfd, line_ptr);
- op_index = 0;
- line_ptr += 2;
+ {
+ CORE_ADDR addr_adj;
+
+ addr_adj = read_2_bytes (abfd, line_ptr);
+ state_machine.address
+ += gdbarch_adjust_dwarf2_line (gdbarch, addr_adj, 1);
+ state_machine.op_index = 0;
+ line_ptr += 2;
+ }
break;
default:
{
}
}
}
- if (lh->num_file_names < file || file == 0)
- dwarf2_debug_line_missing_file_complaint ();
- else
- {
- lh->file_names[file - 1].included_p = 1;
- if (!decode_for_pst_p)
- {
- addr = gdbarch_addr_bits_remove (gdbarch, address);
- (*p_record_line) (current_subfile, 0, addr);
- }
- }
+
+ if (!end_sequence)
+ dwarf2_debug_line_missing_end_sequence_complaint ();
+
+ /* We got a DW_LNE_end_sequence (or we ran off the end of the buffer,
+ in which case we still finish recording the last line). */
+ dwarf_record_line (&reader_state, &state_machine, 1);
}
}
as the corresponding symtab. Since COMP_DIR is not used in the name of the
symtab we don't use it in the name of the psymtabs we create.
E.g. expand_line_sal requires this when finding psymtabs to expand.
- A good testcase for this is mb-inline.exp. */
+ A good testcase for this is mb-inline.exp.
+
+ LOWPC is the lowest address in CU (or 0 if not known).
+
+ Boolean DECODE_MAPPING specifies we need to fully decode .debug_line
+ for its PC<->lines mapping information. Otherwise only the filename
+ table is read in. */
static void
dwarf_decode_lines (struct line_header *lh, const char *comp_dir,
struct dwarf2_cu *cu, struct partial_symtab *pst,
- int want_line_info)
+ CORE_ADDR lowpc, int decode_mapping)
{
struct objfile *objfile = cu->objfile;
const int decode_for_pst_p = (pst != NULL);
- struct subfile *first_subfile = current_subfile;
- if (want_line_info)
- dwarf_decode_lines_1 (lh, comp_dir, cu, pst);
+ if (decode_mapping)
+ dwarf_decode_lines_1 (lh, cu, decode_for_pst_p, lowpc);
if (decode_for_pst_p)
{
/* Make sure a symtab is created for every file, even files
which contain only variables (i.e. no code with associated
line numbers). */
+ struct compunit_symtab *cust = buildsym_compunit_symtab ();
int i;
for (i = 0; i < lh->num_file_names; i++)
struct file_entry *fe;
fe = &lh->file_names[i];
- if (fe->dir_index)
+ if (fe->dir_index && lh->include_dirs != NULL)
dir = lh->include_dirs[fe->dir_index - 1];
- dwarf2_start_subfile (fe->name, dir, comp_dir);
-
- /* Skip the main file; we don't need it, and it must be
- allocated last, so that it will show up before the
- non-primary symtabs in the objfile's symtab list. */
- if (current_subfile == first_subfile)
- continue;
+ dwarf2_start_subfile (fe->name, dir);
if (current_subfile->symtab == NULL)
- current_subfile->symtab = allocate_symtab (current_subfile->name,
- objfile);
+ {
+ current_subfile->symtab
+ = allocate_symtab (cust, current_subfile->name);
+ }
fe->symtab = current_subfile->symtab;
}
}
/* Start a subfile for DWARF. FILENAME is the name of the file and
DIRNAME the name of the source directory which contains FILENAME
- or NULL if not known. COMP_DIR is the compilation directory for the
- linetable's compilation unit or NULL if not known.
+ or NULL if not known.
This routine tries to keep line numbers from identical absolute and
relative file names in a common subfile.
of /srcdir/list0.c yields the following debugging information for list0.c:
DW_AT_name: /srcdir/list0.c
- DW_AT_comp_dir: /compdir
+ DW_AT_comp_dir: /compdir
files.files[0].name: list0.h
files.files[0].dir: /srcdir
files.files[1].name: list0.c
subfile's name. */
static void
-dwarf2_start_subfile (const char *filename, const char *dirname,
- const char *comp_dir)
+dwarf2_start_subfile (const char *filename, const char *dirname)
{
char *copy = NULL;
- /* While reading the DIEs, we call start_symtab(DW_AT_name, DW_AT_comp_dir).
- `start_symtab' will always pass the contents of DW_AT_comp_dir as
- second argument to start_subfile. To be consistent, we do the
- same here. In order not to lose the line information directory,
+ /* In order not to lose the line information directory,
we concatenate it to the filename when it makes sense.
Note that the Dwarf3 standard says (speaking of filenames in line
information): ``The directory index is ignored for file names
filename = copy;
}
- start_subfile (filename, comp_dir);
+ start_subfile (filename);
if (copy != NULL)
xfree (copy);
/* Start a symtab for DWARF.
NAME, COMP_DIR, LOW_PC are passed to start_symtab. */
-static void
+static struct compunit_symtab *
dwarf2_start_symtab (struct dwarf2_cu *cu,
const char *name, const char *comp_dir, CORE_ADDR low_pc)
{
- start_symtab (name, comp_dir, low_pc);
+ struct compunit_symtab *cust
+ = start_symtab (cu->objfile, name, comp_dir, low_pc);
+
record_debugformat ("DWARF 2");
record_producer (cu->producer);
processing_gcc_compilation = 2;
cu->processing_has_namespace_info = 0;
+
+ return cust;
}
static void
struct symbol *space)
{
struct objfile *objfile = cu->objfile;
+ struct gdbarch *gdbarch = get_objfile_arch (objfile);
struct symbol *sym = NULL;
const char *name;
struct attribute *attr = NULL;
struct file_entry *fe;
fe = &cu->line_header->file_names[file_index - 1];
- SYMBOL_SYMTAB (sym) = fe->symtab;
+ symbol_set_symtab (sym, fe->symtab);
}
}
attr = dwarf2_attr (die, DW_AT_low_pc, cu);
if (attr)
{
- SYMBOL_VALUE_ADDRESS (sym) = DW_ADDR (attr) + baseaddr;
+ CORE_ADDR addr;
+
+ addr = attr_value_as_address (attr);
+ addr = gdbarch_adjust_dwarf2_addr (gdbarch, addr + baseaddr);
+ SYMBOL_VALUE_ADDRESS (sym) = addr;
}
SYMBOL_TYPE (sym) = objfile_type (objfile)->builtin_core_addr;
SYMBOL_DOMAIN (sym) = LABEL_DOMAIN;
if (cu->language == language_fortran && die->parent
&& die->parent->tag == DW_TAG_module
&& cu->producer
- && strncmp (cu->producer, "GNU Fortran ", 12) == 0)
+ && startswith (cu->producer, "GNU Fortran "))
SYMBOL_ACLASS_INDEX (sym) = LOC_UNRESOLVED;
/* A variable with DW_AT_external is never static,
case DW_TAG_module:
this_type = read_module_type (die, cu);
break;
+ case DW_TAG_atomic_type:
+ this_type = read_tag_atomic_type (die, cu);
+ break;
default:
complaint (&symfile_complaints,
_("unexpected tag in read_type_die: '%s'"),
&& actual_name[actual_name_len
- die_name_len - 1] == ':')
name =
- obstack_copy0 (&cu->objfile->objfile_obstack,
+ obstack_copy0 (&cu->objfile->per_bfd->storage_obstack,
actual_name,
actual_name_len - die_name_len - 2);
}
if (base == NULL || base == DW_STRING (attr) || base[-1] != ':')
return "";
- return obstack_copy0 (&cu->objfile->objfile_obstack,
+ return obstack_copy0 (&cu->objfile->per_bfd->storage_obstack,
DW_STRING (attr), &base[-1] - DW_STRING (attr));
}
return name;
}
return "";
+ case DW_TAG_enumeration_type:
+ parent_type = read_type_die (parent, cu);
+ if (TYPE_DECLARED_CLASS (parent_type))
+ {
+ if (TYPE_TAG_NAME (parent_type) != NULL)
+ return TYPE_TAG_NAME (parent_type);
+ return "";
+ }
+ /* Fall through. */
default:
return determine_prefix (parent, cu);
}
return name;
}
-/* Get name of a die, return NULL if not found. */
+/* Get name of a die, return NULL if not found.
+ Anonymous namespaces are converted to their magic string. */
static const char *
dwarf2_name (struct die_info *die, struct dwarf2_cu *cu)
attr = dwarf2_attr (die, DW_AT_name, cu);
if ((!attr || !DW_STRING (attr))
+ && die->tag != DW_TAG_namespace
&& die->tag != DW_TAG_class_type
&& die->tag != DW_TAG_interface_type
&& die->tag != DW_TAG_structure_type
to canonicalize them. */
return DW_STRING (attr);
+ case DW_TAG_namespace:
+ if (attr != NULL && DW_STRING (attr) != NULL)
+ return DW_STRING (attr);
+ return CP_ANONYMOUS_NAMESPACE_STR;
+
case DW_TAG_subprogram:
/* Java constructors will all be named "<init>", so return
the class name when we see this special case. */
/* GCJ will output '<init>' for Java constructor names.
For this special case, return the name of the parent class. */
- /* GCJ may output suprogram DIEs with AT_specification set.
+ /* GCJ may output subprogram DIEs with AT_specification set.
If so, use the name of the specified DIE. */
spec_die = die_specification (die, &spec_cu);
if (spec_die != NULL)
or simply "<anonymous struct>" or "<anonymous union>" in GCC 4.3
and GCC 4.4. We work around this problem by ignoring these. */
if (attr && DW_STRING (attr)
- && (strncmp (DW_STRING (attr), "._", 2) == 0
- || strncmp (DW_STRING (attr), "<anonymous", 10) == 0))
+ && (startswith (DW_STRING (attr), "._")
+ || startswith (DW_STRING (attr), "<anonymous")))
return NULL;
/* GCC might emit a nameless typedef that has a linkage name. See
char *base;
/* FIXME: we already did this for the partial symbol... */
- DW_STRING (attr) = obstack_copy0 (&cu->objfile->objfile_obstack,
- demangled, strlen (demangled));
+ DW_STRING (attr)
+ = obstack_copy0 (&cu->objfile->per_bfd->storage_obstack,
+ demangled, strlen (demangled));
DW_STRING_IS_CANONICAL (attr) = 1;
xfree (demangled);
{
DW_STRING (attr)
= dwarf2_canonicalize_name (DW_STRING (attr), cu,
- &cu->objfile->objfile_obstack);
+ &cu->objfile->per_bfd->storage_obstack);
DW_STRING_IS_CANONICAL (attr) = 1;
}
return DW_STRING (attr);
{
struct file_entry *fe = &lh->file_names[file - 1];
- if (IS_ABSOLUTE_PATH (fe->name) || fe->dir_index == 0)
+ if (IS_ABSOLUTE_PATH (fe->name) || fe->dir_index == 0
+ || lh->include_dirs == NULL)
return xstrdup (fe->name);
return concat (lh->include_dirs[fe->dir_index - 1], SLASH_STRING,
fe->name, NULL);
static struct macro_source_file *
macro_start_file (int file, int line,
struct macro_source_file *current_file,
- const char *comp_dir,
- struct line_header *lh, struct objfile *objfile)
+ struct line_header *lh)
{
/* File name relative to the compilation directory of this source file. */
char *file_name = file_file_name (file, lh);
{
/* Note: We don't create a macro table for this compilation unit
at all until we actually get a filename. */
- struct macro_table *macro_table = get_macro_table (objfile, comp_dir);
+ struct macro_table *macro_table = get_macro_table ();
/* If we have no current file, then this must be the start_file
directive for the compilation unit's main source file. */
dwarf_decode_macro_bytes (bfd *abfd,
const gdb_byte *mac_ptr, const gdb_byte *mac_end,
struct macro_source_file *current_file,
- struct line_header *lh, const char *comp_dir,
+ struct line_header *lh,
struct dwarf2_section_info *section,
int section_is_gnu, int section_is_dwz,
unsigned int offset_size,
- struct objfile *objfile,
htab_t include_hash)
{
+ struct objfile *objfile = dwarf2_per_objfile->objfile;
enum dwarf_macro_record_type macinfo_type;
int at_commandline;
const gdb_byte *opcode_definitions[256];
at_commandline = 0;
}
else
- current_file = macro_start_file (file, line,
- current_file, comp_dir,
- lh, objfile);
+ current_file = macro_start_file (file, line, current_file, lh);
}
break;
{
struct dwz_file *dwz = dwarf2_get_dwz_file ();
- dwarf2_read_section (dwarf2_per_objfile->objfile,
- &dwz->macro);
+ dwarf2_read_section (objfile, &dwz->macro);
include_section = &dwz->macro;
include_bfd = get_section_bfd_owner (include_section);
*slot = (void *) new_mac_ptr;
dwarf_decode_macro_bytes (include_bfd, new_mac_ptr,
- include_mac_end, current_file,
- lh, comp_dir,
+ include_mac_end, current_file, lh,
section, section_is_gnu, is_dwz,
- offset_size, objfile, include_hash);
+ offset_size, include_hash);
htab_remove_elt (include_hash, (void *) new_mac_ptr);
}
static void
dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset,
- const char *comp_dir, int section_is_gnu)
+ int section_is_gnu)
{
struct objfile *objfile = dwarf2_per_objfile->objfile;
struct line_header *lh = cu->line_header;
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, objfile);
+ current_file = macro_start_file (file, line, current_file, lh);
}
break;
slot = htab_find_slot (include_hash, mac_ptr, INSERT);
*slot = (void *) mac_ptr;
dwarf_decode_macro_bytes (abfd, mac_ptr, mac_end,
- current_file, lh, comp_dir, section,
- section_is_gnu, 0,
- offset_size, objfile, include_hash);
+ current_file, lh, section,
+ section_is_gnu, 0, offset_size, include_hash);
do_cleanups (cleanup);
}
while (per_cu != NULL)
{
per_cu->cu->last_used ++;
- if (per_cu->cu->last_used <= dwarf2_max_cache_age)
+ if (per_cu->cu->last_used <= dwarf_max_cache_age)
dwarf2_mark (per_cu->cu);
per_cu = per_cu->cu->read_in_chain;
}
if (dwarf2_per_objfile->quick_file_names_table)
htab_delete (dwarf2_per_objfile->quick_file_names_table);
+ if (dwarf2_per_objfile->line_header_hash)
+ htab_delete (dwarf2_per_objfile->line_header_hash);
+
/* Everything else should be on the objfile obstack. */
}
{
struct dwarf2_per_cu_offset_and_type **slot, ofs;
struct objfile *objfile = cu->objfile;
+ struct attribute *attr;
+ struct dynamic_prop prop;
/* For Ada types, make sure that the gnat-specific data is always
initialized (if not already set). There are a few types where
if (need_gnat_info (cu)
&& TYPE_CODE (type) != TYPE_CODE_FUNC
&& TYPE_CODE (type) != TYPE_CODE_FLT
+ && TYPE_CODE (type) != TYPE_CODE_METHODPTR
+ && TYPE_CODE (type) != TYPE_CODE_MEMBERPTR
+ && TYPE_CODE (type) != TYPE_CODE_METHOD
&& !HAVE_GNAT_AUX_INFO (type))
INIT_GNAT_SPECIFIC (type);
+ /* Read DW_AT_data_location and set in type. */
+ attr = dwarf2_attr (die, DW_AT_data_location, cu);
+ if (attr_to_dynamic_prop (attr, die, cu, &prop))
+ add_dyn_prop (DYN_PROP_DATA_LOCATION, prop, type, objfile);
+
if (dwarf2_per_objfile->die_type_hash == NULL)
{
dwarf2_per_objfile->die_type_hash =
return part_die_lhs->offset.sect_off == part_die_rhs->offset.sect_off;
}
-static struct cmd_list_element *set_dwarf2_cmdlist;
-static struct cmd_list_element *show_dwarf2_cmdlist;
+static struct cmd_list_element *set_dwarf_cmdlist;
+static struct cmd_list_element *show_dwarf_cmdlist;
static void
-set_dwarf2_cmd (char *args, int from_tty)
+set_dwarf_cmd (char *args, int from_tty)
{
- help_list (set_dwarf2_cmdlist, "maintenance set dwarf2 ", -1, gdb_stdout);
+ help_list (set_dwarf_cmdlist, "maintenance set dwarf ", all_commands,
+ gdb_stdout);
}
static void
-show_dwarf2_cmd (char *args, int from_tty)
+show_dwarf_cmd (char *args, int from_tty)
{
- cmd_show_list (show_dwarf2_cmdlist, from_tty, "");
+ cmd_show_list (show_dwarf_cmdlist, from_tty, "");
}
/* Free data associated with OBJFILE, if necessary. */
dwarf2_per_objfile = objfile_data (objfile, dwarf2_objfile_data_key);
if (dwarf2_per_objfile)
{
- volatile struct gdb_exception except;
- TRY_CATCH (except, RETURN_MASK_ERROR)
+ TRY
{
write_psymtabs_to_index (objfile, arg);
}
- if (except.reason < 0)
- exception_fprintf (gdb_stderr, except,
- _("Error while writing index for `%s': "),
- objfile_name (objfile));
+ CATCH (except, RETURN_MASK_ERROR)
+ {
+ exception_fprintf (gdb_stderr, except,
+ _("Error while writing index for `%s': "),
+ objfile_name (objfile));
+ }
+ END_CATCH
}
}
}
\f
-int dwarf2_always_disassemble;
+int dwarf_always_disassemble;
static void
-show_dwarf2_always_disassemble (struct ui_file *file, int from_tty,
- struct cmd_list_element *c, const char *value)
+show_dwarf_always_disassemble (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c, const char *value)
{
fprintf_filtered (file,
_("Whether to always disassemble "
dwarf2_objfile_data_key
= register_objfile_data_with_cleanup (NULL, dwarf2_per_objfile_free);
- add_prefix_cmd ("dwarf2", class_maintenance, set_dwarf2_cmd, _("\
-Set DWARF 2 specific variables.\n\
-Configure DWARF 2 variables such as the cache size"),
- &set_dwarf2_cmdlist, "maintenance set dwarf2 ",
+ add_prefix_cmd ("dwarf", class_maintenance, set_dwarf_cmd, _("\
+Set DWARF specific variables.\n\
+Configure DWARF variables such as the cache size"),
+ &set_dwarf_cmdlist, "maintenance set dwarf ",
0/*allow-unknown*/, &maintenance_set_cmdlist);
- add_prefix_cmd ("dwarf2", class_maintenance, show_dwarf2_cmd, _("\
-Show DWARF 2 specific variables\n\
-Show DWARF 2 variables such as the cache size"),
- &show_dwarf2_cmdlist, "maintenance show dwarf2 ",
+ add_prefix_cmd ("dwarf", class_maintenance, show_dwarf_cmd, _("\
+Show DWARF specific variables\n\
+Show DWARF variables such as the cache size"),
+ &show_dwarf_cmdlist, "maintenance show dwarf ",
0/*allow-unknown*/, &maintenance_show_cmdlist);
add_setshow_zinteger_cmd ("max-cache-age", class_obscure,
- &dwarf2_max_cache_age, _("\
-Set the upper bound on the age of cached dwarf2 compilation units."), _("\
-Show the upper bound on the age of cached dwarf2 compilation units."), _("\
+ &dwarf_max_cache_age, _("\
+Set the upper bound on the age of cached DWARF compilation units."), _("\
+Show the upper bound on the age of cached DWARF compilation units."), _("\
A higher limit means that cached compilation units will be stored\n\
in memory longer, and more total memory will be used. Zero disables\n\
caching, which can slow down startup."),
NULL,
- show_dwarf2_max_cache_age,
- &set_dwarf2_cmdlist,
- &show_dwarf2_cmdlist);
+ show_dwarf_max_cache_age,
+ &set_dwarf_cmdlist,
+ &show_dwarf_cmdlist);
add_setshow_boolean_cmd ("always-disassemble", class_obscure,
- &dwarf2_always_disassemble, _("\
+ &dwarf_always_disassemble, _("\
Set whether `info address' always disassembles DWARF expressions."), _("\
Show whether `info address' always disassembles DWARF expressions."), _("\
When enabled, DWARF expressions are always printed in an assembly-like\n\
syntax. When disabled, expressions will be printed in a more\n\
conversational style, when possible."),
NULL,
- show_dwarf2_always_disassemble,
- &set_dwarf2_cmdlist,
- &show_dwarf2_cmdlist);
-
- add_setshow_zuinteger_cmd ("dwarf2-read", no_class, &dwarf2_read_debug, _("\
-Set debugging of the dwarf2 reader."), _("\
-Show debugging of the dwarf2 reader."), _("\
-When enabled (non-zero), debugging messages are printed during dwarf2\n\
+ show_dwarf_always_disassemble,
+ &set_dwarf_cmdlist,
+ &show_dwarf_cmdlist);
+
+ add_setshow_zuinteger_cmd ("dwarf-read", no_class, &dwarf_read_debug, _("\
+Set debugging of the DWARF reader."), _("\
+Show debugging of the DWARF reader."), _("\
+When enabled (non-zero), debugging messages are printed during DWARF\n\
reading and symtab expansion. A value of 1 (one) provides basic\n\
information. A value greater than 1 provides more verbose information."),
NULL,
NULL,
&setdebuglist, &showdebuglist);
- add_setshow_zuinteger_cmd ("dwarf2-die", no_class, &dwarf2_die_debug, _("\
-Set debugging of the dwarf2 DIE reader."), _("\
-Show debugging of the dwarf2 DIE reader."), _("\
+ add_setshow_zuinteger_cmd ("dwarf-die", no_class, &dwarf_die_debug, _("\
+Set debugging of the DWARF DIE reader."), _("\
+Show debugging of the DWARF DIE reader."), _("\
When enabled (non-zero), DIEs are dumped after they are read in.\n\
The value is the maximum depth to print."),
NULL,
NULL,
&setdebuglist, &showdebuglist);
+ add_setshow_zuinteger_cmd ("dwarf-line", no_class, &dwarf_line_debug, _("\
+Set debugging of the dwarf line reader."), _("\
+Show debugging of the dwarf line reader."), _("\
+When enabled (non-zero), line number entries are dumped as they are read in.\n\
+A value of 1 (one) provides basic information.\n\
+A value greater than 1 provides more verbose information."),
+ NULL,
+ NULL,
+ &setdebuglist, &showdebuglist);
+
add_setshow_boolean_cmd ("check-physname", no_class, &check_physname, _("\
Set cross-checking of \"physname\" code against demangler."), _("\
Show cross-checking of \"physname\" code against demangler."), _("\