/* DWARF 2 debugging format support for GDB.
- Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
- 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
- Free Software Foundation, Inc.
+ Copyright (C) 1994-2012 Free Software Foundation, Inc.
Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology,
Inc. with support from Florida State University (under contract
#include "dwarf2.h"
#include "buildsym.h"
#include "demangle.h"
+#include "gdb-demangle.h"
#include "expression.h"
#include "filenames.h" /* for DOSish file names */
#include "macrotab.h"
const char *constant_pool;
};
+/* Collection of data recorded per objfile.
+ This hangs off of dwarf2_objfile_data_key. */
+
struct dwarf2_per_objfile
{
struct dwarf2_section_info info;
/* Note that if the debugging section has been compressed, it might
have a name like .zdebug_info. */
-static const struct dwarf2_debug_sections dwarf2_elf_names = {
+static const struct dwarf2_debug_sections dwarf2_elf_names =
+{
{ ".debug_info", ".zdebug_info" },
{ ".debug_abbrev", ".zdebug_abbrev" },
{ ".debug_line", ".zdebug_line" },
/* Non-zero if base_address has been set. */
int base_known;
- struct function_range *first_fn, *last_fn, *cached_fn;
-
/* The language we are debugging. */
enum language language;
const struct language_defn *language_defn;
after all type information has been read. */
VEC (delayed_method_info) *method_list;
+ /* To be copied to symtab->call_site_htab. */
+ htab_t call_site_htab;
+
/* Mark used when releasing cached dies. */
unsigned int mark : 1;
This test is imperfect as there may exist optimized debug code not using
any location list and still facing inlining issues if handled as
unoptimized code. For a future better test see GCC PR other/32998. */
-
unsigned int has_loclist : 1;
};
/* Persistent data held for a compilation unit, even when not
processing it. We put a pointer to this structure in the
- read_symtab_private field of the psymtab. If we encounter
- inter-compilation-unit references, we also maintain a sorted
- list of all compilation units. */
+ read_symtab_private field of the psymtab. */
struct dwarf2_per_cu_data
{
/* Non-null if this CU is from .debug_types; in which case it points
to the section. Otherwise it's from .debug_info. */
- struct dwarf2_section_info *debug_type_section;
+ struct dwarf2_section_info *debug_types_section;
/* Set to non-NULL iff this CU is currently loaded. When it gets freed out
of the CU cache it gets reset to NULL again. */
struct dwarf2_cu *cu;
- /* The corresponding objfile. */
+ /* The corresponding objfile.
+ Normally we can get the objfile from dwarf2_per_objfile.
+ 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.
struct attribute attrs[1];
};
-struct function_range
-{
- const char *name;
- CORE_ADDR lowpc, highpc;
- int seen_line;
- struct function_range *next;
-};
-
/* Get at parts of an attribute structure. */
#define DW_STRING(attr) ((attr)->u.str)
struct dwarf_block
{
unsigned int size;
+
+ /* Valid only if SIZE is not zero. */
gdb_byte *data;
};
static void psymtab_to_symtab_1 (struct partial_symtab *);
-static void dwarf2_read_abbrevs (bfd *abfd, struct dwarf2_cu *cu);
+static void dwarf2_read_abbrevs (struct dwarf2_cu *cu);
static void dwarf2_free_abbrev_table (void *);
+static unsigned int peek_abbrev_code (bfd *, gdb_byte *);
+
static struct abbrev_info *peek_die_abbrev (gdb_byte *, unsigned int *,
struct dwarf2_cu *);
static void read_lexical_block_scope (struct die_info *, struct dwarf2_cu *);
+static void read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu);
+
static int dwarf2_ranges_read (unsigned, CORE_ADDR *, CORE_ADDR *,
struct dwarf2_cu *, struct partial_symtab *);
struct dwarf2_section_info *section,
unsigned int offset);
-static void read_signatured_type_at_offset (struct objfile *objfile,
- struct dwarf2_section_info *sect,
- unsigned int offset);
+static void load_full_type_unit (struct dwarf2_per_cu_data *per_cu);
-static void read_signatured_type (struct objfile *,
- struct signatured_type *type_sig);
+static void read_signatured_type (struct signatured_type *type_sig);
/* memory allocation interface */
static struct die_info *dwarf_alloc_die (struct dwarf2_cu *, int);
-static void initialize_cu_func_list (struct dwarf2_cu *);
-
-static void add_to_cu_func_list (const char *, CORE_ADDR, CORE_ADDR,
- struct dwarf2_cu *);
-
static void dwarf_decode_macros (struct line_header *, unsigned int,
char *, bfd *, struct dwarf2_cu *,
struct dwarf2_section_info *,
(unsigned int offset, struct objfile *objfile);
static void init_one_comp_unit (struct dwarf2_cu *cu,
- struct objfile *objfile);
+ struct dwarf2_per_cu_data *per_cu);
static void prepare_one_comp_unit (struct dwarf2_cu *cu,
struct die_info *comp_unit_die);
-static void free_one_comp_unit (void *);
+static void free_heap_comp_unit (void *);
static void free_cached_comp_units (void *);
static int create_debug_types_hash_table (struct objfile *objfile);
-static void load_full_comp_unit (struct dwarf2_per_cu_data *,
- struct objfile *);
+static void load_full_comp_unit (struct dwarf2_per_cu_data *);
static void process_full_comp_unit (struct dwarf2_per_cu_data *);
static void dwarf2_release_queue (void *dummy);
-static void queue_comp_unit (struct dwarf2_per_cu_data *per_cu,
- struct objfile *objfile);
+static void queue_comp_unit (struct dwarf2_per_cu_data *per_cu);
-static void process_queue (struct objfile *objfile);
+static void process_queue (void);
static void find_file_and_directory (struct die_info *die,
struct dwarf2_cu *cu,
gdb_byte *info_ptr,
gdb_byte *buffer,
unsigned int buffer_size,
- bfd *abfd);
+ bfd *abfd,
+ int is_debug_types_section);
static void init_cu_die_reader (struct die_reader_specs *reader,
struct dwarf2_cu *cu);
return info->asection == NULL || info->size == 0;
}
-/* Read the contents of the section SECTP from object file specified by
+/* Read the contents of the section INFO from object file specified by
OBJFILE, store info about the section into INFO.
If the section is compressed, uncompress it before returning. */
static void
load_cu (struct dwarf2_per_cu_data *per_cu)
{
- if (per_cu->debug_type_section)
- read_signatured_type_at_offset (per_cu->objfile,
- per_cu->debug_type_section,
- per_cu->offset);
+ if (per_cu->debug_types_section)
+ load_full_type_unit (per_cu);
else
- load_full_comp_unit (per_cu, per_cu->objfile);
-
- dwarf2_find_base_address (per_cu->cu->dies, per_cu->cu);
+ load_full_comp_unit (per_cu);
gdb_assert (per_cu->cu != NULL);
+
+ dwarf2_find_base_address (per_cu->cu->dies, per_cu->cu);
}
-/* Read in the symbols for PER_CU. OBJFILE is the objfile from which
- this CU came. */
+/* Read in the symbols for PER_CU. */
static void
-dw2_do_instantiate_symtab (struct objfile *objfile,
- struct dwarf2_per_cu_data *per_cu)
+dw2_do_instantiate_symtab (struct dwarf2_per_cu_data *per_cu)
{
struct cleanup *back_to;
back_to = make_cleanup (dwarf2_release_queue, NULL);
- queue_comp_unit (per_cu, objfile);
+ queue_comp_unit (per_cu);
load_cu (per_cu);
- process_queue (objfile);
+ process_queue ();
/* Age the cache, releasing compilation units that have not
been used recently. */
table. */
static struct symtab *
-dw2_instantiate_symtab (struct objfile *objfile,
- struct dwarf2_per_cu_data *per_cu)
+dw2_instantiate_symtab (struct dwarf2_per_cu_data *per_cu)
{
if (!per_cu->v.quick->symtab)
{
struct cleanup *back_to = make_cleanup (free_cached_comp_units, NULL);
increment_reading_symtab ();
- dw2_do_instantiate_symtab (objfile, per_cu);
+ dw2_do_instantiate_symtab (per_cu);
do_cleanups (back_to);
}
return per_cu->v.quick->symtab;
struct signatured_type);
type_sig->signature = signature;
type_sig->type_offset = type_offset;
- type_sig->per_cu.debug_type_section = section;
+ type_sig->per_cu.debug_types_section = section;
type_sig->per_cu.offset = offset;
type_sig->per_cu.objfile = objfile;
type_sig->per_cu.v.quick
struct cleanup *cleanups;
struct die_info *comp_unit_die;
struct dwarf2_section_info* sec;
- gdb_byte *beg_of_comp_unit, *info_ptr, *buffer;
+ gdb_byte *info_ptr, *buffer;
int has_children, i;
struct dwarf2_cu cu;
unsigned int bytes_read, buffer_size;
if (this_cu->v.quick->no_file_data)
return NULL;
- init_one_comp_unit (&cu, objfile);
+ init_one_comp_unit (&cu, this_cu);
cleanups = make_cleanup (free_stack_comp_unit, &cu);
- if (this_cu->debug_type_section)
- sec = this_cu->debug_type_section;
+ if (this_cu->debug_types_section)
+ sec = this_cu->debug_types_section;
else
sec = &dwarf2_per_objfile->info;
dwarf2_read_section (objfile, sec);
buffer_size = sec->size;
buffer = sec->buffer;
info_ptr = buffer + this_cu->offset;
- beg_of_comp_unit = info_ptr;
info_ptr = partial_read_comp_unit_head (&cu.header, info_ptr,
buffer, buffer_size,
- abfd);
+ abfd,
+ this_cu->debug_types_section != NULL);
- /* Complete the cu_header. */
- cu.header.offset = beg_of_comp_unit - buffer;
- cu.header.first_die_offset = info_ptr - beg_of_comp_unit;
-
- this_cu->cu = &cu;
- cu.per_cu = this_cu;
+ /* Skip dummy compilation units. */
+ if (info_ptr >= buffer + buffer_size
+ || peek_abbrev_code (abfd, info_ptr) == 0)
+ {
+ do_cleanups (cleanups);
+ return NULL;
+ }
- dwarf2_read_abbrevs (abfd, &cu);
+ dwarf2_read_abbrevs (&cu);
make_cleanup (dwarf2_free_abbrev_table, &cu);
- if (this_cu->debug_type_section)
- info_ptr += 8 /*signature*/ + cu.header.offset_size;
init_cu_die_reader (&reader_specs, &cu);
read_full_die (&reader_specs, &comp_unit_die, info_ptr,
&has_children);
dw2_setup (objfile);
index = dwarf2_per_objfile->n_comp_units - 1;
- return dw2_instantiate_symtab (objfile, dw2_get_cu (index));
+ return dw2_instantiate_symtab (dw2_get_cu (index));
}
/* Traversal function for dw2_forget_cached_source_info. */
dw2_free_cached_file_names, NULL);
}
+/* Helper function for dw2_map_symtabs_matching_filename that expands
+ the symtabs and calls the iterator. */
+
static int
-dw2_lookup_symtab (struct objfile *objfile, const char *name,
- const char *full_path, const char *real_path,
- struct symtab **result)
+dw2_map_expand_apply (struct objfile *objfile,
+ struct dwarf2_per_cu_data *per_cu,
+ const char *name,
+ const char *full_path, const char *real_path,
+ int (*callback) (struct symtab *, void *),
+ void *data)
+{
+ struct symtab *last_made = objfile->symtabs;
+
+ /* Don't visit already-expanded CUs. */
+ if (per_cu->v.quick->symtab)
+ return 0;
+
+ /* This may expand more than one symtab, and we want to iterate over
+ all of them. */
+ dw2_instantiate_symtab (per_cu);
+
+ return iterate_over_some_symtabs (name, full_path, real_path, callback, data,
+ objfile->symtabs, last_made);
+}
+
+/* Implementation of the map_symtabs_matching_filename method. */
+
+static int
+dw2_map_symtabs_matching_filename (struct objfile *objfile, const char *name,
+ const char *full_path, const char *real_path,
+ int (*callback) (struct symtab *, void *),
+ void *data)
{
int i;
- int check_basename = lbasename (name) == name;
+ const char *name_basename = lbasename (name);
+ int check_basename = name_basename == name;
struct dwarf2_per_cu_data *base_cu = NULL;
dw2_setup (objfile);
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)
continue;
if (FILENAME_CMP (name, this_name) == 0)
{
- *result = dw2_instantiate_symtab (objfile, per_cu);
- return 1;
+ if (dw2_map_expand_apply (objfile, per_cu,
+ name, full_path, real_path,
+ callback, data))
+ return 1;
}
if (check_basename && ! base_cu
&& FILENAME_CMP (lbasename (this_name), name) == 0)
base_cu = per_cu;
+ /* Before we invoke realpath, which can get expensive when many
+ files are involved, do a quick comparison of the basenames. */
+ if (! basenames_may_differ
+ && FILENAME_CMP (lbasename (this_name), name_basename) != 0)
+ continue;
+
if (full_path != NULL)
{
const char *this_real_name = dw2_get_real_path (objfile,
if (this_real_name != NULL
&& FILENAME_CMP (full_path, this_real_name) == 0)
{
- *result = dw2_instantiate_symtab (objfile, per_cu);
- return 1;
+ if (dw2_map_expand_apply (objfile, per_cu,
+ name, full_path, real_path,
+ callback, data))
+ return 1;
}
}
if (this_real_name != NULL
&& FILENAME_CMP (real_path, this_real_name) == 0)
{
- *result = dw2_instantiate_symtab (objfile, per_cu);
- return 1;
+ if (dw2_map_expand_apply (objfile, per_cu,
+ name, full_path, real_path,
+ callback, data))
+ return 1;
}
}
}
if (base_cu)
{
- *result = dw2_instantiate_symtab (objfile, base_cu);
- return 1;
+ if (dw2_map_expand_apply (objfile, base_cu,
+ name, full_path, real_path,
+ callback, data))
+ return 1;
}
return 0;
offset_type cu_index = MAYBE_SWAP (vec[i + 1]);
struct dwarf2_per_cu_data *per_cu = dw2_get_cu (cu_index);
- dw2_instantiate_symtab (objfile, per_cu);
+ dw2_instantiate_symtab (per_cu);
}
}
}
{
struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
- dw2_instantiate_symtab (objfile, per_cu);
+ dw2_instantiate_symtab (per_cu);
}
}
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)
continue;
const char *this_name = file_data->file_names[j];
if (FILENAME_CMP (this_name, filename) == 0)
{
- dw2_instantiate_symtab (objfile, per_cu);
+ dw2_instantiate_symtab (per_cu);
break;
}
}
/* index_table is NULL if OBJF_READNOW. */
if (!dwarf2_per_objfile->index_table)
- return NULL;
+ {
+ struct symtab *s;
+
+ ALL_OBJFILE_SYMTABS (objfile, s)
+ if (s->primary)
+ {
+ struct blockvector *bv = BLOCKVECTOR (s);
+ const struct block *block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
+ struct symbol *sym = lookup_block_symbol (block, name, VAR_DOMAIN);
+
+ if (sym)
+ return sym->symtab->filename;
+ }
+ return NULL;
+ }
if (!find_slot_in_mapped_hash (dwarf2_per_objfile->index_table,
name, &vec))
}
static void
-dw2_expand_symtabs_matching (struct objfile *objfile,
- int (*file_matcher) (const char *, void *),
- int (*name_matcher) (const char *, void *),
- enum search_domain kind,
- void *data)
+dw2_expand_symtabs_matching
+ (struct objfile *objfile,
+ int (*file_matcher) (const char *, void *),
+ int (*name_matcher) (const struct language_defn *, const char *, void *),
+ enum search_domain kind,
+ void *data)
{
int i;
offset_type iter;
struct quick_file_names *file_data;
per_cu->v.quick->mark = 0;
+
+ /* We only need to look at symtabs not already expanded. */
if (per_cu->v.quick->symtab)
continue;
name = index->constant_pool + MAYBE_SWAP (index->symbol_table[idx]);
- if (! (*name_matcher) (name, data))
+ if (! (*name_matcher) (current_language, name, data))
continue;
/* The name was matched, now expand corresponding CUs that were
per_cu = dw2_get_cu (MAYBE_SWAP (vec[vec_idx + 1]));
if (file_matcher == NULL || per_cu->v.quick->mark)
- dw2_instantiate_symtab (objfile, per_cu);
+ dw2_instantiate_symtab (per_cu);
}
}
}
warning (_("(Internal error: pc %s in read in CU, but not in symtab.)"),
paddress (get_objfile_arch (objfile), pc));
- return dw2_instantiate_symtab (objfile, data);
+ return dw2_instantiate_symtab (data);
}
static void
dw2_map_symbol_filenames (struct objfile *objfile, symbol_filename_ftype *fun,
- void *data)
+ void *data, int need_fullname)
{
int 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)
continue;
for (j = 0; j < file_data->num_file_names; ++j)
{
- const char *this_real_name = dw2_get_real_path (objfile, file_data,
- j);
+ const char *this_real_name;
+
+ if (need_fullname)
+ this_real_name = dw2_get_real_path (objfile, file_data, j);
+ else
+ this_real_name = NULL;
(*fun) (file_data->file_names[j], this_real_name, data);
}
}
dw2_has_symbols,
dw2_find_last_source_symtab,
dw2_forget_cached_source_info,
- dw2_lookup_symtab,
+ dw2_map_symtabs_matching_filename,
dw2_lookup_symbol,
dw2_pre_expand_symtabs_matching,
dw2_print_stats,
return info_ptr;
}
+/* Read in a CU header and perform some basic error checking. */
+
static gdb_byte *
partial_read_comp_unit_head (struct comp_unit_head *header, gdb_byte *info_ptr,
gdb_byte *buffer, unsigned int buffer_size,
- bfd *abfd)
+ bfd *abfd, int is_debug_types_section)
{
gdb_byte *beg_of_comp_unit = info_ptr;
+ header->offset = beg_of_comp_unit - buffer;
+
info_ptr = read_comp_unit_head (header, info_ptr, abfd);
+ /* If we're reading a type unit, skip over the signature and
+ type_offset fields. */
+ if (is_debug_types_section)
+ info_ptr += 8 /*signature*/ + header->offset_size;
+
+ header->first_die_offset = info_ptr - beg_of_comp_unit;
+
if (header->version != 2 && header->version != 3 && header->version != 4)
error (_("Dwarf Error: wrong version in compilation unit header "
"(is %d, should be 2, 3, or 4) [in module %s]"), header->version,
signature = bfd_get_64 (objfile->obfd, ptr);
ptr += 8;
type_offset = read_offset_1 (objfile->obfd, ptr, offset_size);
+ ptr += offset_size;
+
+ /* Skip dummy type units. */
+ if (ptr >= end_ptr || peek_abbrev_code (objfile->obfd, ptr) == 0)
+ {
+ info_ptr = info_ptr + initial_length_size + length;
+ continue;
+ }
type_sig = obstack_alloc (&objfile->objfile_obstack, sizeof (*type_sig));
memset (type_sig, 0, sizeof (*type_sig));
type_sig->signature = signature;
type_sig->type_offset = type_offset;
type_sig->per_cu.objfile = objfile;
- type_sig->per_cu.debug_type_section = section;
+ type_sig->per_cu.debug_types_section = section;
type_sig->per_cu.offset = offset;
slot = htab_find_slot (types_htab, type_sig, INSERT);
{
reader->abfd = cu->objfile->obfd;
reader->cu = cu;
- if (cu->per_cu->debug_type_section)
+ if (cu->per_cu->debug_types_section)
{
- gdb_assert (cu->per_cu->debug_type_section->readin);
- reader->buffer = cu->per_cu->debug_type_section->buffer;
+ gdb_assert (cu->per_cu->debug_types_section->readin);
+ reader->buffer = cu->per_cu->debug_types_section->buffer;
}
else
{
Returns a pointer to the next CU. */
static gdb_byte *
-process_psymtab_comp_unit (struct objfile *objfile,
- struct dwarf2_per_cu_data *this_cu,
+process_psymtab_comp_unit (struct dwarf2_per_cu_data *this_cu,
gdb_byte *buffer, gdb_byte *info_ptr,
unsigned int buffer_size)
{
+ struct objfile *objfile = this_cu->objfile;
bfd *abfd = objfile->obfd;
gdb_byte *beg_of_comp_unit = info_ptr;
struct die_info *comp_unit_die;
struct die_reader_specs reader_specs;
const char *filename;
- init_one_comp_unit (&cu, objfile);
- back_to_inner = make_cleanup (free_stack_comp_unit, &cu);
-
- info_ptr = partial_read_comp_unit_head (&cu.header, info_ptr,
- buffer, buffer_size,
- abfd);
-
- /* Complete the cu_header. */
- cu.header.offset = beg_of_comp_unit - buffer;
- cu.header.first_die_offset = info_ptr - beg_of_comp_unit;
-
- cu.list_in_scope = &file_symbols;
-
/* If this compilation unit was already read in, free the
cached copy in order to read it in again. This is
necessary because we skipped some symbols when we first
added to a global data structure. It will be cleaned up
in free_stack_comp_unit when we finish with this
compilation unit. */
- this_cu->cu = &cu;
- cu.per_cu = this_cu;
+ init_one_comp_unit (&cu, this_cu);
+ back_to_inner = make_cleanup (free_stack_comp_unit, &cu);
+
+ info_ptr = partial_read_comp_unit_head (&cu.header, info_ptr,
+ buffer, buffer_size,
+ abfd,
+ this_cu->debug_types_section != NULL);
+
+ /* Skip dummy compilation units. */
+ if (info_ptr >= buffer + buffer_size
+ || peek_abbrev_code (abfd, info_ptr) == 0)
+ {
+ info_ptr = (beg_of_comp_unit + cu.header.length
+ + cu.header.initial_length_size);
+ do_cleanups (back_to_inner);
+ return info_ptr;
+ }
+
+ cu.list_in_scope = &file_symbols;
/* Read the abbrevs for this compilation unit into a table. */
- dwarf2_read_abbrevs (abfd, &cu);
+ dwarf2_read_abbrevs (&cu);
make_cleanup (dwarf2_free_abbrev_table, &cu);
/* Read the compilation unit die. */
- if (this_cu->debug_type_section)
- info_ptr += 8 /*signature*/ + cu.header.offset_size;
init_cu_die_reader (&reader_specs, &cu);
info_ptr = read_full_die (&reader_specs, &comp_unit_die, info_ptr,
&has_children);
- if (this_cu->debug_type_section)
+ if (this_cu->debug_types_section)
{
/* LENGTH has not been set yet for type units. */
gdb_assert (this_cu->offset == cu.header.offset);
0,
objfile->global_psymbols.next,
objfile->static_psymbols.next);
+ pst->psymtabs_addrmap_supported = 1;
attr = dwarf2_attr (comp_unit_die, DW_AT_comp_dir, &cu);
if (attr != NULL)
info_ptr = (beg_of_comp_unit + cu.header.length
+ cu.header.initial_length_size);
- if (this_cu->debug_type_section)
+ if (this_cu->debug_types_section)
{
/* It's not clear we want to do anything with stmt lists here.
Waiting to see what gcc ultimately does. */
process_type_comp_unit (void **slot, void *info)
{
struct signatured_type *entry = (struct signatured_type *) *slot;
- struct objfile *objfile = (struct objfile *) info;
struct dwarf2_per_cu_data *this_cu;
+ gdb_assert (info == NULL);
this_cu = &entry->per_cu;
- gdb_assert (this_cu->debug_type_section->readin);
- process_psymtab_comp_unit (objfile, this_cu,
- this_cu->debug_type_section->buffer,
- (this_cu->debug_type_section->buffer
+ gdb_assert (this_cu->debug_types_section->readin);
+ process_psymtab_comp_unit (this_cu,
+ this_cu->debug_types_section->buffer,
+ (this_cu->debug_types_section->buffer
+ this_cu->offset),
- this_cu->debug_type_section->size);
+ this_cu->debug_types_section->size);
return 1;
}
return;
htab_traverse_noresize (dwarf2_per_objfile->signatured_types,
- process_type_comp_unit, objfile);
+ process_type_comp_unit, NULL);
}
/* A cleanup function that clears objfile's psymtabs_addrmap field. */
- dwarf2_per_objfile->info.buffer,
objfile);
- info_ptr = process_psymtab_comp_unit (objfile, this_cu,
+ info_ptr = process_psymtab_comp_unit (this_cu,
dwarf2_per_objfile->info.buffer,
info_ptr,
dwarf2_per_objfile->info.size);
/* Load the partial DIEs for a secondary CU into memory. */
static void
-load_partial_comp_unit (struct dwarf2_per_cu_data *this_cu,
- struct objfile *objfile)
+load_partial_comp_unit (struct dwarf2_per_cu_data *this_cu)
{
+ struct objfile *objfile = this_cu->objfile;
bfd *abfd = objfile->obfd;
- gdb_byte *info_ptr, *beg_of_comp_unit;
+ gdb_byte *info_ptr;
struct die_info *comp_unit_die;
struct dwarf2_cu *cu;
struct cleanup *free_abbrevs_cleanup, *free_cu_cleanup = NULL;
struct die_reader_specs reader_specs;
int read_cu = 0;
- gdb_assert (! this_cu->debug_type_section);
+ gdb_assert (! this_cu->debug_types_section);
gdb_assert (dwarf2_per_objfile->info.readin);
info_ptr = dwarf2_per_objfile->info.buffer + this_cu->offset;
- beg_of_comp_unit = info_ptr;
if (this_cu->cu == NULL)
{
cu = xmalloc (sizeof (*cu));
- init_one_comp_unit (cu, objfile);
+ init_one_comp_unit (cu, this_cu);
read_cu = 1;
/* If an error occurs while loading, release our storage. */
- free_cu_cleanup = make_cleanup (free_one_comp_unit, cu);
+ free_cu_cleanup = make_cleanup (free_heap_comp_unit, cu);
info_ptr = partial_read_comp_unit_head (&cu->header, info_ptr,
dwarf2_per_objfile->info.buffer,
dwarf2_per_objfile->info.size,
- abfd);
-
- /* Complete the cu_header. */
- cu->header.offset = this_cu->offset;
- cu->header.first_die_offset = info_ptr - beg_of_comp_unit;
+ abfd, 0);
- /* Link this compilation unit into the compilation unit tree. */
- this_cu->cu = cu;
- cu->per_cu = this_cu;
+ /* Skip dummy compilation units. */
+ if (info_ptr >= (dwarf2_per_objfile->info.buffer
+ + dwarf2_per_objfile->info.size)
+ || peek_abbrev_code (abfd, info_ptr) == 0)
+ {
+ do_cleanups (free_cu_cleanup);
+ return;
+ }
/* Link this CU into read_in_chain. */
this_cu->cu->read_in_chain = dwarf2_per_objfile->read_in_chain;
/* Read the abbrevs for this compilation unit into a table. */
gdb_assert (cu->dwarf2_abbrevs == NULL);
- dwarf2_read_abbrevs (abfd, cu);
+ dwarf2_read_abbrevs (cu);
free_abbrevs_cleanup = make_cleanup (dwarf2_free_abbrev_table, cu);
/* Read the compilation unit die. */
}
}
-/* Create a list of all compilation units in OBJFILE. We do this only
- if an inter-comp-unit reference is found; presumably if there is one,
- there will be many, and one will occur early in the .debug_info section.
- So there's no point in building this list incrementally. */
+/* Create a list of all compilation units in OBJFILE.
+ This is only done for -readnow and building partial symtabs. */
static void
create_all_comp_units (struct objfile *objfile)
return NULL;
}
- if (parent->tag == DW_TAG_namespace
+ if (pdi->tag == DW_TAG_enumerator)
+ /* Enumerators should not get the name of the enumeration as a prefix. */
+ parent->scope = grandparent_scope;
+ else if (parent->tag == DW_TAG_namespace
|| parent->tag == DW_TAG_module
|| parent->tag == DW_TAG_structure_type
|| parent->tag == DW_TAG_class_type
grandparent_scope,
parent->name, 0, cu);
}
- else if (parent->tag == DW_TAG_enumerator)
- /* Enumerators should not get the name of the enumeration as a prefix. */
- parent->scope = grandparent_scope;
else
{
/* FIXME drow/2004-04-01: What should we be doing with
}
}
+/* Return the initial uleb128 in the die at INFO_PTR. */
+
+static unsigned int
+peek_abbrev_code (bfd *abfd, gdb_byte *info_ptr)
+{
+ unsigned int bytes_read;
+
+ return read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
+}
+
/* Read the initial uleb128 in the die at INFO_PTR in compilation unit CU.
Return the corresponding abbrev, or NULL if the number is zero (indicating
an empty DIE). In either case *BYTES_READ will be set to the length of
}
}
}
+\f
+/* Reading in full CUs. */
/* Add PER_CU to the queue. */
static void
-queue_comp_unit (struct dwarf2_per_cu_data *per_cu, struct objfile *objfile)
+queue_comp_unit (struct dwarf2_per_cu_data *per_cu)
{
struct dwarf2_queue_item *item;
/* Process the queue. */
static void
-process_queue (struct objfile *objfile)
+process_queue (void)
{
struct dwarf2_queue_item *item, *next_item;
return;
}
- dw2_do_instantiate_symtab (pst->objfile, per_cu);
+ dw2_do_instantiate_symtab (per_cu);
}
/* Load the DIEs associated with PER_CU into memory. */
static void
-load_full_comp_unit (struct dwarf2_per_cu_data *per_cu,
- struct objfile *objfile)
+load_full_comp_unit (struct dwarf2_per_cu_data *per_cu)
{
+ struct objfile *objfile = per_cu->objfile;
bfd *abfd = objfile->obfd;
struct dwarf2_cu *cu;
unsigned int offset;
struct attribute *attr;
int read_cu = 0;
- gdb_assert (! per_cu->debug_type_section);
+ gdb_assert (! per_cu->debug_types_section);
/* Set local variables from the partial symbol table info. */
offset = per_cu->offset;
if (per_cu->cu == NULL)
{
cu = xmalloc (sizeof (*cu));
- init_one_comp_unit (cu, objfile);
+ init_one_comp_unit (cu, per_cu);
read_cu = 1;
/* If an error occurs while loading, release our storage. */
- free_cu_cleanup = make_cleanup (free_one_comp_unit, cu);
+ free_cu_cleanup = make_cleanup (free_heap_comp_unit, cu);
/* Read in the comp_unit header. */
info_ptr = read_comp_unit_head (&cu->header, info_ptr, abfd);
+ /* Skip dummy compilation units. */
+ if (info_ptr >= (dwarf2_per_objfile->info.buffer
+ + dwarf2_per_objfile->info.size)
+ || peek_abbrev_code (abfd, info_ptr) == 0)
+ {
+ do_cleanups (free_cu_cleanup);
+ return;
+ }
+
/* Complete the cu_header. */
cu->header.offset = offset;
cu->header.first_die_offset = info_ptr - beg_of_comp_unit;
/* Read the abbrevs for this compilation unit. */
- dwarf2_read_abbrevs (abfd, cu);
+ dwarf2_read_abbrevs (cu);
free_abbrevs_cleanup = make_cleanup (dwarf2_free_abbrev_table, cu);
- /* Link this compilation unit into the compilation unit tree. */
- per_cu->cu = cu;
- cu->per_cu = per_cu;
-
/* Link this CU into read_in_chain. */
per_cu->cu->read_in_chain = dwarf2_per_objfile->read_in_chain;
dwarf2_per_objfile->read_in_chain = per_cu;
cu->dies = read_comp_unit (info_ptr, cu);
/* We try not to read any attributes in this function, because not
- all objfiles needed for references have been loaded yet, and symbol
+ all CUs needed for references have been loaded yet, and symbol
table processing isn't initialized. But we have to set the CU language,
or we won't be able to build types correctly. */
prepare_one_comp_unit (cu, cu->dies);
}
}
-/* Check for GCC >= 4.x. Return minor version (x) of 4.x in such case. If it
- is not GCC or it is GCC older than 4.x return -1. If it is GCC 5.x or
- higher return INT_MAX. */
-
-static int
-producer_is_gcc_ge_4 (struct dwarf2_cu *cu)
-{
- const char *cs;
- int major, minor;
-
- if (cu->producer == NULL)
- {
- /* For unknown compilers expect their behavior is not compliant. For GCC
- this case can also happen for -gdwarf-4 type units supported since
- gcc-4.5. */
-
- return -1;
- }
-
- /* Skip any identifier after "GNU " - such as "C++" or "Java". */
-
- if (strncmp (cu->producer, "GNU ", strlen ("GNU ")) != 0)
- {
- /* For non-GCC compilers expect their behavior is not compliant. */
-
- return -1;
- }
- cs = &cu->producer[strlen ("GNU ")];
- while (*cs && !isdigit (*cs))
- cs++;
- if (sscanf (cs, "%d.%d", &major, &minor) != 2)
- {
- /* Not recognized as GCC. */
-
- return -1;
- }
-
- if (major < 4)
- return -1;
- if (major > 4)
- return INT_MAX;
- return minor;
-}
-
-/* Generate full symbol information for PST and CU, whose DIEs have
+/* Generate full symbol information for PER_CU, whose DIEs have
already been loaded into memory. */
static void
if (symtab != NULL)
{
- int gcc_4_minor = producer_is_gcc_ge_4 (cu);
+ 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
if (gcc_4_minor >= 5)
symtab->epilogue_unwind_valid = 1;
+
+ symtab->call_site_htab = cu->call_site_htab;
}
if (dwarf2_per_objfile->using_index)
case DW_TAG_catch_block:
read_lexical_block_scope (die, cu);
break;
+ case DW_TAG_GNU_call_site:
+ read_call_site_scope (die, cu);
+ break;
case DW_TAG_class_type:
case DW_TAG_interface_type:
case DW_TAG_structure_type:
dwarf2_compute_name (char *name, struct die_info *die, struct dwarf2_cu *cu,
int physname)
{
+ struct objfile *objfile = cu->objfile;
+
if (name == NULL)
name = dwarf2_name (die, cu);
}
}
- name = ui_file_obsavestring (buf, &cu->objfile->objfile_obstack,
+ name = ui_file_obsavestring (buf, &objfile->objfile_obstack,
&length);
ui_file_delete (buf);
{
char *cname
= dwarf2_canonicalize_name (name, cu,
- &cu->objfile->objfile_obstack);
+ &objfile->objfile_obstack);
if (cname != NULL)
name = cname;
static const char *
dwarf2_physname (char *name, struct die_info *die, struct dwarf2_cu *cu)
{
+ struct objfile *objfile = cu->objfile;
struct attribute *attr;
const char *retval, *mangled = NULL, *canon = NULL;
struct cleanup *back_to;
complaint (&symfile_complaints,
_("Computed physname <%s> does not match demangled <%s> "
"(from linkage <%s>) - DIE at 0x%x [in module %s]"),
- physname, canon, mangled, die->offset, cu->objfile->name);
+ physname, canon, mangled, die->offset, objfile->name);
/* Prefer DW_AT_linkage_name (in the CANON form) - when it
is available here - over computed PHYSNAME. It is safer
if (need_copy)
retval = obsavestring (retval, strlen (retval),
- &cu->objfile->objfile_obstack);
+ &objfile->objfile_obstack);
do_cleanups (back_to);
return retval;
static void
read_import_statement (struct die_info *die, struct dwarf2_cu *cu)
{
+ struct objfile *objfile = cu->objfile;
struct attribute *import_attr;
struct die_info *imported_die, *child_die;
struct dwarf2_cu *imported_cu;
complaint (&symfile_complaints,
_("child DW_TAG_imported_declaration expected "
"- DIE at 0x%x [in module %s]"),
- child_die->offset, cu->objfile->name);
+ child_die->offset, objfile->name);
continue;
}
complaint (&symfile_complaints,
_("child DW_TAG_imported_declaration has unknown "
"imported name - DIE at 0x%x [in module %s]"),
- child_die->offset, cu->objfile->name);
+ child_die->offset, objfile->name);
continue;
}
import_alias,
imported_declaration,
excludes,
- &cu->objfile->objfile_obstack);
+ &objfile->objfile_obstack);
do_cleanups (cleanups);
}
-static void
-initialize_cu_func_list (struct dwarf2_cu *cu)
-{
- cu->first_fn = cu->last_fn = cu->cached_fn = NULL;
-}
-
/* Cleanup function for read_file_scope. */
static void
record_debugformat ("DWARF 2");
record_producer (cu->producer);
- initialize_cu_func_list (cu);
-
handle_DW_AT_stmt_list (die, cu, comp_dir);
/* Process all dies in compilation unit. */
&dwarf2_per_objfile->macinfo, 0);
}
}
+
do_cleanups (back_to);
}
do_cleanups (back_to);
}
-static void
-add_to_cu_func_list (const char *name, CORE_ADDR lowpc, CORE_ADDR highpc,
- struct dwarf2_cu *cu)
-{
- struct function_range *thisfn;
-
- thisfn = (struct function_range *)
- obstack_alloc (&cu->comp_unit_obstack, sizeof (struct function_range));
- thisfn->name = name;
- thisfn->lowpc = lowpc;
- thisfn->highpc = highpc;
- thisfn->seen_line = 0;
- thisfn->next = NULL;
-
- if (cu->last_fn == NULL)
- cu->first_fn = thisfn;
- else
- cu->last_fn->next = thisfn;
-
- cu->last_fn = thisfn;
-}
-
/* qsort helper for inherit_abstract_dies. */
static int
lowpc += baseaddr;
highpc += baseaddr;
- /* Record the function range for dwarf_decode_lines. */
- add_to_cu_func_list (name, lowpc, highpc, cu);
-
/* If we have any template arguments, then we must allocate a
different sort of symbol. */
for (child_die = die->child; child_die; child_die = sibling_die (child_die))
using_directives = new->using_directives;
}
+/* Read in DW_TAG_GNU_call_site and insert it to CU->call_site_htab. */
+
+static void
+read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
+{
+ struct objfile *objfile = cu->objfile;
+ struct gdbarch *gdbarch = get_objfile_arch (objfile);
+ CORE_ADDR pc, baseaddr;
+ struct attribute *attr;
+ struct call_site *call_site, call_site_local;
+ void **slot;
+ int nparams;
+ struct die_info *child_die;
+
+ baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
+
+ attr = dwarf2_attr (die, DW_AT_low_pc, cu);
+ if (!attr)
+ {
+ complaint (&symfile_complaints,
+ _("missing DW_AT_low_pc for DW_TAG_GNU_call_site "
+ "DIE 0x%x [in module %s]"),
+ die->offset, objfile->name);
+ return;
+ }
+ pc = DW_ADDR (attr) + baseaddr;
+
+ if (cu->call_site_htab == NULL)
+ cu->call_site_htab = htab_create_alloc_ex (16, core_addr_hash, core_addr_eq,
+ NULL, &objfile->objfile_obstack,
+ hashtab_obstack_allocate, NULL);
+ call_site_local.pc = pc;
+ slot = htab_find_slot (cu->call_site_htab, &call_site_local, INSERT);
+ if (*slot != NULL)
+ {
+ complaint (&symfile_complaints,
+ _("Duplicate PC %s for DW_TAG_GNU_call_site "
+ "DIE 0x%x [in module %s]"),
+ paddress (gdbarch, pc), die->offset, objfile->name);
+ return;
+ }
+
+ /* Count parameters at the caller. */
+
+ nparams = 0;
+ for (child_die = die->child; child_die && child_die->tag;
+ child_die = sibling_die (child_die))
+ {
+ if (child_die->tag != DW_TAG_GNU_call_site_parameter)
+ {
+ complaint (&symfile_complaints,
+ _("Tag %d is not DW_TAG_GNU_call_site_parameter in "
+ "DW_TAG_GNU_call_site child DIE 0x%x [in module %s]"),
+ child_die->tag, child_die->offset, objfile->name);
+ continue;
+ }
+
+ nparams++;
+ }
+
+ call_site = obstack_alloc (&objfile->objfile_obstack,
+ (sizeof (*call_site)
+ + (sizeof (*call_site->parameter)
+ * (nparams - 1))));
+ *slot = call_site;
+ memset (call_site, 0, sizeof (*call_site) - sizeof (*call_site->parameter));
+ call_site->pc = pc;
+
+ if (dwarf2_flag_true_p (die, DW_AT_GNU_tail_call, cu))
+ {
+ struct die_info *func_die;
+
+ /* Skip also over DW_TAG_inlined_subroutine. */
+ for (func_die = die->parent;
+ func_die && func_die->tag != DW_TAG_subprogram
+ && func_die->tag != DW_TAG_subroutine_type;
+ func_die = func_die->parent);
+
+ /* DW_AT_GNU_all_call_sites is a superset
+ of DW_AT_GNU_all_tail_call_sites. */
+ if (func_die
+ && !dwarf2_flag_true_p (func_die, DW_AT_GNU_all_call_sites, cu)
+ && !dwarf2_flag_true_p (func_die, DW_AT_GNU_all_tail_call_sites, cu))
+ {
+ /* TYPE_TAIL_CALL_LIST is not interesting in functions where it is
+ not complete. But keep CALL_SITE for look ups via call_site_htab,
+ both the initial caller containing the real return address PC and
+ the final callee containing the current PC of a chain of tail
+ calls do not need to have the tail call list complete. But any
+ function candidate for a virtual tail call frame searched via
+ TYPE_TAIL_CALL_LIST must have the tail call list complete to be
+ determined unambiguously. */
+ }
+ else
+ {
+ struct type *func_type = NULL;
+
+ if (func_die)
+ func_type = get_die_type (func_die, cu);
+ if (func_type != NULL)
+ {
+ gdb_assert (TYPE_CODE (func_type) == TYPE_CODE_FUNC);
+
+ /* Enlist this call site to the function. */
+ call_site->tail_call_next = TYPE_TAIL_CALL_LIST (func_type);
+ TYPE_TAIL_CALL_LIST (func_type) = call_site;
+ }
+ else
+ complaint (&symfile_complaints,
+ _("Cannot find function owning DW_TAG_GNU_call_site "
+ "DIE 0x%x [in module %s]"),
+ die->offset, objfile->name);
+ }
+ }
+
+ attr = dwarf2_attr (die, DW_AT_GNU_call_site_target, cu);
+ if (attr == NULL)
+ attr = dwarf2_attr (die, DW_AT_abstract_origin, cu);
+ SET_FIELD_DWARF_BLOCK (call_site->target, NULL);
+ if (!attr || (attr_form_is_block (attr) && DW_BLOCK (attr)->size == 0))
+ /* Keep NULL DWARF_BLOCK. */;
+ else if (attr_form_is_block (attr))
+ {
+ struct dwarf2_locexpr_baton *dlbaton;
+
+ dlbaton = obstack_alloc (&objfile->objfile_obstack, sizeof (*dlbaton));
+ dlbaton->data = DW_BLOCK (attr)->data;
+ dlbaton->size = DW_BLOCK (attr)->size;
+ dlbaton->per_cu = cu->per_cu;
+
+ SET_FIELD_DWARF_BLOCK (call_site->target, dlbaton);
+ }
+ else if (is_ref_attr (attr))
+ {
+ struct dwarf2_cu *target_cu = cu;
+ struct die_info *target_die;
+
+ target_die = follow_die_ref_or_sig (die, attr, &target_cu);
+ gdb_assert (target_cu->objfile == objfile);
+ if (die_is_declaration (target_die, target_cu))
+ {
+ const char *target_physname;
+
+ target_physname = dwarf2_physname (NULL, target_die, target_cu);
+ if (target_physname == NULL)
+ complaint (&symfile_complaints,
+ _("DW_AT_GNU_call_site_target target DIE has invalid "
+ "physname, for referencing DIE 0x%x [in module %s]"),
+ die->offset, objfile->name);
+ else
+ SET_FIELD_PHYSNAME (call_site->target, (char *) target_physname);
+ }
+ else
+ {
+ CORE_ADDR lowpc;
+
+ /* DW_AT_entry_pc should be preferred. */
+ if (!dwarf2_get_pc_bounds (target_die, &lowpc, NULL, target_cu, NULL))
+ complaint (&symfile_complaints,
+ _("DW_AT_GNU_call_site_target target DIE has invalid "
+ "low pc, for referencing DIE 0x%x [in module %s]"),
+ die->offset, objfile->name);
+ else
+ SET_FIELD_PHYSADDR (call_site->target, lowpc + baseaddr);
+ }
+ }
+ else
+ complaint (&symfile_complaints,
+ _("DW_TAG_GNU_call_site DW_AT_GNU_call_site_target is neither "
+ "block nor reference, for DIE 0x%x [in module %s]"),
+ die->offset, objfile->name);
+
+ call_site->per_cu = cu->per_cu;
+
+ for (child_die = die->child;
+ child_die && child_die->tag;
+ child_die = sibling_die (child_die))
+ {
+ struct dwarf2_locexpr_baton *dlbaton;
+ struct call_site_parameter *parameter;
+
+ if (child_die->tag != DW_TAG_GNU_call_site_parameter)
+ {
+ /* Already printed the complaint above. */
+ continue;
+ }
+
+ gdb_assert (call_site->parameter_count < nparams);
+ parameter = &call_site->parameter[call_site->parameter_count];
+
+ /* DW_AT_location specifies the register number. Value of the data
+ assumed for the register is contained in DW_AT_GNU_call_site_value. */
+
+ attr = dwarf2_attr (child_die, DW_AT_location, cu);
+ if (!attr || !attr_form_is_block (attr))
+ {
+ complaint (&symfile_complaints,
+ _("No DW_FORM_block* DW_AT_location for "
+ "DW_TAG_GNU_call_site child DIE 0x%x [in module %s]"),
+ child_die->offset, objfile->name);
+ continue;
+ }
+ parameter->dwarf_reg = dwarf_block_to_dwarf_reg (DW_BLOCK (attr)->data,
+ &DW_BLOCK (attr)->data[DW_BLOCK (attr)->size]);
+ if (parameter->dwarf_reg == -1
+ && !dwarf_block_to_sp_offset (gdbarch, DW_BLOCK (attr)->data,
+ &DW_BLOCK (attr)->data[DW_BLOCK (attr)->size],
+ ¶meter->fb_offset))
+ {
+ complaint (&symfile_complaints,
+ _("Only single DW_OP_reg or DW_OP_fbreg is supported "
+ "for DW_FORM_block* DW_AT_location for "
+ "DW_TAG_GNU_call_site child DIE 0x%x [in module %s]"),
+ child_die->offset, objfile->name);
+ continue;
+ }
+
+ attr = dwarf2_attr (child_die, DW_AT_GNU_call_site_value, cu);
+ if (!attr_form_is_block (attr))
+ {
+ complaint (&symfile_complaints,
+ _("No DW_FORM_block* DW_AT_GNU_call_site_value for "
+ "DW_TAG_GNU_call_site child DIE 0x%x [in module %s]"),
+ child_die->offset, objfile->name);
+ continue;
+ }
+ parameter->value = DW_BLOCK (attr)->data;
+ parameter->value_size = DW_BLOCK (attr)->size;
+
+ /* Parameters are not pre-cleared by memset above. */
+ parameter->data_value = NULL;
+ parameter->data_value_size = 0;
+ call_site->parameter_count++;
+
+ attr = dwarf2_attr (child_die, DW_AT_GNU_call_site_data_value, cu);
+ if (attr)
+ {
+ if (!attr_form_is_block (attr))
+ complaint (&symfile_complaints,
+ _("No DW_FORM_block* DW_AT_GNU_call_site_data_value for "
+ "DW_TAG_GNU_call_site child DIE 0x%x [in module %s]"),
+ child_die->offset, objfile->name);
+ else
+ {
+ parameter->data_value = DW_BLOCK (attr)->data;
+ parameter->data_value_size = DW_BLOCK (attr)->size;
+ }
+ }
+ }
+}
+
/* Get low and high pc attributes from DW_AT_ranges attribute value OFFSET.
Return 1 if the attributes are present and valid, otherwise, return 0.
If RANGES_PST is not NULL we should setup `objfile->psymtabs_addrmap'. */
return 0;
*lowpc = low;
- *highpc = high;
+ if (highpc)
+ *highpc = high;
return ret;
}
dwarf2_record_block_ranges (struct die_info *die, struct block *block,
CORE_ADDR baseaddr, struct dwarf2_cu *cu)
{
+ struct objfile *objfile = cu->objfile;
struct attribute *attr;
attr = dwarf2_attr (die, DW_AT_high_pc, cu);
attr = dwarf2_attr (die, DW_AT_ranges, cu);
if (attr)
{
- bfd *obfd = cu->objfile->obfd;
+ bfd *obfd = objfile->obfd;
/* The value of the DW_AT_ranges attribute is the offset of the
address range list in the .debug_ranges section. */
TYPE_CPLUS_REALLY_JAVA (type) = cu->language == language_java;
}
- quirk_gcc_member_function_pointer (type, cu->objfile);
+ quirk_gcc_member_function_pointer (type, objfile);
/* NOTE: carlton/2004-03-16: GCC 3.4 (or at least one of its
snapshots) has been known to create a die giving a declaration
actually available. Note that we do not want to do this for all
enums which are just declarations, because C++0x allows forward
enum declarations. */
- if (cu->per_cu->debug_type_section
+ if (cu->per_cu->debug_types_section
&& die_is_declaration (die, cu))
{
struct signatured_type *type_sig;
type_sig
= lookup_signatured_type_at_offset (dwarf2_per_objfile->objfile,
- cu->per_cu->debug_type_section,
+ cu->per_cu->debug_types_section,
cu->per_cu->offset);
if (type_sig->type_offset != die->offset)
return;
static struct type *
read_subroutine_type (struct die_info *die, struct dwarf2_cu *cu)
{
+ struct objfile *objfile = cu->objfile;
struct type *type; /* Type that this function returns. */
struct type *ftype; /* Function that returns above type. */
struct attribute *attr;
if (die->child != NULL)
{
- struct type *void_type = objfile_type (cu->objfile)->builtin_void;
+ struct type *void_type = objfile_type (objfile)->builtin_void;
struct die_info *child_die;
int nparams, iparams;
{
struct objfile *objfile = cu->objfile;
const char *name = NULL;
- struct type *this_type;
+ struct type *this_type, *target_type;
name = dwarf2_full_name (NULL, die, cu);
this_type = init_type (TYPE_CODE_TYPEDEF, 0,
TYPE_FLAG_TARGET_STUB, NULL, objfile);
TYPE_NAME (this_type) = (char *) name;
set_die_type (die, this_type, cu);
- TYPE_TARGET_TYPE (this_type) = die_type (die, cu);
+ target_type = die_type (die, cu);
+ if (target_type != this_type)
+ TYPE_TARGET_TYPE (this_type) = target_type;
+ else
+ {
+ /* Self-referential typedefs are, it seems, not allowed by the DWARF
+ spec and cause infinite loops in GDB. */
+ complaint (&symfile_complaints,
+ _("Self-referential DW_TAG_typedef "
+ "- DIE at 0x%x [in module %s]"),
+ die->offset, objfile->name);
+ TYPE_TARGET_TYPE (this_type) = NULL;
+ }
return this_type;
}
if (cu->dwarf2_abbrevs == NULL)
{
- dwarf2_read_abbrevs (cu->objfile->obfd, cu);
+ dwarf2_read_abbrevs (cu);
back_to = make_cleanup (dwarf2_free_abbrev_table, cu);
read_abbrevs = 1;
}
{
fprintf_unfiltered (gdb_stdlog,
"\nRead die from %s of %s:\n",
- (reader->cu->per_cu->debug_type_section
+ (reader->cu->per_cu->debug_types_section
? ".debug_types"
: ".debug_info"),
reader->abfd->filename);
the data found in the abbrev table. */
static void
-dwarf2_read_abbrevs (bfd *abfd, struct dwarf2_cu *cu)
+dwarf2_read_abbrevs (struct dwarf2_cu *cu)
{
+ bfd *abfd = cu->objfile->obfd;
struct comp_unit_head *cu_header = &cu->header;
gdb_byte *abbrev_ptr;
struct abbrev_info *cur_abbrev;
load_partial_dies (bfd *abfd, gdb_byte *buffer, gdb_byte *info_ptr,
int building_psymtab, struct dwarf2_cu *cu)
{
+ struct objfile *objfile = cu->objfile;
struct partial_die_info *part_die;
struct partial_die_info *parent_die, *last_die, *first_die = NULL;
struct abbrev_info *abbrev;
if (building_psymtab && part_die->name != NULL)
add_psymbol_to_list (part_die->name, strlen (part_die->name), 0,
VAR_DOMAIN, LOC_TYPEDEF,
- &cu->objfile->static_psymbols,
- 0, (CORE_ADDR) 0, cu->language, cu->objfile);
+ &objfile->static_psymbols,
+ 0, (CORE_ADDR) 0, cu->language, objfile);
info_ptr = locate_pdi_sibling (part_die, buffer, info_ptr, abfd, cu);
continue;
}
complaint (&symfile_complaints,
_("DW_TAG_typedef has childen - GCC PR debug/47510 bug "
"- DIE at 0x%x [in module %s]"),
- part_die->offset, cu->objfile->name);
+ part_die->offset, objfile->name);
/* If we're at the second level, and we're an enumerator, and
our parent has no specification (meaning possibly lives in a
VAR_DOMAIN, LOC_CONST,
(cu->language == language_cplus
|| cu->language == language_java)
- ? &cu->objfile->global_psymbols
- : &cu->objfile->static_psymbols,
- 0, (CORE_ADDR) 0, cu->language, cu->objfile);
+ ? &objfile->global_psymbols
+ : &objfile->static_psymbols,
+ 0, (CORE_ADDR) 0, cu->language, objfile);
info_ptr = locate_pdi_sibling (part_die, buffer, info_ptr, abfd, cu);
continue;
gdb_byte *buffer, gdb_byte *info_ptr,
struct dwarf2_cu *cu)
{
+ struct objfile *objfile = cu->objfile;
unsigned int i;
struct attribute attr;
int has_low_pc_attr = 0;
default:
part_die->name
= dwarf2_canonicalize_name (DW_STRING (&attr), cu,
- &cu->objfile->objfile_obstack);
+ &objfile->objfile_obstack);
break;
}
break;
so that GDB will ignore it. */
if (part_die->lowpc == 0 && !dwarf2_per_objfile->has_section_at_zero)
{
- struct gdbarch *gdbarch = get_objfile_arch (cu->objfile);
+ struct gdbarch *gdbarch = get_objfile_arch (objfile);
complaint (&symfile_complaints,
_("DW_AT_low_pc %s is zero "
"for DIE at 0x%x [in module %s]"),
paddress (gdbarch, part_die->lowpc),
- part_die->offset, cu->objfile->name);
+ part_die->offset, objfile->name);
}
/* dwarf2_get_pc_bounds has also the strict low < high requirement. */
else if (part_die->lowpc >= part_die->highpc)
{
- struct gdbarch *gdbarch = get_objfile_arch (cu->objfile);
+ struct gdbarch *gdbarch = get_objfile_arch (objfile);
complaint (&symfile_complaints,
_("DW_AT_low_pc %s is not < DW_AT_high_pc %s "
"for DIE at 0x%x [in module %s]"),
paddress (gdbarch, part_die->lowpc),
paddress (gdbarch, part_die->highpc),
- part_die->offset, cu->objfile->name);
+ part_die->offset, objfile->name);
}
else
part_die->has_pc_info = 1;
static struct partial_die_info *
find_partial_die (unsigned int offset, struct dwarf2_cu *cu)
{
+ struct objfile *objfile = cu->objfile;
struct dwarf2_per_cu_data *per_cu = NULL;
struct partial_die_info *pd = NULL;
- if (cu->per_cu->debug_type_section)
+ if (cu->per_cu->debug_types_section)
{
pd = find_partial_die_in_comp_unit (offset, cu);
if (pd != NULL)
return pd;
}
- per_cu = dwarf2_find_containing_comp_unit (offset, cu->objfile);
+ per_cu = dwarf2_find_containing_comp_unit (offset, objfile);
if (per_cu->cu == NULL || per_cu->cu->partial_dies == NULL)
- load_partial_comp_unit (per_cu, cu->objfile);
+ load_partial_comp_unit (per_cu);
per_cu->cu->last_used = 0;
pd = find_partial_die_in_comp_unit (offset, per_cu->cu);
back_to = make_cleanup (null_cleanup, 0);
if (per_cu->cu->dwarf2_abbrevs == NULL)
{
- dwarf2_read_abbrevs (per_cu->cu->objfile->obfd, per_cu->cu);
+ dwarf2_read_abbrevs (per_cu->cu);
make_cleanup (dwarf2_free_abbrev_table, per_cu->cu);
}
info_ptr = (dwarf2_per_objfile->info.buffer
+ per_cu->cu->header.first_die_offset);
abbrev = peek_die_abbrev (info_ptr, &bytes_read, per_cu->cu);
info_ptr = read_partial_die (&comp_unit_die, abbrev, bytes_read,
- per_cu->cu->objfile->obfd,
+ objfile->obfd,
dwarf2_per_objfile->info.buffer, info_ptr,
per_cu->cu);
if (comp_unit_die.has_children)
- load_partial_dies (per_cu->cu->objfile->obfd,
+ load_partial_dies (objfile->obfd,
dwarf2_per_objfile->info.buffer, info_ptr,
0, per_cu->cu);
do_cleanups (back_to);
internal_error (__FILE__, __LINE__,
_("could not find partial DIE 0x%x "
"in cache [from module %s]\n"),
- offset, bfd_get_filename (cu->objfile->obfd));
+ offset, bfd_get_filename (objfile->obfd));
return pd;
}
/* GCC might emit a nameless struct or union that has a linkage
name. See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47510. */
if (part_die->name == NULL
- && (part_die->tag == DW_TAG_structure_type
- || part_die->tag == DW_TAG_union_type
- || part_die->tag == DW_TAG_class_type)
+ && (part_die->tag == DW_TAG_class_type
+ || part_die->tag == DW_TAG_interface_type
+ || part_die->tag == DW_TAG_structure_type
+ || part_die->tag == DW_TAG_union_type)
&& part_die->linkage_name != NULL)
{
char *demangled;
demangled = cplus_demangle (part_die->linkage_name, DMGL_TYPES);
if (demangled)
{
- part_die->name = obsavestring (demangled, strlen (demangled),
+ const char *base;
+
+ /* Strip any leading namespaces/classes, keep only the base name.
+ DW_AT_name for named DIEs does not contain the prefixes. */
+ base = strrchr (demangled, ':');
+ if (base && base > demangled && base[-1] == ':')
+ base++;
+ else
+ base = demangled;
+
+ part_die->name = obsavestring (base, strlen (base),
&cu->objfile->objfile_obstack);
xfree (demangled);
}
return bfd_get_16 (abfd, buf);
}
+static int
+read_2_signed_bytes (bfd *abfd, gdb_byte *buf)
+{
+ return bfd_get_signed_16 (abfd, buf);
+}
+
static unsigned int
read_4_bytes (bfd *abfd, gdb_byte *buf)
{
return bfd_get_32 (abfd, buf);
}
+static int
+read_4_signed_bytes (bfd *abfd, gdb_byte *buf)
+{
+ return bfd_get_signed_32 (abfd, buf);
+}
+
static ULONGEST
read_8_bytes (bfd *abfd, gdb_byte *buf)
{
return lh;
}
-/* This function exists to work around a bug in certain compilers
- (particularly GCC 2.95), in which the first line number marker of a
- function does not show up until after the prologue, right before
- the second line number marker. This function shifts ADDRESS down
- to the beginning of the function if necessary, and is called on
- addresses passed to record_line. */
-
-static CORE_ADDR
-check_cu_functions (CORE_ADDR address, struct dwarf2_cu *cu)
-{
- struct function_range *fn;
-
- /* Find the function_range containing address. */
- if (!cu->first_fn)
- return address;
-
- if (!cu->cached_fn)
- cu->cached_fn = cu->first_fn;
-
- fn = cu->cached_fn;
- while (fn)
- if (fn->lowpc <= address && fn->highpc > address)
- goto found;
- else
- fn = fn->next;
-
- fn = cu->first_fn;
- while (fn && fn != cu->cached_fn)
- if (fn->lowpc <= address && fn->highpc > address)
- goto found;
- else
- fn = fn->next;
-
- return address;
-
- found:
- if (fn->seen_line)
- return address;
- if (address != fn->lowpc)
- complaint (&symfile_complaints,
- _("misplaced first line number at 0x%lx for '%s'"),
- (unsigned long) address, fn->name);
- fn->seen_line = 1;
- return fn->lowpc;
-}
-
/* Subroutine of dwarf_decode_lines to simplify it.
Return the file name of the psymtab for included file FILE_INDEX
in line header LH of PST.
last_subfile = current_subfile;
}
/* Append row to matrix using current values. */
- addr = check_cu_functions (address, cu);
- addr = gdbarch_addr_bits_remove (gdbarch, addr);
+ addr = gdbarch_addr_bits_remove (gdbarch, address);
(*p_record_line) (current_subfile, line, addr);
}
}
complaint (&symfile_complaints,
_(".debug_line address at offset 0x%lx is 0 "
"[in module %s]"),
- line_offset, cu->objfile->name);
+ line_offset, objfile->name);
p_record_line = noop_record_line;
}
(*p_record_line) (last_subfile, 0, addr);
last_subfile = current_subfile;
}
- addr = check_cu_functions (address, cu);
- addr = gdbarch_addr_bits_remove (gdbarch, addr);
+ addr = gdbarch_addr_bits_remove (gdbarch, address);
(*p_record_line) (current_subfile, line, addr);
}
}
if (current_subfile->symtab == NULL)
current_subfile->symtab = allocate_symtab (current_subfile->name,
- cu->objfile);
+ objfile);
fe->symtab = current_subfile->symtab;
}
}
namespaces based on the demangled name. */
if (!processing_has_namespace_info
&& cu->language == language_cplus)
- cp_scan_for_anonymous_namespaces (sym);
+ cp_scan_for_anonymous_namespaces (sym, objfile);
}
return (sym);
}
lookup_die_type (struct die_info *die, struct attribute *attr,
struct dwarf2_cu *cu)
{
+ struct objfile *objfile = cu->objfile;
struct type *this_type;
/* First see if we have it cached. */
if (sig_type == NULL)
error (_("Dwarf Error: Cannot find signatured DIE referenced from DIE "
"at 0x%x [in module %s]"),
- die->offset, cu->objfile->name);
+ die->offset, objfile->name);
- gdb_assert (sig_type->per_cu.debug_type_section);
+ gdb_assert (sig_type->per_cu.debug_types_section);
offset = sig_type->per_cu.offset + sig_type->type_offset;
this_type = get_die_type_at_offset (offset, &sig_type->per_cu);
}
{
dump_die_for_error (die);
error (_("Dwarf Error: Bad type attribute %s [in module %s]"),
- dwarf_attr_name (attr->name), cu->objfile->name);
+ dwarf_attr_name (attr->name), objfile->name);
}
/* If not cached we need to read it in. */
/* read_type_die already issued a complaint. */
message = xstrprintf (_("<unknown type in %s, CU 0x%x, DIE 0x%x>"),
- cu->objfile->name,
+ objfile->name,
cu->header.offset,
die->offset);
- saved = obstack_copy0 (&cu->objfile->objfile_obstack,
+ saved = obstack_copy0 (&objfile->objfile_obstack,
message, strlen (message));
xfree (message);
- this_type = init_type (TYPE_CODE_ERROR, 0, 0, saved, cu->objfile);
+ this_type = init_type (TYPE_CODE_ERROR, 0, 0, saved, objfile);
}
return this_type;
return NULL;
}
+/* GCC might emit a nameless typedef that has a linkage name. Determine the
+ prefix part in such case. See
+ http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47510. */
+
+static char *
+anonymous_struct_prefix (struct die_info *die, struct dwarf2_cu *cu)
+{
+ struct attribute *attr;
+ char *base;
+
+ if (die->tag != DW_TAG_class_type && die->tag != DW_TAG_interface_type
+ && die->tag != DW_TAG_structure_type && die->tag != DW_TAG_union_type)
+ return NULL;
+
+ attr = dwarf2_attr (die, DW_AT_name, cu);
+ if (attr != NULL && DW_STRING (attr) != NULL)
+ return NULL;
+
+ attr = dwarf2_attr (die, DW_AT_linkage_name, cu);
+ if (attr == NULL)
+ attr = dwarf2_attr (die, DW_AT_MIPS_linkage_name, cu);
+ if (attr == NULL || DW_STRING (attr) == NULL)
+ return NULL;
+
+ /* dwarf2_name had to be already called. */
+ gdb_assert (DW_STRING_IS_CANONICAL (attr));
+
+ /* Strip the base name, keep any leading namespaces/classes. */
+ base = strrchr (DW_STRING (attr), ':');
+ if (base == NULL || base == DW_STRING (attr) || base[-1] != ':')
+ return "";
+
+ return obsavestring (DW_STRING (attr), &base[-1] - DW_STRING (attr),
+ &cu->objfile->objfile_obstack);
+}
+
/* Return the name of the namespace/class that DIE is defined within,
or "" if we can't tell. The caller should not xfree the result.
struct die_info *parent, *spec_die;
struct dwarf2_cu *spec_cu;
struct type *parent_type;
+ char *retval;
if (cu->language != language_cplus && cu->language != language_java
&& cu->language != language_fortran)
return "";
+ retval = anonymous_struct_prefix (die, cu);
+ if (retval)
+ return retval;
+
/* We have to be careful in the presence of DW_AT_specification.
For example, with GCC 3.4, given the code
if (demangled)
{
+ char *base;
+
/* FIXME: we already did this for the partial symbol... */
- DW_STRING (attr)
- = obsavestring (demangled, strlen (demangled),
- &cu->objfile->objfile_obstack);
+ DW_STRING (attr) = obsavestring (demangled, strlen (demangled),
+ &cu->objfile->objfile_obstack);
DW_STRING_IS_CANONICAL (attr) = 1;
xfree (demangled);
+
+ /* Strip any leading namespaces/classes, keep only the base name.
+ DW_AT_name for named DIEs does not contain the prefixes. */
+ base = strrchr (DW_STRING (attr), ':');
+ if (base && base > DW_STRING (attr) && base[-1] == ':')
+ return &base[1];
+ else
+ return DW_STRING (attr);
}
}
break;
return "DW_TAG_PGI_kanji_type";
case DW_TAG_PGI_interface_block:
return "DW_TAG_PGI_interface_block";
+ case DW_TAG_GNU_call_site:
+ return "DW_TAG_GNU_call_site";
default:
return "DW_TAG_<unknown>";
}
}
/* Add it to the queue. */
- queue_comp_unit (per_cu, this_cu->objfile);
+ queue_comp_unit (per_cu);
return 1;
}
target_cu = cu;
- if (cu->per_cu->debug_type_section)
+ if (cu->per_cu->debug_types_section)
{
/* .debug_types CUs cannot reference anything outside their CU.
If they need to, they have to reference a signatured type via
/* If necessary, add it to the queue and load its DIEs. */
if (maybe_queue_comp_unit (cu, per_cu))
- load_full_comp_unit (per_cu, cu->objfile);
+ load_full_comp_unit (per_cu);
target_cu = per_cu->cu;
}
{
/* We're loading full DIEs during partial symbol reading. */
gdb_assert (dwarf2_per_objfile->reading_partial_symbols);
- load_full_comp_unit (cu->per_cu, cu->objfile);
+ load_full_comp_unit (cu->per_cu);
}
*ref_cu = target_cu;
return die;
}
-/* Return DWARF block and its CU referenced by OFFSET at PER_CU. Returned
- value is intended for DW_OP_call*. You must call xfree on returned
- dwarf2_locexpr_baton->data. */
+/* Return DWARF block referenced by DW_AT_location of DIE at OFFSET at PER_CU.
+ Returned value is intended for DW_OP_call*. Returned
+ dwarf2_locexpr_baton->data has lifetime of PER_CU->OBJFILE. */
struct dwarf2_locexpr_baton
dwarf2_fetch_die_location_block (unsigned int offset,
die = follow_die_offset (offset, &cu);
if (!die)
error (_("Dwarf Error: Cannot find DIE at 0x%x referenced in module %s"),
- offset, per_cu->cu->objfile->name);
+ offset, per_cu->objfile->name);
attr = dwarf2_attr (die, DW_AT_location, cu);
if (!attr)
{
- /* DWARF: "If there is no such attribute, then there is no effect.". */
+ /* DWARF: "If there is no such attribute, then there is no effect.".
+ DATA is ignored if SIZE is 0. */
retval.data = NULL;
retval.size = 0;
if (!attr_form_is_block (attr))
error (_("Dwarf Error: DIE at 0x%x referenced in module %s "
"is neither DW_FORM_block* nor DW_FORM_exprloc"),
- offset, per_cu->cu->objfile->name);
+ offset, per_cu->objfile->name);
retval.data = DW_BLOCK (attr)->data;
retval.size = DW_BLOCK (attr)->size;
}
retval.per_cu = cu->per_cu;
- if (retval.data)
- retval.data = xmemdup (retval.data, retval.size, retval.size);
-
age_cached_comp_units ();
return retval;
/* If necessary, add it to the queue and load its DIEs. */
if (maybe_queue_comp_unit (*ref_cu, &sig_type->per_cu))
- read_signatured_type (objfile, sig_type);
+ read_signatured_type (sig_type);
gdb_assert (sig_type->per_cu.cu != NULL);
return type_sig;
}
-/* Read in signatured type at OFFSET and build its CU and die(s). */
+/* Load the DIEs associated with type unit PER_CU into memory. */
static void
-read_signatured_type_at_offset (struct objfile *objfile,
- struct dwarf2_section_info *sect,
- unsigned int offset)
+load_full_type_unit (struct dwarf2_per_cu_data *per_cu)
{
+ struct objfile *objfile = per_cu->objfile;
+ struct dwarf2_section_info *sect = per_cu->debug_types_section;
+ unsigned int offset = per_cu->offset;
struct signatured_type *type_sig;
dwarf2_read_section (objfile, sect);
/* We have the section offset, but we need the signature to do the
- hash table lookup. */
+ hash table lookup. */
+ /* FIXME: This is sorta unnecessary, read_signatured_type only uses
+ the signature to assert we found the right one.
+ Ok, but it's a lot of work. We should simplify things so any needed
+ assert doesn't require all this clumsiness. */
type_sig = lookup_signatured_type_at_offset (objfile, sect, offset);
gdb_assert (type_sig->per_cu.cu == NULL);
- read_signatured_type (objfile, type_sig);
+ read_signatured_type (type_sig);
gdb_assert (type_sig->per_cu.cu != NULL);
}
/* Read in a signatured type and build its CU and DIEs. */
static void
-read_signatured_type (struct objfile *objfile,
- struct signatured_type *type_sig)
+read_signatured_type (struct signatured_type *type_sig)
{
+ struct objfile *objfile = type_sig->per_cu.objfile;
gdb_byte *types_ptr;
struct die_reader_specs reader_specs;
struct dwarf2_cu *cu;
ULONGEST signature;
struct cleanup *back_to, *free_cu_cleanup;
- struct dwarf2_section_info *section = type_sig->per_cu.debug_type_section;
+ struct dwarf2_section_info *section = type_sig->per_cu.debug_types_section;
dwarf2_read_section (objfile, section);
types_ptr = section->buffer + type_sig->per_cu.offset;
gdb_assert (type_sig->per_cu.cu == NULL);
cu = xmalloc (sizeof (*cu));
- init_one_comp_unit (cu, objfile);
-
- type_sig->per_cu.cu = cu;
- cu->per_cu = &type_sig->per_cu;
+ init_one_comp_unit (cu, &type_sig->per_cu);
/* If an error occurs while loading, release our storage. */
- free_cu_cleanup = make_cleanup (free_one_comp_unit, cu);
+ free_cu_cleanup = make_cleanup (free_heap_comp_unit, cu);
types_ptr = read_type_comp_unit_head (&cu->header, section, &signature,
types_ptr, objfile->obfd);
hashtab_obstack_allocate,
dummy_obstack_deallocate);
- dwarf2_read_abbrevs (cu->objfile->obfd, cu);
+ dwarf2_read_abbrevs (cu);
back_to = make_cleanup (dwarf2_free_abbrev_table, cu);
init_cu_die_reader (&reader_specs, cu);
NULL /*parent*/);
/* We try not to read any attributes in this function, because not
- all objfiles needed for references have been loaded yet, and symbol
+ all CUs needed for references have been loaded yet, and symbol
table processing isn't initialized. But we have to set the CU language,
or we won't be able to build types correctly. */
prepare_one_comp_unit (cu, cu->dies);
dwarf2_per_objfile->read_in_chain = &type_sig->per_cu;
}
-/* Workaround as dwarf_expr_context_funcs.read_mem implementation before
- a proper runtime DWARF expressions evaluator gets implemented.
- Otherwise gnuv3_baseclass_offset would error by:
- Expected a negative vbase offset (old compiler?) */
-
-static void
-decode_locdesc_read_mem (void *baton, gdb_byte *buf, CORE_ADDR addr,
- size_t length)
-{
- struct dwarf_expr_context *ctx = baton;
- struct gdbarch *gdbarch = ctx->gdbarch;
- struct type *ptr_type = builtin_type (gdbarch)->builtin_data_ptr;
-
- memset (buf, 0, length);
-
- if (TYPE_LENGTH (ptr_type) == length)
- store_typed_address (buf, ptr_type, addr);
-}
-
-static const struct dwarf_expr_context_funcs decode_locdesc_ctx_funcs =
-{
- ctx_no_read_reg,
- decode_locdesc_read_mem,
- ctx_no_get_frame_base,
- ctx_no_get_frame_cfa,
- ctx_no_get_frame_pc,
- ctx_no_get_tls_address,
- ctx_no_dwarf_call,
- ctx_no_get_base_type
-};
-
/* Decode simple location descriptions.
Given a pointer to a dwarf block that defines a location, compute
the location and return the value.
object is optimized out. The return value is 0 for that case.
FIXME drow/2003-11-16: No callers check for this case any more; soon all
callers will only want a very basic result and this can become a
- complaint. */
+ complaint.
+
+ Note that stack[0] is unused except as a default error return. */
static CORE_ADDR
decode_locdesc (struct dwarf_block *blk, struct dwarf2_cu *cu)
{
struct objfile *objfile = cu->objfile;
- struct dwarf_expr_context *ctx;
- struct cleanup *old_chain;
- volatile struct gdb_exception ex;
+ int i;
+ int size = blk->size;
+ gdb_byte *data = blk->data;
+ CORE_ADDR stack[64];
+ int stacki;
+ unsigned int bytes_read, unsnd;
+ gdb_byte op;
- ctx = new_dwarf_expr_context ();
- old_chain = make_cleanup_free_dwarf_expr_context (ctx);
- make_cleanup_value_free_to_mark (value_mark ());
+ i = 0;
+ stacki = 0;
+ stack[stacki] = 0;
+ stack[++stacki] = 0;
- ctx->gdbarch = get_objfile_arch (objfile);
- ctx->addr_size = cu->header.addr_size;
- ctx->offset = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
- ctx->baton = ctx;
- ctx->funcs = &decode_locdesc_ctx_funcs;
+ while (i < size)
+ {
+ op = data[i++];
+ switch (op)
+ {
+ case DW_OP_lit0:
+ case DW_OP_lit1:
+ case DW_OP_lit2:
+ case DW_OP_lit3:
+ case DW_OP_lit4:
+ case DW_OP_lit5:
+ case DW_OP_lit6:
+ case DW_OP_lit7:
+ case DW_OP_lit8:
+ case DW_OP_lit9:
+ case DW_OP_lit10:
+ case DW_OP_lit11:
+ case DW_OP_lit12:
+ case DW_OP_lit13:
+ case DW_OP_lit14:
+ case DW_OP_lit15:
+ case DW_OP_lit16:
+ case DW_OP_lit17:
+ case DW_OP_lit18:
+ case DW_OP_lit19:
+ case DW_OP_lit20:
+ case DW_OP_lit21:
+ case DW_OP_lit22:
+ case DW_OP_lit23:
+ case DW_OP_lit24:
+ case DW_OP_lit25:
+ case DW_OP_lit26:
+ case DW_OP_lit27:
+ case DW_OP_lit28:
+ case DW_OP_lit29:
+ case DW_OP_lit30:
+ case DW_OP_lit31:
+ stack[++stacki] = op - DW_OP_lit0;
+ break;
- /* DW_AT_data_member_location expects the structure address to be pushed on
- the stack. Simulate the offset by address 0. */
- dwarf_expr_push_address (ctx, 0, 0);
+ case DW_OP_reg0:
+ case DW_OP_reg1:
+ case DW_OP_reg2:
+ case DW_OP_reg3:
+ case DW_OP_reg4:
+ case DW_OP_reg5:
+ case DW_OP_reg6:
+ case DW_OP_reg7:
+ case DW_OP_reg8:
+ case DW_OP_reg9:
+ case DW_OP_reg10:
+ case DW_OP_reg11:
+ case DW_OP_reg12:
+ case DW_OP_reg13:
+ case DW_OP_reg14:
+ case DW_OP_reg15:
+ case DW_OP_reg16:
+ case DW_OP_reg17:
+ case DW_OP_reg18:
+ case DW_OP_reg19:
+ case DW_OP_reg20:
+ case DW_OP_reg21:
+ case DW_OP_reg22:
+ case DW_OP_reg23:
+ case DW_OP_reg24:
+ case DW_OP_reg25:
+ case DW_OP_reg26:
+ case DW_OP_reg27:
+ case DW_OP_reg28:
+ case DW_OP_reg29:
+ case DW_OP_reg30:
+ case DW_OP_reg31:
+ stack[++stacki] = op - DW_OP_reg0;
+ if (i < size)
+ dwarf2_complex_location_expr_complaint ();
+ break;
- TRY_CATCH (ex, RETURN_MASK_ERROR)
- {
- dwarf_expr_eval (ctx, blk->data, blk->size);
- }
- if (ex.reason < 0)
- {
- if (ex.message)
- complaint (&symfile_complaints, "%s", ex.message);
- }
- else if (ctx->num_pieces == 0)
- switch (ctx->location)
- {
- /* The returned number will be bogus, just do not complain for locations
- in global registers - it is here only a partial symbol address. */
- case DWARF_VALUE_REGISTER:
+ case DW_OP_regx:
+ unsnd = read_unsigned_leb128 (NULL, (data + i), &bytes_read);
+ i += bytes_read;
+ stack[++stacki] = unsnd;
+ if (i < size)
+ dwarf2_complex_location_expr_complaint ();
+ break;
- case DWARF_VALUE_MEMORY:
- case DWARF_VALUE_STACK:
- {
- CORE_ADDR address = dwarf_expr_fetch_address (ctx, 0);
+ case DW_OP_addr:
+ stack[++stacki] = read_address (objfile->obfd, &data[i],
+ cu, &bytes_read);
+ i += bytes_read;
+ break;
+
+ case DW_OP_const1u:
+ stack[++stacki] = read_1_byte (objfile->obfd, &data[i]);
+ i += 1;
+ break;
+
+ case DW_OP_const1s:
+ stack[++stacki] = read_1_signed_byte (objfile->obfd, &data[i]);
+ i += 1;
+ break;
+
+ case DW_OP_const2u:
+ stack[++stacki] = read_2_bytes (objfile->obfd, &data[i]);
+ i += 2;
+ break;
+
+ case DW_OP_const2s:
+ stack[++stacki] = read_2_signed_bytes (objfile->obfd, &data[i]);
+ i += 2;
+ break;
+
+ case DW_OP_const4u:
+ stack[++stacki] = read_4_bytes (objfile->obfd, &data[i]);
+ i += 4;
+ break;
+
+ case DW_OP_const4s:
+ stack[++stacki] = read_4_signed_bytes (objfile->obfd, &data[i]);
+ i += 4;
+ break;
+
+ case DW_OP_const8u:
+ stack[++stacki] = read_8_bytes (objfile->obfd, &data[i]);
+ i += 8;
+ break;
- do_cleanups (old_chain);
- return address;
+ case DW_OP_constu:
+ stack[++stacki] = read_unsigned_leb128 (NULL, (data + i),
+ &bytes_read);
+ i += bytes_read;
+ break;
+
+ case DW_OP_consts:
+ stack[++stacki] = read_signed_leb128 (NULL, (data + i), &bytes_read);
+ i += bytes_read;
+ break;
+
+ case DW_OP_dup:
+ stack[stacki + 1] = stack[stacki];
+ stacki++;
+ break;
+
+ case DW_OP_plus:
+ stack[stacki - 1] += stack[stacki];
+ stacki--;
+ break;
+
+ case DW_OP_plus_uconst:
+ stack[stacki] += read_unsigned_leb128 (NULL, (data + i),
+ &bytes_read);
+ i += bytes_read;
+ break;
+
+ case DW_OP_minus:
+ stack[stacki - 1] -= stack[stacki];
+ stacki--;
+ break;
+
+ case DW_OP_deref:
+ /* If we're not the last op, then we definitely can't encode
+ this using GDB's address_class enum. This is valid for partial
+ global symbols, although the variable's address will be bogus
+ in the psymtab. */
+ if (i < size)
+ dwarf2_complex_location_expr_complaint ();
+ break;
+
+ case DW_OP_GNU_push_tls_address:
+ /* The top of the stack has the offset from the beginning
+ of the thread control block at which the variable is located. */
+ /* Nothing should follow this operator, so the top of stack would
+ be returned. */
+ /* This is valid for partial global symbols, but the variable's
+ address will be bogus in the psymtab. Make it always at least
+ non-zero to not look as a variable garbage collected by linker
+ which have DW_OP_addr 0. */
+ if (i < size)
+ dwarf2_complex_location_expr_complaint ();
+ stack[stacki]++;
+ break;
+
+ case DW_OP_GNU_uninit:
+ break;
+
+ default:
+ {
+ const char *name = dwarf_stack_op_name (op);
+
+ if (name)
+ complaint (&symfile_complaints, _("unsupported stack op: '%s'"),
+ name);
+ else
+ complaint (&symfile_complaints, _("unsupported stack op: '%02x'"),
+ op);
+ }
+
+ return (stack[stacki]);
}
- }
- do_cleanups (old_chain);
- dwarf2_complex_location_expr_complaint ();
- return 0;
+ /* Enforce maximum stack depth of SIZE-1 to avoid writing
+ outside of the allocated space. Also enforce minimum>0. */
+ if (stacki >= ARRAY_SIZE (stack) - 1)
+ {
+ complaint (&symfile_complaints,
+ _("location description stack overflow"));
+ return 0;
+ }
+
+ if (stacki <= 0)
+ {
+ complaint (&symfile_complaints,
+ _("location description stack underflow"));
+ return 0;
+ }
+ }
+ return (stack[stacki]);
}
/* memory allocation interface */
struct dwarf2_section_info *section,
int section_is_gnu)
{
+ struct objfile *objfile = dwarf2_per_objfile->objfile;
gdb_byte *mac_ptr, *mac_end;
struct macro_source_file *current_file = 0;
enum dwarf_macro_record_type macinfo_type;
unsigned int offset_size = cu->header.offset_size;
gdb_byte *opcode_definitions[256];
- dwarf2_read_section (dwarf2_per_objfile->objfile, section);
+ dwarf2_read_section (objfile, section);
if (section->buffer == NULL)
{
complaint (&symfile_complaints, _("missing %s section"),
mac_ptr += bytes_read;
current_file = macro_start_file (file, line, current_file,
- comp_dir, lh, cu->objfile);
+ comp_dir, lh, objfile);
}
break;
dwarf_decode_macro_bytes (abfd, section->buffer + offset, mac_end,
current_file, lh, comp_dir, section, section_is_gnu,
- offset_size, cu->objfile);
+ offset_size, objfile);
}
/* Check if the attribute's form is a DW_FORM_block*
dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym,
struct dwarf2_cu *cu)
{
+ struct objfile *objfile = dwarf2_per_objfile->objfile;
+
if (attr_form_is_section_offset (attr)
/* ".debug_loc" may not exist at all, or the offset may be outside
the section. If so, fall through to the complaint in the
other branch. */
- && DW_UNSND (attr) < dwarf2_section_size (dwarf2_per_objfile->objfile,
+ && DW_UNSND (attr) < dwarf2_section_size (objfile,
&dwarf2_per_objfile->loc))
{
struct dwarf2_loclist_baton *baton;
- baton = obstack_alloc (&cu->objfile->objfile_obstack,
+ baton = obstack_alloc (&objfile->objfile_obstack,
sizeof (struct dwarf2_loclist_baton));
fill_in_loclist_baton (cu, baton, attr);
{
struct dwarf2_locexpr_baton *baton;
- baton = obstack_alloc (&cu->objfile->objfile_obstack,
+ baton = obstack_alloc (&objfile->objfile_obstack,
sizeof (struct dwarf2_locexpr_baton));
baton->per_cu = cu->per_cu;
gdb_assert (baton->per_cu);
dwarf2_invalid_attrib_class_complaint ("location description",
SYMBOL_NATURAL_NAME (sym));
baton->size = 0;
- baton->data = NULL;
}
SYMBOL_COMPUTED_OPS (sym) = &dwarf2_locexpr_funcs;
return objfile;
}
+/* Return comp_unit_head for PER_CU, either already available in PER_CU->CU
+ (CU_HEADERP is unused in such case) or prepare a temporary copy at
+ CU_HEADERP first. */
+
+static const struct comp_unit_head *
+per_cu_header_read_in (struct comp_unit_head *cu_headerp,
+ struct dwarf2_per_cu_data *per_cu)
+{
+ struct objfile *objfile;
+ struct dwarf2_per_objfile *per_objfile;
+ gdb_byte *info_ptr;
+
+ if (per_cu->cu)
+ return &per_cu->cu->header;
+
+ objfile = per_cu->objfile;
+ per_objfile = objfile_data (objfile, dwarf2_objfile_data_key);
+ info_ptr = per_objfile->info.buffer + per_cu->offset;
+
+ memset (cu_headerp, 0, sizeof (*cu_headerp));
+ read_comp_unit_head (cu_headerp, info_ptr, objfile->obfd);
+
+ return cu_headerp;
+}
+
/* Return the address size given in the compilation unit header for CU. */
CORE_ADDR
dwarf2_per_cu_addr_size (struct dwarf2_per_cu_data *per_cu)
{
- if (per_cu->cu)
- return per_cu->cu->header.addr_size;
- else
- {
- /* If the CU is not currently read in, we re-read its header. */
- struct objfile *objfile = per_cu->objfile;
- struct dwarf2_per_objfile *per_objfile
- = objfile_data (objfile, dwarf2_objfile_data_key);
- gdb_byte *info_ptr = per_objfile->info.buffer + per_cu->offset;
- struct comp_unit_head cu_header;
+ struct comp_unit_head cu_header_local;
+ const struct comp_unit_head *cu_headerp;
- memset (&cu_header, 0, sizeof cu_header);
- read_comp_unit_head (&cu_header, info_ptr, objfile->obfd);
- return cu_header.addr_size;
- }
+ cu_headerp = per_cu_header_read_in (&cu_header_local, per_cu);
+
+ return cu_headerp->addr_size;
}
/* Return the offset size given in the compilation unit header for CU. */
int
dwarf2_per_cu_offset_size (struct dwarf2_per_cu_data *per_cu)
{
- if (per_cu->cu)
- return per_cu->cu->header.offset_size;
- else
- {
- /* If the CU is not currently read in, we re-read its header. */
- struct objfile *objfile = per_cu->objfile;
- struct dwarf2_per_objfile *per_objfile
- = objfile_data (objfile, dwarf2_objfile_data_key);
- gdb_byte *info_ptr = per_objfile->info.buffer + per_cu->offset;
- struct comp_unit_head cu_header;
+ struct comp_unit_head cu_header_local;
+ const struct comp_unit_head *cu_headerp;
- memset (&cu_header, 0, sizeof cu_header);
- read_comp_unit_head (&cu_header, info_ptr, objfile->obfd);
- return cu_header.offset_size;
- }
+ cu_headerp = per_cu_header_read_in (&cu_header_local, per_cu);
+
+ return cu_headerp->offset_size;
+}
+
+/* See its dwarf2loc.h declaration. */
+
+int
+dwarf2_per_cu_ref_addr_size (struct dwarf2_per_cu_data *per_cu)
+{
+ struct comp_unit_head cu_header_local;
+ const struct comp_unit_head *cu_headerp;
+
+ cu_headerp = per_cu_header_read_in (&cu_header_local, per_cu);
+
+ if (cu_headerp->version == 2)
+ return cu_headerp->addr_size;
+ else
+ return cu_headerp->offset_size;
}
/* Return the text offset of the CU. The returned offset comes from
return this_cu;
}
-/* Initialize dwarf2_cu CU for OBJFILE in a pre-allocated space. */
+/* Initialize dwarf2_cu CU, owned by PER_CU. */
static void
-init_one_comp_unit (struct dwarf2_cu *cu, struct objfile *objfile)
+init_one_comp_unit (struct dwarf2_cu *cu, struct dwarf2_per_cu_data *per_cu)
{
memset (cu, 0, sizeof (*cu));
- cu->objfile = objfile;
+ per_cu->cu = cu;
+ cu->per_cu = per_cu;
+ cu->objfile = per_cu->objfile;
obstack_init (&cu->comp_unit_obstack);
}
cleanup routine. */
static void
-free_one_comp_unit (void *data)
+free_heap_comp_unit (void *data)
{
struct dwarf2_cu *cu = data;
- if (cu->per_cu != NULL)
- cu->per_cu->cu = NULL;
+ gdb_assert (cu->per_cu != NULL);
+ cu->per_cu->cu = NULL;
cu->per_cu = NULL;
obstack_free (&cu->comp_unit_obstack, NULL);
{
struct dwarf2_cu *cu = data;
+ gdb_assert (cu->per_cu != NULL);
+ cu->per_cu->cu = NULL;
+ cu->per_cu = NULL;
+
obstack_free (&cu->comp_unit_obstack, NULL);
cu->partial_dies = NULL;
- if (cu->per_cu != NULL)
- {
- /* This compilation unit is on the stack in our caller, so we
- should not xfree it. Just unlink it. */
- cu->per_cu->cu = NULL;
- cu->per_cu = NULL;
-
- /* If we had a per-cu pointer, then we may have other compilation
- units loaded, so age them now. */
- age_cached_comp_units ();
- }
+ /* The previous code only did this if per_cu != NULL.
+ But that would always succeed, so now we just unconditionally do
+ the aging. This seems like the wrong place to do such aging,
+ but cleaning that up is left for later. */
+ age_cached_comp_units ();
}
/* Free all cached compilation units. */
next_cu = per_cu->cu->read_in_chain;
- free_one_comp_unit (per_cu->cu);
+ free_heap_comp_unit (per_cu->cu);
*last_chain = next_cu;
per_cu = next_cu;
if (!per_cu->cu->mark)
{
- free_one_comp_unit (per_cu->cu);
+ free_heap_comp_unit (per_cu->cu);
*last_chain = next_cu;
}
else
if (per_cu->cu == target_cu)
{
- free_one_comp_unit (per_cu->cu);
+ free_heap_comp_unit (per_cu->cu);
*last_chain = next_cu;
break;
}
&& !HAVE_GNAT_AUX_INFO (type))
INIT_GNAT_SPECIFIC (type);
- if (cu->per_cu->debug_type_section)
+ if (cu->per_cu->debug_types_section)
type_hash_ptr = &dwarf2_per_objfile->debug_types_type_hash;
else
type_hash_ptr = &dwarf2_per_objfile->debug_info_type_hash;
struct dwarf2_offset_and_type *slot, ofs;
htab_t type_hash;
- if (per_cu->debug_type_section)
+ if (per_cu->debug_types_section)
type_hash = dwarf2_per_objfile->debug_types_type_hash;
else
type_hash = dwarf2_per_objfile->debug_info_type_hash;
if (!*slot)
{
*slot = lookup;
- add_index_entry (symtab, SYMBOL_NATURAL_NAME (*psymp), cu_index);
+ add_index_entry (symtab, SYMBOL_SEARCH_NAME (*psymp), cu_index);
}
}
}
return 1;
}
-/* A cleanup function for an htab_t. */
-
-static void
-cleanup_htab (void *arg)
-{
- htab_delete (arg);
-}
-
/* Create an index file for OBJFILE in the directory DIR. */
static void
psyms_seen = htab_create_alloc (100, htab_hash_pointer, htab_eq_pointer,
NULL, xcalloc, xfree);
- make_cleanup (cleanup_htab, psyms_seen);
+ make_cleanup_htab_delete (psyms_seen);
/* While we're scanning CU's create a table that maps a psymtab pointer
(which is what addrmap records) to its index (which is what is recorded
hash_psymtab_cu_index,
eq_psymtab_cu_index,
NULL, xcalloc, xfree);
- make_cleanup (cleanup_htab, cu_index_htab);
+ make_cleanup_htab_delete (cu_index_htab);
psymtab_cu_index_map = (struct psymtab_cu_index_map *)
xmalloc (sizeof (struct psymtab_cu_index_map)
* dwarf2_per_objfile->n_comp_units);