/* DWARF 2 debugging format support for GDB.
- Copyright (C) 1994-2012 Free Software Foundation, Inc.
+ Copyright (C) 1994-2013 Free Software Foundation, Inc.
Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology,
Inc. with support from Florida State University (under contract
#include "defs.h"
#include "bfd.h"
+#include "elf-bfd.h"
#include "symtab.h"
#include "gdbtypes.h"
#include "objfiles.h"
#include "gdb/gdb-index.h"
#include <ctype.h>
#include "gdb_bfd.h"
+#include "f-lang.h"
+#include "source.h"
#include <fcntl.h>
#include "gdb_string.h"
/* When non-zero, do not reject deprecated .gdb_index sections. */
static int use_deprecated_index_sections = 0;
-/* When set, the file that we're processing is known to have debugging
- info for C++ namespaces. GCC 3.3.x did not produce this information,
- but later versions do. */
-
-static int processing_has_namespace_info;
-
static const struct objfile_data *dwarf2_objfile_data_key;
struct dwarf2_section_info
This is NULL if the table hasn't been allocated yet. */
htab_t dwo_files;
+ /* Non-zero if we've check for whether there is a DWP file. */
+ int dwp_checked;
+
+ /* The DWP file if there is one, or NULL. */
+ struct dwp_file *dwp_file;
+
/* The shared '.dwz' file, if one exists. This is used when the
original data was compressed using 'dwz -m'. */
struct dwz_file *dwz_file;
struct mapped_index *index_table;
/* When using index_table, this keeps track of all quick_file_names entries.
- TUs can share line table entries with CUs or other TUs, and there can be
- a lot more TUs than unique line tables, so we maintain a separate table
- of all line table entries to support the sharing. */
+ TUs typically share line table entries with a CU, so we maintain a
+ separate table of all line table entries to support the sharing.
+ Note that while there can be way more TUs than CUs, we've already
+ sorted all the TUs into "type unit groups", grouped by their
+ DW_AT_stmt_list value. Therefore the only sharing done here is with a
+ CU and its associated TU group if there is one. */
htab_t quick_file_names_table;
/* Set during partial symbol reading, to prevent queueing of full
23
};
-/* List of DWO sections. */
+/* List of DWO/DWP sections. */
-static const struct dwo_section_names
+static const struct dwop_section_names
{
struct dwarf2_section_names abbrev_dwo;
struct dwarf2_section_names info_dwo;
struct dwarf2_section_names str_dwo;
struct dwarf2_section_names str_offsets_dwo;
struct dwarf2_section_names types_dwo;
+ struct dwarf2_section_names cu_index;
+ struct dwarf2_section_names tu_index;
}
-dwo_section_names =
+dwop_section_names =
{
{ ".debug_abbrev.dwo", ".zdebug_abbrev.dwo" },
{ ".debug_info.dwo", ".zdebug_info.dwo" },
{ ".debug_str.dwo", ".zdebug_str.dwo" },
{ ".debug_str_offsets.dwo", ".zdebug_str_offsets.dwo" },
{ ".debug_types.dwo", ".zdebug_types.dwo" },
+ { ".debug_cu_index", ".zdebug_cu_index" },
+ { ".debug_tu_index", ".zdebug_tu_index" },
};
/* local data types */
(zero is a valid value though).
Note this value comes from the 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. */
+ 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
+ DW_TAG_compile_unit dies. This is a bit of a wart, consider if ever
+ DW_AT_ranges appeared in the DW_TAG_compile_unit of DWO DIEs: then
+ DW_AT_ranges_base *would* have to be applied, and we'd have to care
+ whether the DW_AT_ranges attribute came from the skeleton or DWO. */
ULONGEST ranges_base;
/* Mark used when releasing cached dies. */
unoptimized code. For a future better test see GCC PR other/32998. */
unsigned int has_loclist : 1;
- /* These cache the results for producer_is_gxx_lt_4_6 and producer_is_icc.
- CHECKED_PRODUCER is set if both PRODUCER_IS_GXX_LT_4_6 and PRODUCER_IS_ICC
- are valid. This information is cached because profiling CU expansion
- showed excessive time spent in producer_is_gxx_lt_4_6. */
+ /* These cache the results for producer_is_* fields. CHECKED_PRODUCER is set
+ if all the producer_is_* fields are valid. This information is cached
+ because profiling CU expansion showed excessive time spent in
+ producer_is_gxx_lt_4_6. */
unsigned int checked_producer : 1;
unsigned int producer_is_gxx_lt_4_6 : 1;
+ unsigned int producer_is_gcc_lt_4_3 : 1;
unsigned int producer_is_icc : 1;
+
+ /* When set, the file that we're processing is known to have
+ debugging info for C++ namespaces. GCC 3.3.x did not produce
+ this information, but later versions do. */
+
+ unsigned int processing_has_namespace_info : 1;
};
/* Persistent data held for a compilation unit, even when not
struct dwarf2_per_cu_quick_data *quick;
} v;
- union
- {
- /* The CUs we import using DW_TAG_imported_unit. This is filled in
- while reading psymtabs, used to compute the psymtab dependencies,
- and then cleared. Then it is filled in again while reading full
- symbols, and only deleted when the objfile is destroyed. */
- VEC (dwarf2_per_cu_ptr) *imported_symtabs;
-
- /* Type units are grouped by their DW_AT_stmt_list entry so that they
- can share them. If this is a TU, this points to the containing
- symtab. */
- struct type_unit_group *type_unit_group;
- } s;
+ /* The CUs we import using DW_TAG_imported_unit. This is filled in
+ while reading psymtabs, used to compute the psymtab dependencies,
+ and then cleared. Then it is filled in again while reading full
+ symbols, and only deleted when the objfile is destroyed.
+
+ This is also used to work around a difference between the way gold
+ generates .gdb_index version <=7 and the way gdb does. Arguably this
+ is a gold bug. For symbols coming from TUs, gold records in the index
+ the CU that includes the TU instead of the TU itself. This breaks
+ dw2_lookup_symbol: It assumes that if the index says symbol X lives
+ in CU/TU Y, then one need only expand Y and a subsequent lookup in Y
+ will find X. Alas TUs live in their own symtab, so after expanding CU Y
+ we need to look in TU Z to find X. Fortunately, this is akin to
+ DW_TAG_imported_unit, so we just use the same mechanism: For
+ .gdb_index version <=7 this also records the TUs that the CU referred
+ to. Concurrently with this change gdb was modified to emit version 8
+ indices so we only pay a price for gold generated indices. */
+ VEC (dwarf2_per_cu_ptr) *imported_symtabs;
+
+ /* Type units are grouped by their DW_AT_stmt_list entry so that they
+ can share them. If this is a TU, this points to the containing
+ symtab. */
+ struct type_unit_group *type_unit_group;
};
/* Entry in the signatured_types hash table. */
struct symtab **symtabs;
};
-/* These sections are what may appear in a "dwo" file. */
+/* These sections are what may appear in a DWO file. */
struct dwo_sections
{
struct dwarf2_section_info abbrev;
- struct dwarf2_section_info info;
struct dwarf2_section_info line;
struct dwarf2_section_info loc;
struct dwarf2_section_info macinfo;
struct dwarf2_section_info macro;
struct dwarf2_section_info str;
struct dwarf2_section_info str_offsets;
+ /* In the case of a virtual DWO file, these two are unused. */
+ struct dwarf2_section_info info;
VEC (dwarf2_section_info_def) *types;
};
cu_offset type_offset_in_tu;
};
-/* Data for one DWO file. */
+/* Data for one DWO file.
+ This includes virtual DWO files that have been packaged into a
+ DWP file. */
struct dwo_file
{
- /* The DW_AT_GNU_dwo_name attribute.
- We don't manage space for this, it's an attribute. */
- const char *dwo_name;
+ /* The DW_AT_GNU_dwo_name attribute. This is the hash key.
+ For virtual DWO files the name is constructed from the section offsets
+ of abbrev,line,loc,str_offsets so that we combine virtual DWO files
+ from related CU+TUs. */
+ const char *name;
- /* The bfd, when the file is open. Otherwise this is NULL. */
- bfd *dwo_bfd;
+ /* The bfd, when the file is open. Otherwise this is NULL.
+ This is unused(NULL) for virtual DWO files where we use dwp_file.dbfd. */
+ bfd *dbfd;
/* Section info for this file. */
struct dwo_sections sections;
htab_t tus;
};
+/* These sections are what may appear in a DWP file. */
+
+struct dwp_sections
+{
+ struct dwarf2_section_info str;
+ struct dwarf2_section_info cu_index;
+ struct dwarf2_section_info tu_index;
+ /* The .debug_info.dwo, .debug_types.dwo, and other sections are referenced
+ by section number. We don't need to record them here. */
+};
+
+/* These sections are what may appear in a virtual DWO file. */
+
+struct virtual_dwo_sections
+{
+ struct dwarf2_section_info abbrev;
+ struct dwarf2_section_info line;
+ struct dwarf2_section_info loc;
+ struct dwarf2_section_info macinfo;
+ struct dwarf2_section_info macro;
+ struct dwarf2_section_info str_offsets;
+ /* Each DWP hash table entry records one CU or one TU.
+ That is recorded here, and copied to dwo_unit.info_or_types_section. */
+ struct dwarf2_section_info info_or_types;
+};
+
+/* Contents of DWP hash tables. */
+
+struct dwp_hash_table
+{
+ uint32_t nr_units, nr_slots;
+ const gdb_byte *hash_table, *unit_table, *section_pool;
+};
+
+/* Data for one DWP file. */
+
+struct dwp_file
+{
+ /* Name of the file. */
+ const char *name;
+
+ /* The bfd, when the file is open. Otherwise this is NULL. */
+ bfd *dbfd;
+
+ /* Section info for this file. */
+ struct dwp_sections sections;
+
+ /* Table of CUs in the file. */
+ const struct dwp_hash_table *cus;
+
+ /* Table of TUs in the file. */
+ const struct dwp_hash_table *tus;
+
+ /* Table of loaded CUs/TUs. Each entry is a struct dwo_unit *. */
+ htab_t loaded_cutus;
+
+ /* Table to map ELF section numbers to their sections. */
+ unsigned int num_sections;
+ asection **elf_sections;
+};
+
/* This represents a '.dwz' file. */
struct dwz_file
/* The CU of the DIE we are parsing. */
struct dwarf2_cu *cu;
- /* Non-NULL if reading a DWO file. */
+ /* Non-NULL if reading a DWO file (including one packaged into a DWP). */
struct dwo_file *dwo_file;
/* The section the die comes from.
/* The name of this DIE. Normally the value of DW_AT_name, but
sometimes a default name for unnamed DIEs. */
- char *name;
+ const char *name;
/* The linkage name, if present. */
const char *linkage_name;
/* The scope to prepend to our children. This is generally
allocated on the comp_unit_obstack, so will disappear
when this compilation unit leaves the cache. */
- char *scope;
+ const char *scope;
/* Some data associated with the partial DIE. The tag determines
which field is live. */
union
{
- char *str;
+ const char *str;
struct dwarf_block *blk;
ULONGEST unsnd;
LONGEST snd;
to the head of the member function field chain. */
struct fnfieldlist
{
- char *name;
+ const char *name;
int length;
struct nextfnfield *head;
}
CORE_ADDR *lowpc, CORE_ADDR *highpc,
int need_pc, struct dwarf2_cu *cu);
-static void dwarf2_psymtab_to_symtab (struct partial_symtab *);
+static void dwarf2_read_symtab (struct partial_symtab *,
+ struct objfile *);
static void psymtab_to_symtab_1 (struct partial_symtab *);
struct attribute *, struct attr_abbrev *,
gdb_byte *);
-static unsigned int read_1_byte (bfd *, gdb_byte *);
+static unsigned int read_1_byte (bfd *, const gdb_byte *);
-static int read_1_signed_byte (bfd *, gdb_byte *);
+static int read_1_signed_byte (bfd *, const gdb_byte *);
-static unsigned int read_2_bytes (bfd *, gdb_byte *);
+static unsigned int read_2_bytes (bfd *, const gdb_byte *);
-static unsigned int read_4_bytes (bfd *, gdb_byte *);
+static unsigned int read_4_bytes (bfd *, const gdb_byte *);
-static ULONGEST read_8_bytes (bfd *, gdb_byte *);
+static ULONGEST read_8_bytes (bfd *, const gdb_byte *);
static CORE_ADDR read_address (bfd *, gdb_byte *ptr, struct dwarf2_cu *,
unsigned int *);
static void dwarf2_start_subfile (char *, const char *, const char *);
static void dwarf2_start_symtab (struct dwarf2_cu *,
- char *, char *, CORE_ADDR);
+ const char *, const char *, CORE_ADDR);
static struct symbol *new_symbol (struct die_info *, struct type *,
struct dwarf2_cu *);
static void process_die (struct die_info *, struct dwarf2_cu *);
-static char *dwarf2_canonicalize_name (char *, struct dwarf2_cu *,
- struct obstack *);
+static const char *dwarf2_canonicalize_name (const char *, struct dwarf2_cu *,
+ struct obstack *);
-static char *dwarf2_name (struct die_info *die, struct dwarf2_cu *);
+static const char *dwarf2_name (struct die_info *die, struct dwarf2_cu *);
-static const char *dwarf2_full_name (char *name,
+static const char *dwarf2_full_name (const char *name,
struct die_info *die,
struct dwarf2_cu *cu);
static struct die_info *dwarf_alloc_die (struct dwarf2_cu *, int);
static void dwarf_decode_macros (struct dwarf2_cu *, unsigned int,
- char *, int);
+ const char *, int);
static int attr_form_is_block (struct attribute *);
static void find_file_and_directory (struct die_info *die,
struct dwarf2_cu *cu,
- char **name, char **comp_dir);
+ const char **name, const char **comp_dir);
static char *file_full_name (int file, struct line_header *lh,
const char *comp_dir);
static htab_t allocate_dwo_unit_table (struct objfile *objfile);
static struct dwo_unit *lookup_dwo_comp_unit
- (struct dwarf2_per_cu_data *, char *, const char *, ULONGEST);
+ (struct dwarf2_per_cu_data *, const char *, const char *, ULONGEST);
static struct dwo_unit *lookup_dwo_type_unit
- (struct signatured_type *, char *, const char *);
+ (struct signatured_type *, const char *, const char *);
static void free_dwo_file_cleanup (void *);
static void process_cu_includes (void);
+static void check_producer (struct dwarf2_cu *cu);
+
#if WORDS_BIGENDIAN
/* Convert VALUE between big- and little-endian. */
/* The suffix for an index file. */
#define INDEX_SUFFIX ".gdb-index"
-static const char *dwarf2_physname (char *name, struct die_info *die,
+static const char *dwarf2_physname (const char *name, struct die_info *die,
struct dwarf2_cu *cu);
/* Try to locate the sections we need for DWARF 2 debugging
do_cleanups (cleanup);
+ dwarf2_per_objfile->dwz_file = result;
return result;
}
\f
return dwarf2_per_objfile->all_comp_units[index];
}
-/* A helper function that knows how to read a 64-bit value in a way
- that doesn't make gdb die. Returns 1 if the conversion went ok, 0
- otherwise. */
-
-static int
-extract_cu_value (const char *bytes, ULONGEST *result)
-{
- if (sizeof (ULONGEST) < 8)
- {
- int i;
-
- /* Ignore the upper 4 bytes if they are all zero. */
- for (i = 0; i < 4; ++i)
- if (bytes[i + 4] != 0)
- return 0;
-
- *result = extract_unsigned_integer (bytes, 4, BFD_ENDIAN_LITTLE);
- }
- else
- *result = extract_unsigned_integer (bytes, 8, BFD_ENDIAN_LITTLE);
- return 1;
-}
-
/* A helper for create_cus_from_index that handles a given list of
CUs. */
-static int
+static void
create_cus_from_index_list (struct objfile *objfile,
const gdb_byte *cu_list, offset_type n_elements,
struct dwarf2_section_info *section,
struct dwarf2_per_cu_data *the_cu;
ULONGEST offset, length;
- if (!extract_cu_value (cu_list, &offset)
- || !extract_cu_value (cu_list + 8, &length))
- return 0;
+ gdb_static_assert (sizeof (ULONGEST) >= 8);
+ offset = extract_unsigned_integer (cu_list, 8, BFD_ENDIAN_LITTLE);
+ length = extract_unsigned_integer (cu_list + 8, 8, BFD_ENDIAN_LITTLE);
cu_list += 2 * 8;
the_cu = OBSTACK_ZALLOC (&objfile->objfile_obstack,
the_cu->is_dwz = is_dwz;
dwarf2_per_objfile->all_comp_units[base_offset + i / 2] = the_cu;
}
-
- return 1;
}
/* Read the CU list from the mapped index, and use it to create all
- the CU objects for this objfile. Return 0 if something went wrong,
- 1 if everything went ok. */
+ the CU objects for this objfile. */
-static int
+static void
create_cus_from_index (struct objfile *objfile,
const gdb_byte *cu_list, offset_type cu_list_elements,
const gdb_byte *dwz_list, offset_type dwz_elements)
dwarf2_per_objfile->n_comp_units
* sizeof (struct dwarf2_per_cu_data *));
- if (!create_cus_from_index_list (objfile, cu_list, cu_list_elements,
- &dwarf2_per_objfile->info, 0, 0))
- return 0;
+ create_cus_from_index_list (objfile, cu_list, cu_list_elements,
+ &dwarf2_per_objfile->info, 0, 0);
if (dwz_elements == 0)
- return 1;
+ return;
dwz = dwarf2_get_dwz_file ();
- return create_cus_from_index_list (objfile, dwz_list, dwz_elements,
- &dwz->info, 1, cu_list_elements / 2);
+ create_cus_from_index_list (objfile, dwz_list, dwz_elements, &dwz->info, 1,
+ cu_list_elements / 2);
}
/* Create the signatured type hash table from the index. */
-static int
+static void
create_signatured_type_table_from_index (struct objfile *objfile,
struct dwarf2_section_info *section,
const gdb_byte *bytes,
ULONGEST offset, type_offset_in_tu, signature;
void **slot;
- if (!extract_cu_value (bytes, &offset)
- || !extract_cu_value (bytes + 8, &type_offset_in_tu))
- return 0;
+ gdb_static_assert (sizeof (ULONGEST) >= 8);
+ offset = extract_unsigned_integer (bytes, 8, BFD_ENDIAN_LITTLE);
+ type_offset_in_tu = extract_unsigned_integer (bytes + 8, 8,
+ BFD_ENDIAN_LITTLE);
signature = extract_unsigned_integer (bytes + 16, 8, BFD_ENDIAN_LITTLE);
bytes += 3 * 8;
}
dwarf2_per_objfile->signatured_types = sig_types_hash;
-
- return 1;
}
/* Read the address map data from the mapped index, and use it to
}
return 0;
}
+ /* Version 7 indices generated by gold refer to the CU for a symbol instead
+ of the TU (for symbols coming from TUs). It's just a performance bug, and
+ we can't distinguish gdb-generated indices from gold-generated ones, so
+ nothing to do here. */
+
/* Indexes with higher version than the one supported by GDB may be no
longer backward compatible. */
- if (version > 7)
+ if (version > 8)
return 0;
map->version = version;
}
}
- if (!create_cus_from_index (objfile, cu_list, cu_list_elements,
- dwz_list, dwz_list_elements))
- return 0;
+ create_cus_from_index (objfile, cu_list, cu_list_elements, dwz_list,
+ dwz_list_elements);
if (types_list_elements)
{
section = VEC_index (dwarf2_section_info_def,
dwarf2_per_objfile->types, 0);
- if (!create_signatured_type_table_from_index (objfile, section,
- types_list,
- types_list_elements))
- return 0;
+ create_signatured_type_table_from_index (objfile, section, types_list,
+ types_list_elements);
}
create_addrmap_from_index (objfile, &local_map);
gdb_assert (dwarf2_per_objfile);
}
-/* Reader function for dw2_build_type_unit_groups. */
-
-static void
-dw2_build_type_unit_groups_reader (const struct die_reader_specs *reader,
- gdb_byte *info_ptr,
- struct die_info *type_unit_die,
- int has_children,
- void *data)
-{
- struct dwarf2_cu *cu = reader->cu;
- struct attribute *attr;
- struct type_unit_group *tu_group;
-
- gdb_assert (data == NULL);
-
- if (! has_children)
- return;
-
- attr = dwarf2_attr_no_follow (type_unit_die, DW_AT_stmt_list);
- /* Call this for its side-effect of creating the associated
- struct type_unit_group if it doesn't already exist. */
- tu_group = get_type_unit_group (cu, attr);
-}
-
-/* Build dwarf2_per_objfile->type_unit_groups.
- This function may be called multiple times. */
-
-static void
-dw2_build_type_unit_groups (void)
-{
- if (dwarf2_per_objfile->type_unit_groups == NULL)
- build_type_unit_groups (dw2_build_type_unit_groups_reader, NULL);
-}
-
/* die_reader_func for dw2_get_file_names. */
static void
struct line_header *lh;
struct attribute *attr;
int i;
- char *name, *comp_dir;
+ const char *name, *comp_dir;
void **slot;
struct quick_file_names *qfn;
unsigned int line_offset;
DWO file. */
if (this_cu->is_debug_types)
{
- struct type_unit_group *tu_group = this_cu->s.type_unit_group;
+ struct type_unit_group *tu_group = this_cu->type_unit_group;
init_cutu_and_read_dies (tu_group->t.first_tu, NULL, 0, 0,
dw2_get_file_names_reader, tu_group);
static int
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,
+ const char *name, const char *real_path,
int (*callback) (struct symtab *, void *),
void *data)
{
all of them. */
dw2_instantiate_symtab (per_cu);
- return iterate_over_some_symtabs (name, full_path, real_path, callback, data,
+ return iterate_over_some_symtabs (name, real_path, callback, data,
objfile->symtabs, last_made);
}
static int
dw2_map_symtabs_matching_filename (struct objfile *objfile, const char *name,
- const char *full_path, const char *real_path,
+ const char *real_path,
int (*callback) (struct symtab *, void *),
void *data)
{
int i;
const char *name_basename = lbasename (name);
- int name_len = strlen (name);
- int is_abs = IS_ABSOLUTE_PATH (name);
dw2_setup (objfile);
- dw2_build_type_unit_groups ();
+ /* The rule is CUs specify all the files, including those used by
+ any TU, so there's no need to scan TUs here. */
- for (i = 0; i < (dwarf2_per_objfile->n_comp_units
- + dwarf2_per_objfile->n_type_unit_groups); ++i)
+ 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);
for (j = 0; j < file_data->num_file_names; ++j)
{
const char *this_name = file_data->file_names[j];
+ const char *this_real_name;
- if (FILENAME_CMP (name, this_name) == 0
- || (!is_abs && compare_filenames_for_search (this_name,
- name, name_len)))
+ if (compare_filenames_for_search (this_name, name))
{
- if (dw2_map_expand_apply (objfile, per_cu,
- name, full_path, real_path,
+ if (dw2_map_expand_apply (objfile, per_cu, name, real_path,
callback, data))
return 1;
}
&& FILENAME_CMP (lbasename (this_name), name_basename) != 0)
continue;
- if (full_path != NULL)
+ this_real_name = dw2_get_real_path (objfile, file_data, j);
+ if (compare_filenames_for_search (this_real_name, name))
{
- const char *this_real_name = dw2_get_real_path (objfile,
- file_data, j);
-
- if (this_real_name != NULL
- && (FILENAME_CMP (full_path, this_real_name) == 0
- || (!is_abs
- && compare_filenames_for_search (this_real_name,
- name, name_len))))
- {
- if (dw2_map_expand_apply (objfile, per_cu,
- name, full_path, real_path,
- callback, data))
- return 1;
- }
+ if (dw2_map_expand_apply (objfile, per_cu, name, real_path,
+ callback, data))
+ return 1;
}
if (real_path != NULL)
{
- const char *this_real_name = dw2_get_real_path (objfile,
- file_data, j);
-
+ gdb_assert (IS_ABSOLUTE_PATH (real_path));
+ gdb_assert (IS_ABSOLUTE_PATH (name));
if (this_real_name != NULL
- && (FILENAME_CMP (real_path, this_real_name) == 0
- || (!is_abs
- && compare_filenames_for_search (this_real_name,
- name, name_len))))
+ && FILENAME_CMP (real_path, this_real_name) == 0)
{
- if (dw2_map_expand_apply (objfile, per_cu,
- name, full_path, real_path,
+ if (dw2_map_expand_apply (objfile, per_cu, name, real_path,
callback, data))
return 1;
}
return 0;
}
-static struct symtab *
-dw2_lookup_symbol (struct objfile *objfile, int block_index,
- const char *name, domain_enum domain)
+/* Struct used to manage iterating over all CUs looking for a symbol. */
+
+struct dw2_symtab_iterator
{
- /* We do all the work in the pre_expand_symtabs_matching hook
- instead. */
- return NULL;
-}
+ /* The internalized form of .gdb_index. */
+ struct mapped_index *index;
+ /* If non-zero, only look for symbols that match BLOCK_INDEX. */
+ int want_specific_block;
+ /* One of GLOBAL_BLOCK or STATIC_BLOCK.
+ Unused if !WANT_SPECIFIC_BLOCK. */
+ int block_index;
+ /* The kind of symbol we're looking for. */
+ domain_enum domain;
+ /* The list of CUs from the index entry of the symbol,
+ or NULL if not found. */
+ offset_type *vec;
+ /* The next element in VEC to look at. */
+ int next;
+ /* The number of elements in VEC, or zero if there is no match. */
+ int length;
+};
-/* A helper function that expands all symtabs that hold an object
- named NAME. If WANT_SPECIFIC_BLOCK is non-zero, only look for
- symbols in block BLOCK_KIND. */
+/* Initialize the index symtab iterator ITER.
+ If WANT_SPECIFIC_BLOCK is non-zero, only look for symbols
+ in block BLOCK_INDEX. Otherwise BLOCK_INDEX is ignored. */
static void
-dw2_do_expand_symtabs_matching (struct objfile *objfile,
- int want_specific_block,
- enum block_enum block_kind,
- const char *name, domain_enum domain)
+dw2_symtab_iter_init (struct dw2_symtab_iterator *iter,
+ struct mapped_index *index,
+ int want_specific_block,
+ int block_index,
+ domain_enum domain,
+ const char *name)
+{
+ iter->index = index;
+ iter->want_specific_block = want_specific_block;
+ iter->block_index = block_index;
+ iter->domain = domain;
+ iter->next = 0;
+
+ if (find_slot_in_mapped_hash (index, name, &iter->vec))
+ iter->length = MAYBE_SWAP (*iter->vec);
+ else
+ {
+ iter->vec = NULL;
+ iter->length = 0;
+ }
+}
+
+/* Return the next matching CU or NULL if there are no more. */
+
+static struct dwarf2_per_cu_data *
+dw2_symtab_iter_next (struct dw2_symtab_iterator *iter)
+{
+ for ( ; iter->next < iter->length; ++iter->next)
+ {
+ offset_type cu_index_and_attrs =
+ MAYBE_SWAP (iter->vec[iter->next + 1]);
+ offset_type cu_index = GDB_INDEX_CU_VALUE (cu_index_and_attrs);
+ struct dwarf2_per_cu_data *per_cu = dw2_get_cu (cu_index);
+ int want_static = iter->block_index != GLOBAL_BLOCK;
+ /* This value is only valid for index versions >= 7. */
+ int is_static = GDB_INDEX_SYMBOL_STATIC_VALUE (cu_index_and_attrs);
+ gdb_index_symbol_kind symbol_kind =
+ GDB_INDEX_SYMBOL_KIND_VALUE (cu_index_and_attrs);
+ /* Only check the symbol attributes if they're present.
+ Indices prior to version 7 don't record them,
+ and indices >= 7 may elide them for certain symbols
+ (gold does this). */
+ int attrs_valid =
+ (iter->index->version >= 7
+ && symbol_kind != GDB_INDEX_SYMBOL_KIND_NONE);
+
+ /* Skip if already read in. */
+ if (per_cu->v.quick->symtab)
+ continue;
+
+ if (attrs_valid
+ && iter->want_specific_block
+ && want_static != is_static)
+ continue;
+
+ /* Only check the symbol's kind if it has one. */
+ if (attrs_valid)
+ {
+ switch (iter->domain)
+ {
+ case VAR_DOMAIN:
+ if (symbol_kind != GDB_INDEX_SYMBOL_KIND_VARIABLE
+ && symbol_kind != GDB_INDEX_SYMBOL_KIND_FUNCTION
+ /* Some types are also in VAR_DOMAIN. */
+ && symbol_kind != GDB_INDEX_SYMBOL_KIND_TYPE)
+ continue;
+ break;
+ case STRUCT_DOMAIN:
+ if (symbol_kind != GDB_INDEX_SYMBOL_KIND_TYPE)
+ continue;
+ break;
+ case LABEL_DOMAIN:
+ if (symbol_kind != GDB_INDEX_SYMBOL_KIND_OTHER)
+ continue;
+ break;
+ default:
+ break;
+ }
+ }
+
+ ++iter->next;
+ return per_cu;
+ }
+
+ return NULL;
+}
+
+static struct symtab *
+dw2_lookup_symbol (struct objfile *objfile, int block_index,
+ const char *name, domain_enum domain)
{
+ struct symtab *stab_best = NULL;
struct mapped_index *index;
dw2_setup (objfile);
index = dwarf2_per_objfile->index_table;
- /* index_table is NULL if OBJF_READNOW. */
+ /* index is NULL if OBJF_READNOW. */
if (index)
{
- offset_type *vec;
+ struct dw2_symtab_iterator iter;
+ struct dwarf2_per_cu_data *per_cu;
+
+ dw2_symtab_iter_init (&iter, index, 1, block_index, domain, name);
- if (find_slot_in_mapped_hash (index, name, &vec))
+ while ((per_cu = dw2_symtab_iter_next (&iter)) != NULL)
{
- offset_type i, len = MAYBE_SWAP (*vec);
- for (i = 0; i < len; ++i)
+ struct symbol *sym = NULL;
+ struct symtab *stab = dw2_instantiate_symtab (per_cu);
+
+ /* 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)
{
- offset_type cu_index_and_attrs = MAYBE_SWAP (vec[i + 1]);
- offset_type cu_index = GDB_INDEX_CU_VALUE (cu_index_and_attrs);
- struct dwarf2_per_cu_data *per_cu = dw2_get_cu (cu_index);
- int want_static = block_kind != GLOBAL_BLOCK;
- /* This value is only valid for index versions >= 7. */
- int is_static = GDB_INDEX_SYMBOL_STATIC_VALUE (cu_index_and_attrs);
- gdb_index_symbol_kind symbol_kind =
- GDB_INDEX_SYMBOL_KIND_VALUE (cu_index_and_attrs);
- /* Only check the symbol attributes if they're present.
- Indices prior to version 7 don't record them,
- and indices >= 7 may elide them for certain symbols
- (gold does this). */
- int attrs_valid =
- (index->version >= 7
- && symbol_kind != GDB_INDEX_SYMBOL_KIND_NONE);
-
- if (attrs_valid
- && want_specific_block
- && want_static != is_static)
- continue;
+ struct blockvector *bv = BLOCKVECTOR (stab);
+ struct block *block = BLOCKVECTOR_BLOCK (bv, block_index);
- /* Only check the symbol's kind if it has one. */
- if (attrs_valid)
- {
- switch (domain)
- {
- case VAR_DOMAIN:
- if (symbol_kind != GDB_INDEX_SYMBOL_KIND_VARIABLE
- && symbol_kind != GDB_INDEX_SYMBOL_KIND_FUNCTION
- /* Some types are also in VAR_DOMAIN. */
- && symbol_kind != GDB_INDEX_SYMBOL_KIND_TYPE)
- continue;
- break;
- case STRUCT_DOMAIN:
- if (symbol_kind != GDB_INDEX_SYMBOL_KIND_TYPE)
- continue;
- break;
- case LABEL_DOMAIN:
- if (symbol_kind != GDB_INDEX_SYMBOL_KIND_OTHER)
- continue;
- break;
- default:
- break;
- }
- }
+ sym = lookup_block_symbol (block, name, domain);
+ }
- dw2_instantiate_symtab (per_cu);
+ if (sym && strcmp_iw (SYMBOL_SEARCH_NAME (sym), name) == 0)
+ {
+ if (!TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)))
+ return stab;
+
+ stab_best = stab;
}
+
+ /* Keep looking through other CUs. */
}
}
-}
-static void
-dw2_pre_expand_symtabs_matching (struct objfile *objfile,
- enum block_enum block_kind, const char *name,
- domain_enum domain)
-{
- dw2_do_expand_symtabs_matching (objfile, 1, block_kind, name, domain);
+ return stab_best;
}
static void
dw2_expand_symtabs_for_function (struct objfile *objfile,
const char *func_name)
{
- /* Note: It doesn't matter what we pass for block_kind here. */
- dw2_do_expand_symtabs_matching (objfile, 0, GLOBAL_BLOCK, func_name,
- VAR_DOMAIN);
+ struct mapped_index *index;
+
+ dw2_setup (objfile);
+
+ index = dwarf2_per_objfile->index_table;
+
+ /* index is NULL if OBJF_READNOW. */
+ if (index)
+ {
+ struct dw2_symtab_iterator iter;
+ struct dwarf2_per_cu_data *per_cu;
+
+ /* Note: It doesn't matter what we pass for block_index here. */
+ dw2_symtab_iter_init (&iter, index, 0, GLOBAL_BLOCK, VAR_DOMAIN,
+ func_name);
+
+ while ((per_cu = dw2_symtab_iter_next (&iter)) != NULL)
+ dw2_instantiate_symtab (per_cu);
+ }
}
static void
}
static void
-dw2_expand_symtabs_with_filename (struct objfile *objfile,
- const char *filename)
+dw2_expand_symtabs_with_fullname (struct objfile *objfile,
+ const char *fullname)
{
int i;
for (j = 0; j < file_data->num_file_names; ++j)
{
- const char *this_name = file_data->file_names[j];
- if (FILENAME_CMP (this_name, filename) == 0)
+ const char *this_fullname = file_data->file_names[j];
+
+ if (filename_cmp (this_fullname, fullname) == 0)
{
dw2_instantiate_symtab (per_cu);
break;
{
struct dwarf2_per_cu_data *per_cu;
offset_type *vec;
- struct quick_file_names *file_data;
const char *filename;
dw2_setup (objfile);
struct symbol *sym = lookup_block_symbol (block, name, VAR_DOMAIN);
if (sym)
- return sym->symtab->filename;
+ {
+ /* Only file extension of returned filename is recognized. */
+ return SYMBOL_SYMTAB (sym)->filename;
+ }
}
return NULL;
}
per_cu = dw2_get_cu (GDB_INDEX_CU_VALUE (MAYBE_SWAP (vec[1])));
if (per_cu->v.quick->symtab != NULL)
- return per_cu->v.quick->symtab->filename;
+ {
+ /* Only file extension of returned filename is recognized. */
+ return per_cu->v.quick->symtab->filename;
+ }
init_cutu_and_read_dies (per_cu, NULL, 0, 0,
dw2_get_primary_filename_reader, &filename);
+ /* Only file extension of returned filename is recognized. */
return filename;
}
static void
dw2_expand_symtabs_matching
(struct objfile *objfile,
- int (*file_matcher) (const char *, void *),
+ int (*file_matcher) (const char *, void *, int basenames),
int (*name_matcher) (const char *, void *),
enum search_domain kind,
void *data)
struct cleanup *cleanup;
htab_t visited_found, visited_not_found;
- dw2_build_type_unit_groups ();
-
visited_found = htab_create_alloc (10,
htab_hash_pointer, htab_eq_pointer,
NULL, xcalloc, xfree);
NULL, xcalloc, xfree);
make_cleanup_htab_delete (visited_not_found);
- for (i = 0; i < (dwarf2_per_objfile->n_comp_units
- + dwarf2_per_objfile->n_type_unit_groups); ++i)
+ /* The rule is CUs specify all the files, including those used by
+ any TU, so there's no need to scan TUs here. */
+
+ 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);
for (j = 0; j < file_data->num_file_names; ++j)
{
- if (file_matcher (file_data->file_names[j], data))
+ const char *this_real_name;
+
+ if (file_matcher (file_data->file_names[j], data, 0))
+ {
+ per_cu->v.quick->mark = 1;
+ break;
+ }
+
+ /* Before we invoke realpath, which can get expensive when many
+ files are involved, do a quick comparison of the basenames. */
+ if (!basenames_may_differ
+ && !file_matcher (lbasename (file_data->file_names[j]),
+ data, 1))
+ continue;
+
+ this_real_name = dw2_get_real_path (objfile, file_data, j);
+ if (file_matcher (this_real_name, data, 0))
{
per_cu->v.quick->mark = 1;
break;
cleanup = make_cleanup_htab_delete (visited);
dw2_setup (objfile);
- dw2_build_type_unit_groups ();
+ /* The rule is CUs specify all the files, including those used by
+ any TU, so there's no need to scan TUs here.
+ We can ignore file names coming from already-expanded CUs. */
- /* We can ignore file names coming from already-expanded CUs. */
- for (i = 0; i < (dwarf2_per_objfile->n_comp_units
- + dwarf2_per_objfile->n_type_units); ++i)
+ for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
{
struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
}
}
- for (i = 0; i < (dwarf2_per_objfile->n_comp_units
- + dwarf2_per_objfile->n_type_unit_groups); ++i)
+ 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);
dw2_forget_cached_source_info,
dw2_map_symtabs_matching_filename,
dw2_lookup_symbol,
- dw2_pre_expand_symtabs_matching,
dw2_print_stats,
dw2_dump,
dw2_relocate,
dw2_expand_symtabs_for_function,
dw2_expand_all_symtabs,
- dw2_expand_symtabs_with_filename,
+ dw2_expand_symtabs_with_fullname,
dw2_find_symbol_file,
dw2_map_matching_symbols,
dw2_expand_symtabs_matching,
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);
}
- dwarf2_build_psymtabs_hard (objfile);
+ TRY_CATCH (except, RETURN_MASK_ERROR)
+ {
+ /* This isn't really ideal: all the data we allocate on the
+ objfile's obstack is still uselessly kept around. However,
+ freeing it seems unsafe. */
+ struct cleanup *cleanups = make_cleanup_discard_psymtabs (objfile);
+
+ dwarf2_build_psymtabs_hard (objfile);
+ discard_cleanups (cleanups);
+ }
+ if (except.reason < 0)
+ exception_print (gdb_stderr, except);
}
/* Return the total length of the CU described by HEADER. */
{
struct partial_symtab *subpst = allocate_psymtab (name, objfile);
+ if (!IS_ABSOLUTE_PATH (subpst->filename))
+ {
+ /* It shares objfile->objfile_obstack. */
+ subpst->dirname = pst->dirname;
+ }
+
subpst->section_offsets = pst->section_offsets;
subpst->textlow = 0;
subpst->texthigh = 0;
}
/* Create the hash table of all entries in the .debug_types section.
- DWO_FILE is a pointer to the DWO file for .debug_types.dwo, NULL otherwise.
+ DWO_FILE is a pointer to the DWO file for .debug_types.dwo,
+ NULL otherwise.
+ Note: This function processes DWO files only, not DWP files.
The result is a pointer to the hash table or NULL if there are
no types. */
attr = dwarf2_attr (comp_unit_die, DW_AT_GNU_dwo_name, cu);
if (attr)
{
- char *dwo_name = DW_STRING (attr);
+ const char *dwo_name = DW_STRING (attr);
const char *comp_dir_string;
struct dwo_unit *dwo_unit;
ULONGEST signature; /* Or dwo_id. */
/* Set up for reading the DWO CU/TU. */
cu->dwo_unit = dwo_unit;
section = dwo_unit->info_or_types_section;
+ dwarf2_read_section (objfile, section);
begin_info_ptr = info_ptr = section->buffer + dwo_unit->offset.sect_off;
dwo_abbrev_section = &dwo_unit->dwo_file->sections.abbrev;
init_cu_die_reader (&reader, cu, section, dwo_unit->dwo_file);
if (this_cu->is_debug_types)
{
ULONGEST signature;
+ cu_offset type_offset_in_tu;
info_ptr = read_and_check_type_unit_head (&cu->header, section,
dwo_abbrev_section,
info_ptr,
- &signature, NULL);
+ &signature,
+ &type_offset_in_tu);
gdb_assert (sig_type->signature == signature);
gdb_assert (dwo_unit->offset.sect_off == cu->header.offset.sect_off);
- gdb_assert (dwo_unit->length == get_cu_length (&cu->header));
+ /* For DWOs coming from DWP files, we don't know the CU length
+ nor the type's offset in the TU until now. */
+ dwo_unit->length = get_cu_length (&cu->header);
+ dwo_unit->type_offset_in_tu = type_offset_in_tu;
/* Establish the type offset that can be used to lookup the type.
For DWO files, we don't know it until now. */
dwo_abbrev_section,
info_ptr, 0);
gdb_assert (dwo_unit->offset.sect_off == cu->header.offset.sect_off);
- gdb_assert (dwo_unit->length == get_cu_length (&cu->header));
+ /* For DWOs coming from DWP files, we don't know the CU length
+ until now. */
+ dwo_unit->length = get_cu_length (&cu->header);
}
/* Discard the original CU's abbrev table, and read the DWO's. */
/* Read CU/TU THIS_CU in section SECTION,
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).
+ 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).
The caller is required to fill in THIS_CU->section, THIS_CU->offset, and
THIS_CU->is_debug_types, but nothing else.
/* This is the glue that links PST into GDB's symbol API. */
pst->read_symtab_private = per_cu;
- pst->read_symtab = dwarf2_psymtab_to_symtab;
+ pst->read_symtab = dwarf2_read_symtab;
per_cu->v.psymtab = pst;
return pst;
(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 (pst);
+ sort_pst_symbols (objfile, pst);
- if (!VEC_empty (dwarf2_per_cu_ptr, cu->per_cu->s.imported_symtabs))
+ if (!VEC_empty (dwarf2_per_cu_ptr, cu->per_cu->imported_symtabs))
{
int i;
- int len = VEC_length (dwarf2_per_cu_ptr, cu->per_cu->s.imported_symtabs);
+ int len = VEC_length (dwarf2_per_cu_ptr, cu->per_cu->imported_symtabs);
struct dwarf2_per_cu_data *iter;
/* Fill in 'dependencies' here; we fill in 'users' in a
pst->dependencies = obstack_alloc (&objfile->objfile_obstack,
len * sizeof (struct symtab *));
for (i = 0;
- VEC_iterate (dwarf2_per_cu_ptr, cu->per_cu->s.imported_symtabs,
+ VEC_iterate (dwarf2_per_cu_ptr, cu->per_cu->imported_symtabs,
i, iter);
++i)
pst->dependencies[i] = iter->v.psymtab;
- VEC_free (dwarf2_per_cu_ptr, cu->per_cu->s.imported_symtabs);
+ VEC_free (dwarf2_per_cu_ptr, cu->per_cu->imported_symtabs);
}
/* Get the list of files included in the current compilation unit,
struct gdbarch *gdbarch = get_objfile_arch (objfile);
fprintf_unfiltered (gdb_stdlog,
- "Psymtab for %s unit @0x%x: 0x%s - 0x%s"
+ "Psymtab for %s unit @0x%x: %s - %s"
", %d global, %d static syms\n",
per_cu->is_debug_types ? "type" : "comp",
per_cu->offset.sect_off,
per_cu = &tu_group->per_cu;
per_cu->objfile = objfile;
per_cu->is_debug_types = 1;
- per_cu->s.type_unit_group = tu_group;
+ per_cu->type_unit_group = tu_group;
if (dwarf2_per_objfile->using_index)
{
(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 (pst);
+ sort_pst_symbols (objfile, pst);
}
/* Traversal function for build_type_psymtabs. */
++i)
{
pst->dependencies[i] = iter->v.psymtab;
- iter->s.type_unit_group = tu_group;
+ iter->type_unit_group = tu_group;
}
VEC_free (dwarf2_per_cu_ptr, tu_group->t.tus);
process_psymtab_comp_unit (per_cu, 1);
VEC_safe_push (dwarf2_per_cu_ptr,
- cu->per_cu->s.imported_symtabs, per_cu);
+ cu->per_cu->imported_symtabs, per_cu);
}
break;
default:
compilation unit CU. The result will be allocated on CU's
comp_unit_obstack, or a copy of the already allocated PDI->NAME
field. NULL is returned if no prefix is necessary. */
-static char *
+static const char *
partial_die_parent_scope (struct partial_die_info *pdi,
struct dwarf2_cu *cu)
{
- char *grandparent_scope;
+ const char *grandparent_scope;
struct partial_die_info *parent, *real_pdi;
/* We need to look at our parent DIE; if we have a DW_AT_specification,
partial_die_full_name (struct partial_die_info *pdi,
struct dwarf2_cu *cu)
{
- char *parent_scope;
+ const char *parent_scope;
/* If this is a template instantiation, we can not work out the
template arguments from partial DIEs. So, unfortunately, we have
{
struct objfile *objfile = cu->objfile;
CORE_ADDR addr = 0;
- char *actual_name = NULL;
+ const char *actual_name = NULL;
CORE_ADDR baseaddr;
- int built_actual_name = 0;
+ char *built_actual_name;
baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
- actual_name = partial_die_full_name (pdi, cu);
- if (actual_name)
- built_actual_name = 1;
+ built_actual_name = partial_die_full_name (pdi, cu);
+ if (built_actual_name != NULL)
+ actual_name = built_actual_name;
if (actual_name == NULL)
actual_name = pdi->name;
/* prim_record_minimal_symbol (actual_name, pdi->lowpc + baseaddr,
mst_text, objfile); */
add_psymbol_to_list (actual_name, strlen (actual_name),
- built_actual_name,
+ built_actual_name != NULL,
VAR_DOMAIN, LOC_BLOCK,
&objfile->global_psymbols,
0, pdi->lowpc + baseaddr,
/* prim_record_minimal_symbol (actual_name, pdi->lowpc + baseaddr,
mst_file_text, objfile); */
add_psymbol_to_list (actual_name, strlen (actual_name),
- built_actual_name,
+ built_actual_name != NULL,
VAR_DOMAIN, LOC_BLOCK,
&objfile->static_psymbols,
0, pdi->lowpc + baseaddr,
else
list = &objfile->static_psymbols;
add_psymbol_to_list (actual_name, strlen (actual_name),
- built_actual_name, VAR_DOMAIN, LOC_STATIC,
+ built_actual_name != NULL, VAR_DOMAIN, LOC_STATIC,
list, 0, 0, cu->language, objfile);
}
break;
if (pdi->d.locdesc || pdi->has_type)
add_psymbol_to_list (actual_name, strlen (actual_name),
- built_actual_name,
+ built_actual_name != NULL,
VAR_DOMAIN, LOC_STATIC,
&objfile->global_psymbols,
0, addr + baseaddr,
/* Static Variable. Skip symbols without location descriptors. */
if (pdi->d.locdesc == NULL)
{
- if (built_actual_name)
- xfree (actual_name);
+ 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,
+ built_actual_name != NULL,
VAR_DOMAIN, LOC_STATIC,
&objfile->static_psymbols,
0, addr + baseaddr,
case DW_TAG_base_type:
case DW_TAG_subrange_type:
add_psymbol_to_list (actual_name, strlen (actual_name),
- built_actual_name,
+ built_actual_name != NULL,
VAR_DOMAIN, LOC_TYPEDEF,
&objfile->static_psymbols,
0, (CORE_ADDR) 0, cu->language, objfile);
break;
case DW_TAG_namespace:
add_psymbol_to_list (actual_name, strlen (actual_name),
- built_actual_name,
+ built_actual_name != NULL,
VAR_DOMAIN, LOC_TYPEDEF,
&objfile->global_psymbols,
0, (CORE_ADDR) 0, cu->language, objfile);
and that has a DW_AT_declaration attribute." */
if (!pdi->has_byte_size && pdi->is_declaration)
{
- if (built_actual_name)
- xfree (actual_name);
+ xfree (built_actual_name);
return;
}
/* NOTE: carlton/2003-10-07: See comment in new_symbol about
static vs. global. */
add_psymbol_to_list (actual_name, strlen (actual_name),
- built_actual_name,
+ built_actual_name != NULL,
STRUCT_DOMAIN, LOC_TYPEDEF,
(cu->language == language_cplus
|| cu->language == language_java)
break;
case DW_TAG_enumerator:
add_psymbol_to_list (actual_name, strlen (actual_name),
- built_actual_name,
+ built_actual_name != NULL,
VAR_DOMAIN, LOC_CONST,
(cu->language == language_cplus
|| cu->language == language_java)
break;
}
- if (built_actual_name)
- xfree (actual_name);
+ xfree (built_actual_name);
}
/* Read a partial die corresponding to a namespace; also, add a symbol
return skip_children (reader, info_ptr);
}
-/* Expand this partial symbol table into a full symbol table. */
+/* Expand this partial symbol table into a full symbol table. SELF is
+ not NULL. */
static void
-dwarf2_psymtab_to_symtab (struct partial_symtab *pst)
+dwarf2_read_symtab (struct partial_symtab *self,
+ struct objfile *objfile)
{
- if (pst != NULL)
+ if (self->readin)
{
- if (pst->readin)
+ warning (_("bug: psymtab for %s is already read in."),
+ self->filename);
+ }
+ else
+ {
+ if (info_verbose)
{
- warning (_("bug: psymtab for %s is already read in."),
- pst->filename);
+ printf_filtered (_("Reading in symbols for %s..."),
+ self->filename);
+ gdb_flush (gdb_stdout);
}
- else
- {
- if (info_verbose)
- {
- printf_filtered (_("Reading in symbols for %s..."),
- pst->filename);
- gdb_flush (gdb_stdout);
- }
- /* Restore our global data. */
- dwarf2_per_objfile = objfile_data (pst->objfile,
- dwarf2_objfile_data_key);
+ /* Restore our global data. */
+ dwarf2_per_objfile = objfile_data (objfile, dwarf2_objfile_data_key);
- /* If this psymtab is constructed from a debug-only objfile, the
- has_section_at_zero flag will not necessarily be correct. We
- can get the correct value for this flag by looking at the data
- associated with the (presumably stripped) associated objfile. */
- if (pst->objfile->separate_debug_objfile_backlink)
- {
- struct dwarf2_per_objfile *dpo_backlink
- = objfile_data (pst->objfile->separate_debug_objfile_backlink,
- dwarf2_objfile_data_key);
+ /* If this psymtab is constructed from a debug-only objfile, the
+ has_section_at_zero flag will not necessarily be correct. We
+ can get the correct value for this flag by looking at the data
+ associated with the (presumably stripped) associated objfile. */
+ if (objfile->separate_debug_objfile_backlink)
+ {
+ struct dwarf2_per_objfile *dpo_backlink
+ = objfile_data (objfile->separate_debug_objfile_backlink,
+ dwarf2_objfile_data_key);
- dwarf2_per_objfile->has_section_at_zero
- = dpo_backlink->has_section_at_zero;
- }
+ dwarf2_per_objfile->has_section_at_zero
+ = dpo_backlink->has_section_at_zero;
+ }
- dwarf2_per_objfile->reading_partial_symbols = 0;
+ dwarf2_per_objfile->reading_partial_symbols = 0;
- psymtab_to_symtab_1 (pst);
+ psymtab_to_symtab_1 (self);
- /* Finish up the debug error message. */
- if (info_verbose)
- printf_filtered (_("done.\n"));
- }
+ /* Finish up the debug error message. */
+ if (info_verbose)
+ printf_filtered (_("done.\n"));
}
process_cu_includes ();
const char *physname;
struct fn_fieldlist *fn_flp
= &TYPE_FN_FIELDLIST (mi->type, mi->fnfield_index);
- physname = dwarf2_physname ((char *) mi->name, mi->die, cu);
+ physname = dwarf2_physname (mi->name, mi->die, cu);
fn_flp->fn_fields[mi->index].physname = 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"),
- (sym->symtab && sym->symtab->filename
- ? sym->symtab->filename
+ (SYMBOL_SYMTAB (sym)
+ ? symtab_to_filename_for_display (SYMBOL_SYMTAB (sym))
: cu->objfile->name),
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));
struct type *type = init_type (TYPE_CODE_MODULE, 0, 0,
- package_name, objfile);
+ saved_package_name, objfile);
struct symbol *sym;
TYPE_TAG_NAME (type) = TYPE_NAME (type);
sym = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct symbol);
SYMBOL_SET_LANGUAGE (sym, language_go);
- SYMBOL_SET_NAMES (sym, package_name, strlen (package_name), 1, objfile);
+ SYMBOL_SET_NAMES (sym, saved_package_name,
+ strlen (saved_package_name), 0, objfile);
/* This is not VAR_DOMAIN because we want a way to ensure a lookup of,
e.g., "main" finds the "main" module and not C's main(). */
SYMBOL_DOMAIN (sym) = STRUCT_DOMAIN;
VEC_safe_push (dwarf2_per_cu_ptr, *result, per_cu);
for (ix = 0;
- VEC_iterate (dwarf2_per_cu_ptr, per_cu->s.imported_symtabs, ix, iter);
+ VEC_iterate (dwarf2_per_cu_ptr, per_cu->imported_symtabs, ix, iter);
++ix)
recursively_compute_inclusions (result, all_children, iter);
}
{
gdb_assert (! per_cu->is_debug_types);
- if (!VEC_empty (dwarf2_per_cu_ptr, per_cu->s.imported_symtabs))
+ if (!VEC_empty (dwarf2_per_cu_ptr, per_cu->imported_symtabs))
{
int ix, len;
struct dwarf2_per_cu_data *iter;
NULL, xcalloc, xfree);
for (ix = 0;
- VEC_iterate (dwarf2_per_cu_ptr, per_cu->s.imported_symtabs,
+ VEC_iterate (dwarf2_per_cu_ptr, per_cu->imported_symtabs,
ix, iter);
++ix)
recursively_compute_inclusions (&result_children, all_children, iter);
- /* Now we have a transitive closure of all the included CUs, so
- we can convert it to a list of symtabs. */
+ /* Now we have a transitive closure of all the included CUs, and
+ for .gdb_index version 7 the included TUs, so we can convert it
+ to a list of symtabs. */
len = VEC_length (dwarf2_per_cu_ptr, result_children);
symtab->includes
= obstack_alloc (&dwarf2_per_objfile->objfile->objfile_obstack,
static_block
= end_symtab_get_static_block (highpc + baseaddr, objfile, 0,
- per_cu->s.imported_symtabs != NULL);
+ per_cu->imported_symtabs != NULL);
/* 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
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 (per_cu->s.type_unit_group->primary_symtab == NULL)
+ if (per_cu->type_unit_group->primary_symtab == NULL)
{
symtab = end_expandable_symtab (0, objfile, SECT_OFF_TEXT (objfile));
- per_cu->s.type_unit_group->primary_symtab = symtab;
+ per_cu->type_unit_group->primary_symtab = symtab;
if (symtab != NULL)
{
else
{
augment_type_symtab (objfile,
- per_cu->s.type_unit_group->primary_symtab);
- symtab = per_cu->s.type_unit_group->primary_symtab;
+ per_cu->type_unit_group->primary_symtab);
+ symtab = per_cu->type_unit_group->primary_symtab;
}
if (dwarf2_per_objfile->using_index)
if (maybe_queue_comp_unit (cu, per_cu, cu->language))
load_full_comp_unit (per_cu, cu->language);
- VEC_safe_push (dwarf2_per_cu_ptr, cu->per_cu->s.imported_symtabs,
+ VEC_safe_push (dwarf2_per_cu_ptr, cu->per_cu->imported_symtabs,
per_cu);
}
}
case DW_TAG_common_inclusion:
break;
case DW_TAG_namespace:
- processing_has_namespace_info = 1;
+ cu->processing_has_namespace_info = 1;
read_namespace (die, cu);
break;
case DW_TAG_module:
- processing_has_namespace_info = 1;
+ cu->processing_has_namespace_info = 1;
read_module (die, cu);
break;
case DW_TAG_imported_declaration:
case DW_TAG_imported_module:
- processing_has_namespace_info = 1;
+ cu->processing_has_namespace_info = 1;
if (die->child != NULL && (die->tag == DW_TAG_imported_declaration
|| cu->language != language_fortran))
complaint (&symfile_complaints, _("Tag '%s' has unexpected children"),
The result is allocated on the objfile_obstack and canonicalized. */
static const char *
-dwarf2_compute_name (char *name, struct die_info *die, struct dwarf2_cu *cu,
+dwarf2_compute_name (const char *name,
+ struct die_info *die, struct dwarf2_cu *cu,
int physname)
{
struct objfile *objfile = cu->objfile;
if (child->tag == DW_TAG_template_type_param)
{
- c_print_type (type, "", buf, -1, 0);
+ c_print_type (type, "", buf, -1, 0, &type_print_raw_options);
continue;
}
{
struct type *type = read_type_die (die, cu);
- c_type_print_args (type, buf, 1, cu->language);
+ c_type_print_args (type, buf, 1, cu->language,
+ &type_print_raw_options);
if (cu->language == language_java)
{
names. */
if (die->tag == DW_TAG_subprogram)
java_print_type (TYPE_TARGET_TYPE (type), "", buf,
- 0, 0);
+ 0, 0, &type_print_raw_options);
}
else if (cu->language == language_cplus)
{
if (cu->language == language_cplus)
{
- char *cname
+ const char *cname
= dwarf2_canonicalize_name (name, cu,
&objfile->objfile_obstack);
The output string will be canonicalized (if C++/Java). */
static const char *
-dwarf2_full_name (char *name, struct die_info *die, struct dwarf2_cu *cu)
+dwarf2_full_name (const char *name, struct die_info *die, struct dwarf2_cu *cu)
{
return dwarf2_compute_name (name, die, cu, 0);
}
The output string will be canonicalized (if C++/Java). */
static const char *
-dwarf2_physname (char *name, struct die_info *die, struct dwarf2_cu *cu)
+dwarf2_physname (const char *name, struct die_info *die, struct dwarf2_cu *cu)
{
struct objfile *objfile = cu->objfile;
struct attribute *attr;
retval = canon;
if (need_copy)
- retval = obsavestring (retval, strlen (retval),
- &objfile->objfile_obstack);
+ retval = obstack_copy0 (&objfile->objfile_obstack, retval, strlen (retval));
do_cleanups (back_to);
return retval;
VEC (const_char_ptr) *excludes = NULL;
struct cleanup *cleanups;
- char *temp;
-
import_attr = dwarf2_attr (die, DW_AT_import, cu);
if (import_attr == NULL)
{
canonical_name = imported_name_prefix;
}
else if (strlen (imported_name_prefix) > 0)
- {
- temp = alloca (strlen (imported_name_prefix)
- + 2 + strlen (imported_name) + 1);
- strcpy (temp, imported_name_prefix);
- strcat (temp, "::");
- strcat (temp, imported_name);
- canonical_name = temp;
- }
+ canonical_name = obconcat (&objfile->objfile_obstack,
+ imported_name_prefix, "::", imported_name,
+ (char *) NULL);
else
canonical_name = imported_name;
import_alias,
imported_declaration,
excludes,
+ 0,
&objfile->objfile_obstack);
do_cleanups (cleanups);
cu->line_header = NULL;
}
+/* Check for possibly missing DW_AT_comp_dir with relative .debug_line
+ directory paths. GCC SVN r127613 (new option -fdebug-prefix-map) fixed
+ this, it was first present in GCC release 4.3.0. */
+
+static int
+producer_is_gcc_lt_4_3 (struct dwarf2_cu *cu)
+{
+ if (!cu->checked_producer)
+ check_producer (cu);
+
+ return cu->producer_is_gcc_lt_4_3;
+}
+
static void
find_file_and_directory (struct die_info *die, struct dwarf2_cu *cu,
- char **name, char **comp_dir)
+ const char **name, const char **comp_dir)
{
struct attribute *attr;
attr = dwarf2_attr (die, DW_AT_comp_dir, cu);
if (attr)
*comp_dir = DW_STRING (attr);
- else if (*name != NULL && IS_ABSOLUTE_PATH (*name))
+ else if (producer_is_gcc_lt_4_3 (cu) && *name != NULL
+ && IS_ABSOLUTE_PATH (*name))
{
- *comp_dir = ldirname (*name);
- if (*comp_dir != NULL)
- make_cleanup (xfree, *comp_dir);
+ char *d = ldirname (*name);
+
+ *comp_dir = d;
+ if (d != NULL)
+ make_cleanup (xfree, d);
}
if (*comp_dir != NULL)
{
CORE_ADDR lowpc = ((CORE_ADDR) -1);
CORE_ADDR highpc = ((CORE_ADDR) 0);
struct attribute *attr;
- char *name = NULL;
- char *comp_dir = NULL;
+ const char *name = NULL;
+ const char *comp_dir = NULL;
struct die_info *child_die;
bfd *abfd = objfile->obfd;
CORE_ADDR baseaddr;
/* If we're using .gdb_index (includes -readnow) then
per_cu->s.type_unit_group may not have been set up yet. */
- if (per_cu->s.type_unit_group == NULL)
- per_cu->s.type_unit_group = get_type_unit_group (cu, attr);
- tu_group = per_cu->s.type_unit_group;
+ if (per_cu->type_unit_group == NULL)
+ per_cu->type_unit_group = get_type_unit_group (cu, attr);
+ tu_group = per_cu->type_unit_group;
/* If we've already processed this stmt_list there's no real need to
do it again, we could fake it and just recreate the part we need
}
}
\f
-/* DWO files. */
+/* DWO/DWP files.
+
+ http://gcc.gnu.org/wiki/DebugFission
+ http://gcc.gnu.org/wiki/DebugFissionDWP
+
+ To simplify handling of both DWO files ("object" files with the DWARF info)
+ and DWP files (a file with the DWOs packaged up into one file), we treat
+ DWP files as having a collection of virtual DWO files. */
static hashval_t
hash_dwo_file (const void *item)
{
const struct dwo_file *dwo_file = item;
- return htab_hash_string (dwo_file->dwo_name);
+ return htab_hash_string (dwo_file->name);
}
static int
const struct dwo_file *lhs = item_lhs;
const struct dwo_file *rhs = item_rhs;
- return strcmp (lhs->dwo_name, rhs->dwo_name) == 0;
+ return strcmp (lhs->name, rhs->name) == 0;
}
/* Allocate a hash table for DWO files. */
dummy_obstack_deallocate);
}
-static hashval_t
-hash_dwo_unit (const void *item)
-{
- const struct dwo_unit *dwo_unit = item;
+/* Lookup DWO file DWO_NAME. */
+
+static void **
+lookup_dwo_file_slot (const char *dwo_name)
+{
+ struct dwo_file find_entry;
+ void **slot;
+
+ if (dwarf2_per_objfile->dwo_files == NULL)
+ dwarf2_per_objfile->dwo_files = allocate_dwo_file_hash_table ();
+
+ memset (&find_entry, 0, sizeof (find_entry));
+ find_entry.name = dwo_name;
+ slot = htab_find_slot (dwarf2_per_objfile->dwo_files, &find_entry, INSERT);
+
+ return slot;
+}
+
+static hashval_t
+hash_dwo_unit (const void *item)
+{
+ const struct dwo_unit *dwo_unit = item;
/* This drops the top 32 bits of the id, but is ok for a hash. */
return dwo_unit->signature;
dummy_obstack_deallocate);
}
-/* This function is mapped across the sections and remembers the offset and
- size of each of the DWO debugging sections we are interested in. */
-
-static void
-dwarf2_locate_dwo_sections (bfd *abfd, asection *sectp, void *dwo_file_ptr)
-{
- struct dwo_file *dwo_file = dwo_file_ptr;
- const struct dwo_section_names *names = &dwo_section_names;
-
- if (section_is_p (sectp->name, &names->abbrev_dwo))
- {
- dwo_file->sections.abbrev.asection = sectp;
- dwo_file->sections.abbrev.size = bfd_get_section_size (sectp);
- }
- else if (section_is_p (sectp->name, &names->info_dwo))
- {
- dwo_file->sections.info.asection = sectp;
- dwo_file->sections.info.size = bfd_get_section_size (sectp);
- }
- else if (section_is_p (sectp->name, &names->line_dwo))
- {
- dwo_file->sections.line.asection = sectp;
- dwo_file->sections.line.size = bfd_get_section_size (sectp);
- }
- else if (section_is_p (sectp->name, &names->loc_dwo))
- {
- dwo_file->sections.loc.asection = sectp;
- dwo_file->sections.loc.size = bfd_get_section_size (sectp);
- }
- else if (section_is_p (sectp->name, &names->macinfo_dwo))
- {
- dwo_file->sections.macinfo.asection = sectp;
- dwo_file->sections.macinfo.size = bfd_get_section_size (sectp);
- }
- else if (section_is_p (sectp->name, &names->macro_dwo))
- {
- dwo_file->sections.macro.asection = sectp;
- dwo_file->sections.macro.size = bfd_get_section_size (sectp);
- }
- else if (section_is_p (sectp->name, &names->str_dwo))
- {
- dwo_file->sections.str.asection = sectp;
- dwo_file->sections.str.size = bfd_get_section_size (sectp);
- }
- else if (section_is_p (sectp->name, &names->str_offsets_dwo))
- {
- dwo_file->sections.str_offsets.asection = sectp;
- dwo_file->sections.str_offsets.size = bfd_get_section_size (sectp);
- }
- else if (section_is_p (sectp->name, &names->types_dwo))
- {
- struct dwarf2_section_info type_section;
-
- memset (&type_section, 0, sizeof (type_section));
- type_section.asection = sectp;
- type_section.size = bfd_get_section_size (sectp);
- VEC_safe_push (dwarf2_section_info_def, dwo_file->sections.types,
- &type_section);
- }
-}
-
-/* Structure used to pass data to create_debug_info_hash_table_reader. */
+/* Structure used to pass data to create_dwo_debug_info_hash_table_reader. */
struct create_dwo_info_table_data
{
htab_t cu_htab;
};
-/* die_reader_func for create_debug_info_hash_table. */
+/* die_reader_func for create_dwo_debug_info_hash_table. */
static void
-create_debug_info_hash_table_reader (const struct die_reader_specs *reader,
- gdb_byte *info_ptr,
- struct die_info *comp_unit_die,
- int has_children,
- void *datap)
+create_dwo_debug_info_hash_table_reader (const struct die_reader_specs *reader,
+ gdb_byte *info_ptr,
+ struct die_info *comp_unit_die,
+ int has_children,
+ void *datap)
{
struct dwarf2_cu *cu = reader->cu;
struct objfile *objfile = dwarf2_per_objfile->objfile;
{
error (_("Dwarf Error: debug entry at offset 0x%x is missing"
" its dwo_id [in module %s]"),
- offset.sect_off, dwo_file->dwo_name);
+ offset.sect_off, dwo_file->name);
return;
}
" offset 0x%x, dwo_id 0x%s [in module %s]"),
offset.sect_off, dup_dwo_unit->offset.sect_off,
phex (dwo_unit->signature, sizeof (dwo_unit->signature)),
- dwo_file->dwo_name);
+ dwo_file->name);
}
else
*slot = dwo_unit;
sizeof (dwo_unit->signature)));
}
-/* Create a hash table to map DWO IDs to their CU entry in .debug_info.dwo. */
+/* Create a hash table to map DWO IDs to their CU entry in
+ .debug_info.dwo in DWO_FILE.
+ Note: This function processes DWO files only, not DWP files. */
static htab_t
-create_debug_info_hash_table (struct dwo_file *dwo_file)
+create_dwo_debug_info_hash_table (struct dwo_file *dwo_file)
{
struct objfile *objfile = dwarf2_per_objfile->objfile;
struct dwarf2_section_info *section = &dwo_file->sections.info;
init_cutu_and_read_dies_no_follow (&per_cu,
&dwo_file->sections.abbrev,
dwo_file,
- create_debug_info_hash_table_reader,
+ create_dwo_debug_info_hash_table_reader,
&create_dwo_info_table_data);
info_ptr += per_cu.length;
return cu_htab;
}
-/* Subroutine of open_dwo_file to simplify it.
+/* DWP file .debug_{cu,tu}_index section format:
+ [ref: http://gcc.gnu.org/wiki/DebugFissionDWP]
+
+ Both index sections have the same format, and serve to map a 64-bit
+ signature to a set of section numbers. Each section begins with a header,
+ followed by a hash table of 64-bit signatures, a parallel table of 32-bit
+ indexes, and a pool of 32-bit section numbers. The index sections will be
+ aligned at 8-byte boundaries in the file.
+
+ The index section header contains two unsigned 32-bit values (using the
+ byte order of the application binary):
+
+ N, the number of compilation units or type units in the index
+ M, the number of slots in the hash table
+
+ (We assume that N and M will not exceed 2^32 - 1.)
+
+ The size of the hash table, M, must be 2^k such that 2^k > 3*N/2.
+
+ The hash table begins at offset 8 in the section, and consists of an array
+ of M 64-bit slots. Each slot contains a 64-bit signature (using the byte
+ order of the application binary). Unused slots in the hash table are 0.
+ (We rely on the extreme unlikeliness of a signature being exactly 0.)
+
+ The parallel table begins immediately after the hash table
+ (at offset 8 + 8 * M from the beginning of the section), and consists of an
+ array of 32-bit indexes (using the byte order of the application binary),
+ corresponding 1-1 with slots in the hash table. Each entry in the parallel
+ table contains a 32-bit index into the pool of section numbers. For unused
+ hash table slots, the corresponding entry in the parallel table will be 0.
+
+ Given a 64-bit compilation unit signature or a type signature S, an entry
+ in the hash table is located as follows:
+
+ 1) Calculate a primary hash H = S & MASK(k), where MASK(k) is a mask with
+ the low-order k bits all set to 1.
+
+ 2) Calculate a secondary hash H' = (((S >> 32) & MASK(k)) | 1).
+
+ 3) If the hash table entry at index H matches the signature, use that
+ entry. If the hash table entry at index H is unused (all zeroes),
+ terminate the search: the signature is not present in the table.
+
+ 4) Let H = (H + H') modulo M. Repeat at Step 3.
+
+ Because M > N and H' and M are relatively prime, the search is guaranteed
+ to stop at an unused slot or find the match.
+
+ The pool of section numbers begins immediately following the hash table
+ (at offset 8 + 12 * M from the beginning of the section). The pool of
+ section numbers consists of an array of 32-bit words (using the byte order
+ of the application binary). Each item in the array is indexed starting
+ from 0. The hash table entry provides the index of the first section
+ number in the set. Additional section numbers in the set follow, and the
+ set is terminated by a 0 entry (section number 0 is not used in ELF).
+
+ In each set of section numbers, the .debug_info.dwo or .debug_types.dwo
+ section must be the first entry in the set, and the .debug_abbrev.dwo must
+ be the second entry. Other members of the set may follow in any order. */
+
+/* Create a hash table to map DWO IDs to their CU/TU entry in
+ .debug_{info,types}.dwo in DWP_FILE.
+ Returns NULL if there isn't one.
+ Note: This function processes DWP files only, not DWO files. */
+
+static struct dwp_hash_table *
+create_dwp_hash_table (struct dwp_file *dwp_file, int is_debug_types)
+{
+ struct objfile *objfile = dwarf2_per_objfile->objfile;
+ bfd *dbfd = dwp_file->dbfd;
+ char *index_ptr, *index_end;
+ struct dwarf2_section_info *index;
+ uint32_t version, nr_units, nr_slots;
+ struct dwp_hash_table *htab;
+
+ if (is_debug_types)
+ index = &dwp_file->sections.tu_index;
+ else
+ index = &dwp_file->sections.cu_index;
+
+ if (dwarf2_section_empty_p (index))
+ return NULL;
+ dwarf2_read_section (objfile, index);
+
+ index_ptr = index->buffer;
+ index_end = index_ptr + index->size;
+
+ version = read_4_bytes (dbfd, index_ptr);
+ index_ptr += 8; /* Skip the unused word. */
+ nr_units = read_4_bytes (dbfd, index_ptr);
+ index_ptr += 4;
+ nr_slots = read_4_bytes (dbfd, index_ptr);
+ index_ptr += 4;
+
+ if (version != 1)
+ {
+ error (_("Dwarf Error: unsupported DWP file version (%u)"
+ " [in module %s]"),
+ version, dwp_file->name);
+ }
+ if (nr_slots != (nr_slots & -nr_slots))
+ {
+ error (_("Dwarf Error: number of slots in DWP hash table (%u)"
+ " is not power of 2 [in module %s]"),
+ nr_slots, dwp_file->name);
+ }
+
+ htab = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwp_hash_table);
+ htab->nr_units = nr_units;
+ htab->nr_slots = nr_slots;
+ htab->hash_table = index_ptr;
+ htab->unit_table = htab->hash_table + sizeof (uint64_t) * nr_slots;
+ htab->section_pool = htab->unit_table + sizeof (uint32_t) * nr_slots;
+
+ return htab;
+}
+
+/* Update SECTIONS with the data from SECTP.
+
+ This function is like the other "locate" section routines that are
+ passed to bfd_map_over_sections, but in this context the sections to
+ read comes from the DWP hash table, not the full ELF section table.
+
+ The result is non-zero for success, or zero if an error was found. */
+
+static int
+locate_virtual_dwo_sections (asection *sectp,
+ struct virtual_dwo_sections *sections)
+{
+ const struct dwop_section_names *names = &dwop_section_names;
+
+ if (section_is_p (sectp->name, &names->abbrev_dwo))
+ {
+ /* There can be only one. */
+ if (sections->abbrev.asection != NULL)
+ return 0;
+ sections->abbrev.asection = sectp;
+ sections->abbrev.size = bfd_get_section_size (sectp);
+ }
+ else if (section_is_p (sectp->name, &names->info_dwo)
+ || section_is_p (sectp->name, &names->types_dwo))
+ {
+ /* There can be only one. */
+ if (sections->info_or_types.asection != NULL)
+ return 0;
+ sections->info_or_types.asection = sectp;
+ sections->info_or_types.size = bfd_get_section_size (sectp);
+ }
+ else if (section_is_p (sectp->name, &names->line_dwo))
+ {
+ /* There can be only one. */
+ if (sections->line.asection != NULL)
+ return 0;
+ sections->line.asection = sectp;
+ sections->line.size = bfd_get_section_size (sectp);
+ }
+ else if (section_is_p (sectp->name, &names->loc_dwo))
+ {
+ /* There can be only one. */
+ if (sections->loc.asection != NULL)
+ return 0;
+ sections->loc.asection = sectp;
+ sections->loc.size = bfd_get_section_size (sectp);
+ }
+ else if (section_is_p (sectp->name, &names->macinfo_dwo))
+ {
+ /* There can be only one. */
+ if (sections->macinfo.asection != NULL)
+ return 0;
+ sections->macinfo.asection = sectp;
+ sections->macinfo.size = bfd_get_section_size (sectp);
+ }
+ else if (section_is_p (sectp->name, &names->macro_dwo))
+ {
+ /* There can be only one. */
+ if (sections->macro.asection != NULL)
+ return 0;
+ sections->macro.asection = sectp;
+ sections->macro.size = bfd_get_section_size (sectp);
+ }
+ else if (section_is_p (sectp->name, &names->str_offsets_dwo))
+ {
+ /* There can be only one. */
+ if (sections->str_offsets.asection != NULL)
+ return 0;
+ sections->str_offsets.asection = sectp;
+ sections->str_offsets.size = bfd_get_section_size (sectp);
+ }
+ else
+ {
+ /* No other kind of section is valid. */
+ return 0;
+ }
+
+ return 1;
+}
+
+/* Create a dwo_unit object for the DWO with signature SIGNATURE.
+ HTAB is the hash table from the DWP file.
+ SECTION_INDEX is the index of the DWO in HTAB. */
+
+static struct dwo_unit *
+create_dwo_in_dwp (struct dwp_file *dwp_file,
+ const struct dwp_hash_table *htab,
+ uint32_t section_index,
+ ULONGEST signature, int is_debug_types)
+{
+ struct objfile *objfile = dwarf2_per_objfile->objfile;
+ bfd *dbfd = dwp_file->dbfd;
+ const char *kind = is_debug_types ? "TU" : "CU";
+ struct dwo_file *dwo_file;
+ struct dwo_unit *dwo_unit;
+ struct virtual_dwo_sections sections;
+ void **dwo_file_slot;
+ char *virtual_dwo_name;
+ struct dwarf2_section_info *cutu;
+ struct cleanup *cleanups;
+ int i;
+
+ if (dwarf2_read_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog, "Reading %s %u/0x%s in DWP file: %s\n",
+ kind,
+ section_index, phex (signature, sizeof (signature)),
+ dwp_file->name);
+ }
+
+ /* Fetch the sections of this DWO.
+ Put a limit on the number of sections we look for so that bad data
+ doesn't cause us to loop forever. */
+
+#define MAX_NR_DWO_SECTIONS \
+ (1 /* .debug_info or .debug_types */ \
+ + 1 /* .debug_abbrev */ \
+ + 1 /* .debug_line */ \
+ + 1 /* .debug_loc */ \
+ + 1 /* .debug_str_offsets */ \
+ + 1 /* .debug_macro */ \
+ + 1 /* .debug_macinfo */ \
+ + 1 /* trailing zero */)
+
+ memset (§ions, 0, sizeof (sections));
+ cleanups = make_cleanup (null_cleanup, 0);
+
+ for (i = 0; i < MAX_NR_DWO_SECTIONS; ++i)
+ {
+ asection *sectp;
+ uint32_t section_nr =
+ read_4_bytes (dbfd,
+ htab->section_pool
+ + (section_index + i) * sizeof (uint32_t));
+
+ if (section_nr == 0)
+ break;
+ if (section_nr >= dwp_file->num_sections)
+ {
+ error (_("Dwarf Error: bad DWP hash table, section number too large"
+ " [in module %s]"),
+ dwp_file->name);
+ }
+
+ sectp = dwp_file->elf_sections[section_nr];
+ if (! locate_virtual_dwo_sections (sectp, §ions))
+ {
+ error (_("Dwarf Error: bad DWP hash table, invalid section found"
+ " [in module %s]"),
+ dwp_file->name);
+ }
+ }
+
+ if (i < 2
+ || sections.info_or_types.asection == NULL
+ || sections.abbrev.asection == NULL)
+ {
+ error (_("Dwarf Error: bad DWP hash table, missing DWO sections"
+ " [in module %s]"),
+ dwp_file->name);
+ }
+ if (i == MAX_NR_DWO_SECTIONS)
+ {
+ error (_("Dwarf Error: bad DWP hash table, too many DWO sections"
+ " [in module %s]"),
+ dwp_file->name);
+ }
+
+ /* It's easier for the rest of the code if we fake a struct dwo_file and
+ have dwo_unit "live" in that. At least for now.
+
+ The DWP file can be made up of a random collection of CUs and TUs.
+ However, for each CU + set of TUs that came from the same original DWO
+ file, we want to combine them back into a virtual DWO file to save space
+ (fewer struct dwo_file objects to allocated). Remember that for really
+ large apps there can be on the order of 8K CUs and 200K TUs, or more. */
+
+ virtual_dwo_name =
+ xstrprintf ("virtual-dwo/%d-%d-%d-%d",
+ sections.abbrev.asection ? sections.abbrev.asection->id : 0,
+ sections.line.asection ? sections.line.asection->id : 0,
+ sections.loc.asection ? sections.loc.asection->id : 0,
+ (sections.str_offsets.asection
+ ? sections.str_offsets.asection->id
+ : 0));
+ make_cleanup (xfree, virtual_dwo_name);
+ /* Can we use an existing virtual DWO file? */
+ dwo_file_slot = lookup_dwo_file_slot (virtual_dwo_name);
+ /* Create one if necessary. */
+ if (*dwo_file_slot == NULL)
+ {
+ if (dwarf2_read_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog, "Creating virtual DWO: %s\n",
+ virtual_dwo_name);
+ }
+ dwo_file = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwo_file);
+ dwo_file->name = obstack_copy0 (&objfile->objfile_obstack,
+ virtual_dwo_name,
+ strlen (virtual_dwo_name));
+ dwo_file->sections.abbrev = sections.abbrev;
+ dwo_file->sections.line = sections.line;
+ dwo_file->sections.loc = sections.loc;
+ dwo_file->sections.macinfo = sections.macinfo;
+ dwo_file->sections.macro = sections.macro;
+ dwo_file->sections.str_offsets = sections.str_offsets;
+ /* The "str" section is global to the entire DWP file. */
+ dwo_file->sections.str = dwp_file->sections.str;
+ /* The info or types section is assigned later to dwo_unit,
+ there's no need to record it in dwo_file.
+ Also, we can't simply record type sections in dwo_file because
+ we record a pointer into the vector in dwo_unit. As we collect more
+ types we'll grow the vector and eventually have to reallocate space
+ for it, invalidating all the pointers into the current copy. */
+ *dwo_file_slot = dwo_file;
+ }
+ else
+ {
+ if (dwarf2_read_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog, "Using existing virtual DWO: %s\n",
+ virtual_dwo_name);
+ }
+ dwo_file = *dwo_file_slot;
+ }
+ do_cleanups (cleanups);
+
+ dwo_unit = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwo_unit);
+ dwo_unit->dwo_file = dwo_file;
+ dwo_unit->signature = signature;
+ dwo_unit->info_or_types_section =
+ obstack_alloc (&objfile->objfile_obstack,
+ sizeof (struct dwarf2_section_info));
+ *dwo_unit->info_or_types_section = sections.info_or_types;
+ /* offset, length, type_offset_in_tu are set later. */
+
+ return dwo_unit;
+}
+
+/* Lookup the DWO with SIGNATURE in DWP_FILE. */
+
+static struct dwo_unit *
+lookup_dwo_in_dwp (struct dwp_file *dwp_file,
+ const struct dwp_hash_table *htab,
+ ULONGEST signature, int is_debug_types)
+{
+ bfd *dbfd = dwp_file->dbfd;
+ uint32_t mask = htab->nr_slots - 1;
+ uint32_t hash = signature & mask;
+ uint32_t hash2 = ((signature >> 32) & mask) | 1;
+ unsigned int i;
+ void **slot;
+ struct dwo_unit find_dwo_cu, *dwo_cu;
+
+ memset (&find_dwo_cu, 0, sizeof (find_dwo_cu));
+ find_dwo_cu.signature = signature;
+ slot = htab_find_slot (dwp_file->loaded_cutus, &find_dwo_cu, INSERT);
+
+ if (*slot != NULL)
+ return *slot;
+
+ /* Use a for loop so that we don't loop forever on bad debug info. */
+ for (i = 0; i < htab->nr_slots; ++i)
+ {
+ ULONGEST signature_in_table;
+
+ signature_in_table =
+ read_8_bytes (dbfd, htab->hash_table + hash * sizeof (uint64_t));
+ if (signature_in_table == signature)
+ {
+ uint32_t section_index =
+ read_4_bytes (dbfd, htab->unit_table + hash * sizeof (uint32_t));
+
+ *slot = create_dwo_in_dwp (dwp_file, htab, section_index,
+ signature, is_debug_types);
+ return *slot;
+ }
+ if (signature_in_table == 0)
+ return NULL;
+ hash = (hash + hash2) & mask;
+ }
+
+ error (_("Dwarf Error: bad DWP hash table, lookup didn't terminate"
+ " [in module %s]"),
+ dwp_file->name);
+}
+
+/* Subroutine of open_dwop_file to simplify it.
Open the file specified by FILE_NAME and hand it off to BFD for
preliminary analysis. Return a newly initialized bfd *, which
includes a canonicalized copy of FILE_NAME.
+ If IS_DWP is TRUE, we're opening a DWP file, otherwise a DWO file.
In case of trouble, return NULL.
NOTE: This function is derived from symfile_bfd_open. */
static bfd *
-try_open_dwo_file (const char *file_name)
+try_open_dwop_file (const char *file_name, int is_dwp)
{
bfd *sym_bfd;
- int desc;
+ int desc, flags;
char *absolute_name;
- desc = openp (debug_file_directory, OPF_TRY_CWD_FIRST, file_name,
+ flags = OPF_TRY_CWD_FIRST;
+ if (is_dwp)
+ flags |= OPF_SEARCH_IN_PATH;
+ desc = openp (debug_file_directory, flags, file_name,
O_RDONLY | O_BINARY, &absolute_name);
if (desc < 0)
return NULL;
return sym_bfd;
}
-/* Try to open DWO file DWO_NAME.
+/* Try to open DWO/DWP file FILE_NAME.
COMP_DIR is the DW_AT_comp_dir attribute.
+ If IS_DWP is TRUE, we're opening a DWP file, otherwise a DWO file.
The result is the bfd handle of the file.
If there is a problem finding or opening the file, return NULL.
Upon success, the canonicalized path of the file is stored in the bfd,
same as symfile_bfd_open. */
static bfd *
-open_dwo_file (const char *dwo_name, const char *comp_dir)
+open_dwop_file (const char *file_name, const char *comp_dir, int is_dwp)
{
bfd *abfd;
- if (IS_ABSOLUTE_PATH (dwo_name))
- return try_open_dwo_file (dwo_name);
+ if (IS_ABSOLUTE_PATH (file_name))
+ return try_open_dwop_file (file_name, is_dwp);
/* Before trying the search path, try DWO_NAME in COMP_DIR. */
if (comp_dir != NULL)
{
- char *path_to_try = concat (comp_dir, SLASH_STRING, dwo_name, NULL);
+ char *path_to_try = concat (comp_dir, SLASH_STRING, file_name, NULL);
/* NOTE: If comp_dir is a relative path, this will also try the
search path, which seems useful. */
- abfd = try_open_dwo_file (path_to_try);
+ abfd = try_open_dwop_file (path_to_try, is_dwp);
xfree (path_to_try);
if (abfd != NULL)
return abfd;
}
- /* That didn't work, try debug-file-directory, which, despite its name,
- is a list of paths. */
+ /* That didn't work, try debug-file-directory, which, despite its name,
+ is a list of paths. */
+
+ if (*debug_file_directory == '\0')
+ return NULL;
+
+ return try_open_dwop_file (file_name, is_dwp);
+}
+
+/* This function is mapped across the sections and remembers the offset and
+ size of each of the DWO debugging sections we are interested in. */
+
+static void
+dwarf2_locate_dwo_sections (bfd *abfd, asection *sectp, void *dwo_sections_ptr)
+{
+ struct dwo_sections *dwo_sections = dwo_sections_ptr;
+ const struct dwop_section_names *names = &dwop_section_names;
+
+ if (section_is_p (sectp->name, &names->abbrev_dwo))
+ {
+ dwo_sections->abbrev.asection = sectp;
+ dwo_sections->abbrev.size = bfd_get_section_size (sectp);
+ }
+ else if (section_is_p (sectp->name, &names->info_dwo))
+ {
+ dwo_sections->info.asection = sectp;
+ dwo_sections->info.size = bfd_get_section_size (sectp);
+ }
+ else if (section_is_p (sectp->name, &names->line_dwo))
+ {
+ dwo_sections->line.asection = sectp;
+ dwo_sections->line.size = bfd_get_section_size (sectp);
+ }
+ else if (section_is_p (sectp->name, &names->loc_dwo))
+ {
+ dwo_sections->loc.asection = sectp;
+ dwo_sections->loc.size = bfd_get_section_size (sectp);
+ }
+ else if (section_is_p (sectp->name, &names->macinfo_dwo))
+ {
+ dwo_sections->macinfo.asection = sectp;
+ dwo_sections->macinfo.size = bfd_get_section_size (sectp);
+ }
+ else if (section_is_p (sectp->name, &names->macro_dwo))
+ {
+ dwo_sections->macro.asection = sectp;
+ dwo_sections->macro.size = bfd_get_section_size (sectp);
+ }
+ else if (section_is_p (sectp->name, &names->str_dwo))
+ {
+ dwo_sections->str.asection = sectp;
+ dwo_sections->str.size = bfd_get_section_size (sectp);
+ }
+ else if (section_is_p (sectp->name, &names->str_offsets_dwo))
+ {
+ dwo_sections->str_offsets.asection = sectp;
+ dwo_sections->str_offsets.size = bfd_get_section_size (sectp);
+ }
+ else if (section_is_p (sectp->name, &names->types_dwo))
+ {
+ struct dwarf2_section_info type_section;
+
+ memset (&type_section, 0, sizeof (type_section));
+ type_section.asection = sectp;
+ type_section.size = bfd_get_section_size (sectp);
+ VEC_safe_push (dwarf2_section_info_def, dwo_sections->types,
+ &type_section);
+ }
+}
+
+/* Initialize the use of the DWO file specified by DWO_NAME.
+ The result is NULL if DWO_NAME can't be found. */
+
+static struct dwo_file *
+open_and_init_dwo_file (const char *dwo_name, const char *comp_dir)
+{
+ struct objfile *objfile = dwarf2_per_objfile->objfile;
+ struct dwo_file *dwo_file;
+ bfd *dbfd;
+ struct cleanup *cleanups;
+
+ dbfd = open_dwop_file (dwo_name, comp_dir, 0);
+ if (dbfd == NULL)
+ {
+ if (dwarf2_read_debug)
+ fprintf_unfiltered (gdb_stdlog, "DWO file not found: %s\n", dwo_name);
+ return NULL;
+ }
+ dwo_file = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwo_file);
+ dwo_file->name = obstack_copy0 (&objfile->objfile_obstack,
+ dwo_name, strlen (dwo_name));
+ dwo_file->dbfd = dbfd;
+
+ cleanups = make_cleanup (free_dwo_file_cleanup, dwo_file);
+
+ bfd_map_over_sections (dbfd, dwarf2_locate_dwo_sections, &dwo_file->sections);
+
+ dwo_file->cus = create_dwo_debug_info_hash_table (dwo_file);
+
+ dwo_file->tus = create_debug_types_hash_table (dwo_file,
+ dwo_file->sections.types);
+
+ discard_cleanups (cleanups);
+
+ if (dwarf2_read_debug)
+ fprintf_unfiltered (gdb_stdlog, "DWO file found: %s\n", dwo_name);
+
+ return dwo_file;
+}
+
+/* This function is mapped across the sections and remembers the offset and
+ size of each of the DWP debugging sections we are interested in. */
+
+static void
+dwarf2_locate_dwp_sections (bfd *abfd, asection *sectp, void *dwp_file_ptr)
+{
+ struct dwp_file *dwp_file = dwp_file_ptr;
+ const struct dwop_section_names *names = &dwop_section_names;
+ unsigned int elf_section_nr = elf_section_data (sectp)->this_idx;
+
+ /* Record the ELF section number for later lookup: this is what the
+ .debug_cu_index,.debug_tu_index tables use. */
+ gdb_assert (elf_section_nr < dwp_file->num_sections);
+ dwp_file->elf_sections[elf_section_nr] = sectp;
+
+ /* Look for specific sections that we need. */
+ if (section_is_p (sectp->name, &names->str_dwo))
+ {
+ dwp_file->sections.str.asection = sectp;
+ dwp_file->sections.str.size = bfd_get_section_size (sectp);
+ }
+ else if (section_is_p (sectp->name, &names->cu_index))
+ {
+ dwp_file->sections.cu_index.asection = sectp;
+ dwp_file->sections.cu_index.size = bfd_get_section_size (sectp);
+ }
+ else if (section_is_p (sectp->name, &names->tu_index))
+ {
+ dwp_file->sections.tu_index.asection = sectp;
+ dwp_file->sections.tu_index.size = bfd_get_section_size (sectp);
+ }
+}
+
+/* Hash function for dwp_file loaded CUs/TUs. */
+
+static hashval_t
+hash_dwp_loaded_cutus (const void *item)
+{
+ const struct dwo_unit *dwo_unit = item;
+
+ /* This drops the top 32 bits of the signature, but is ok for a hash. */
+ return dwo_unit->signature;
+}
+
+/* Equality function for dwp_file loaded CUs/TUs. */
+
+static int
+eq_dwp_loaded_cutus (const void *a, const void *b)
+{
+ const struct dwo_unit *dua = a;
+ const struct dwo_unit *dub = b;
+
+ return dua->signature == dub->signature;
+}
- if (*debug_file_directory == '\0')
- return NULL;
+/* Allocate a hash table for dwp_file loaded CUs/TUs. */
- return try_open_dwo_file (dwo_name);
+static htab_t
+allocate_dwp_loaded_cutus_table (struct objfile *objfile)
+{
+ return htab_create_alloc_ex (3,
+ hash_dwp_loaded_cutus,
+ eq_dwp_loaded_cutus,
+ NULL,
+ &objfile->objfile_obstack,
+ hashtab_obstack_allocate,
+ dummy_obstack_deallocate);
}
-/* Initialize the use of the DWO file specified by DWO_NAME. */
+/* Initialize the use of the DWP file for the current objfile.
+ By convention the name of the DWP file is ${objfile}.dwp.
+ The result is NULL if it can't be found. */
-static struct dwo_file *
-init_dwo_file (const char *dwo_name, const char *comp_dir)
+static struct dwp_file *
+open_and_init_dwp_file (const char *comp_dir)
{
struct objfile *objfile = dwarf2_per_objfile->objfile;
- struct dwo_file *dwo_file = OBSTACK_ZALLOC (&objfile->objfile_obstack,
- struct dwo_file);
- bfd *abfd;
+ struct dwp_file *dwp_file;
+ char *dwp_name;
+ bfd *dbfd;
struct cleanup *cleanups;
- if (dwarf2_read_debug)
- fprintf_unfiltered (gdb_stdlog, "Reading DWO file %s:\n", dwo_name);
-
- abfd = open_dwo_file (dwo_name, comp_dir);
- if (abfd == NULL)
- return NULL;
- dwo_file->dwo_name = dwo_name;
- dwo_file->dwo_bfd = abfd;
-
- cleanups = make_cleanup (free_dwo_file_cleanup, dwo_file);
-
- bfd_map_over_sections (abfd, dwarf2_locate_dwo_sections, dwo_file);
+ dwp_name = xstrprintf ("%s.dwp", dwarf2_per_objfile->objfile->name);
+ cleanups = make_cleanup (xfree, dwp_name);
- dwo_file->cus = create_debug_info_hash_table (dwo_file);
-
- dwo_file->tus = create_debug_types_hash_table (dwo_file,
- dwo_file->sections.types);
+ dbfd = open_dwop_file (dwp_name, comp_dir, 1);
+ if (dbfd == NULL)
+ {
+ if (dwarf2_read_debug)
+ fprintf_unfiltered (gdb_stdlog, "DWP file not found: %s\n", dwp_name);
+ do_cleanups (cleanups);
+ return NULL;
+ }
+ dwp_file = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwp_file);
+ dwp_file->name = obstack_copy0 (&objfile->objfile_obstack,
+ dwp_name, strlen (dwp_name));
+ dwp_file->dbfd = dbfd;
+ do_cleanups (cleanups);
- discard_cleanups (cleanups);
+ cleanups = make_cleanup (free_dwo_file_cleanup, dwp_file);
- return dwo_file;
-}
+ /* +1: section 0 is unused */
+ dwp_file->num_sections = bfd_count_sections (dbfd) + 1;
+ dwp_file->elf_sections =
+ OBSTACK_CALLOC (&objfile->objfile_obstack,
+ dwp_file->num_sections, asection *);
-/* Lookup DWO file DWO_NAME. */
+ bfd_map_over_sections (dbfd, dwarf2_locate_dwp_sections, dwp_file);
-static struct dwo_file *
-lookup_dwo_file (char *dwo_name, const char *comp_dir)
-{
- struct dwo_file *dwo_file;
- struct dwo_file find_entry;
- void **slot;
+ dwp_file->cus = create_dwp_hash_table (dwp_file, 0);
- if (dwarf2_per_objfile->dwo_files == NULL)
- dwarf2_per_objfile->dwo_files = allocate_dwo_file_hash_table ();
+ dwp_file->tus = create_dwp_hash_table (dwp_file, 1);
- /* Have we already seen this DWO file? */
- find_entry.dwo_name = dwo_name;
- slot = htab_find_slot (dwarf2_per_objfile->dwo_files, &find_entry, INSERT);
+ dwp_file->loaded_cutus = allocate_dwp_loaded_cutus_table (objfile);
- /* If not, read it in and build a table of the DWOs it contains. */
- if (*slot == NULL)
- *slot = init_dwo_file (dwo_name, comp_dir);
+ discard_cleanups (cleanups);
- /* NOTE: This will be NULL if unable to open the file. */
- dwo_file = *slot;
+ if (dwarf2_read_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog, "DWP file found: %s\n", dwp_file->name);
+ fprintf_unfiltered (gdb_stdlog,
+ " %u CUs, %u TUs\n",
+ dwp_file->cus ? dwp_file->cus->nr_units : 0,
+ dwp_file->tus ? dwp_file->tus->nr_units : 0);
+ }
- return dwo_file;
+ return dwp_file;
}
-/* Lookup the DWO CU referenced from THIS_CU in DWO file DWO_NAME.
+/* Subroutine of lookup_dwo_comp_unit, lookup_dwo_type_unit.
+ Look up the CU/TU with signature SIGNATURE, either in DWO file DWO_NAME
+ or in the DWP file for the objfile, referenced by THIS_UNIT.
If non-NULL, comp_dir is the DW_AT_comp_dir attribute.
- SIGNATURE is the "dwo_id" of the CU (for consistency we use the same
- nomenclature as TUs).
+ IS_DEBUG_TYPES is non-zero if reading a TU, otherwise read a CU.
+
+ This is called, for example, when wanting to read a variable with a
+ complex location. Therefore we don't want to do file i/o for every call.
+ Therefore we don't want to look for a DWO file on every call.
+ Therefore we first see if we've already seen SIGNATURE in a DWP file,
+ then we check if we've already seen DWO_NAME, and only THEN do we check
+ for a DWO file.
+
The result is a pointer to the dwo_unit object or NULL if we didn't find it
- (dwo_id mismatch or couldn't find the DWO file). */
+ (dwo_id mismatch or couldn't find the DWO/DWP file). */
static struct dwo_unit *
-lookup_dwo_comp_unit (struct dwarf2_per_cu_data *this_cu,
- char *dwo_name, const char *comp_dir,
- ULONGEST signature)
+lookup_dwo_cutu (struct dwarf2_per_cu_data *this_unit,
+ const char *dwo_name, const char *comp_dir,
+ ULONGEST signature, int is_debug_types)
{
struct objfile *objfile = dwarf2_per_objfile->objfile;
+ const char *kind = is_debug_types ? "TU" : "CU";
+ void **dwo_file_slot;
struct dwo_file *dwo_file;
+ struct dwp_file *dwp_file;
- dwo_file = lookup_dwo_file (dwo_name, comp_dir);
- if (dwo_file == NULL)
- return NULL;
+ /* Have we already read SIGNATURE from a DWP file? */
- /* Look up the DWO using its signature(dwo_id). */
+ if (! dwarf2_per_objfile->dwp_checked)
+ {
+ dwarf2_per_objfile->dwp_file = open_and_init_dwp_file (comp_dir);
+ dwarf2_per_objfile->dwp_checked = 1;
+ }
+ dwp_file = dwarf2_per_objfile->dwp_file;
- if (dwo_file->cus != NULL)
+ if (dwp_file != NULL)
{
- struct dwo_unit find_dwo_cu, *dwo_cu;
+ const struct dwp_hash_table *dwp_htab =
+ is_debug_types ? dwp_file->tus : dwp_file->cus;
- find_dwo_cu.signature = signature;
- dwo_cu = htab_find (dwo_file->cus, &find_dwo_cu);
+ if (dwp_htab != NULL)
+ {
+ struct dwo_unit *dwo_cutu =
+ lookup_dwo_in_dwp (dwp_file, dwp_htab, signature, is_debug_types);
- if (dwo_cu != NULL)
- return dwo_cu;
+ if (dwo_cutu != NULL)
+ {
+ if (dwarf2_read_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog,
+ "Virtual DWO %s %s found: @%s\n",
+ kind, hex_string (signature),
+ host_address_to_string (dwo_cutu));
+ }
+ return dwo_cutu;
+ }
+ }
}
- /* We didn't find it. This must mean a dwo_id mismatch. */
-
- complaint (&symfile_complaints,
- _("Could not find DWO CU referenced by CU at offset 0x%x"
- " [in module %s]"),
- this_cu->offset.sect_off, objfile->name);
- return NULL;
-}
+ /* Have we already seen DWO_NAME? */
-/* Lookup the DWO TU referenced from THIS_TU in DWO file DWO_NAME.
- If non-NULL, comp_dir is the DW_AT_comp_dir attribute.
- The result is a pointer to the dwo_unit object or NULL if we didn't find it
- (dwo_id mismatch or couldn't find the DWO file). */
+ dwo_file_slot = lookup_dwo_file_slot (dwo_name);
+ if (*dwo_file_slot == NULL)
+ {
+ /* Read in the file and build a table of the DWOs it contains. */
+ *dwo_file_slot = open_and_init_dwo_file (dwo_name, comp_dir);
+ }
+ /* NOTE: This will be NULL if unable to open the file. */
+ dwo_file = *dwo_file_slot;
-static struct dwo_unit *
-lookup_dwo_type_unit (struct signatured_type *this_tu,
- char *dwo_name, const char *comp_dir)
-{
- struct objfile *objfile = dwarf2_per_objfile->objfile;
- struct dwo_file *dwo_file;
+ if (dwo_file != NULL)
+ {
+ htab_t htab = is_debug_types ? dwo_file->tus : dwo_file->cus;
- dwo_file = lookup_dwo_file (dwo_name, comp_dir);
- if (dwo_file == NULL)
- return NULL;
+ if (htab != NULL)
+ {
+ struct dwo_unit find_dwo_cutu, *dwo_cutu;
- /* Look up the DWO using its signature(dwo_id). */
+ memset (&find_dwo_cutu, 0, sizeof (find_dwo_cutu));
+ find_dwo_cutu.signature = signature;
+ dwo_cutu = htab_find (htab, &find_dwo_cutu);
- if (dwo_file->tus != NULL)
- {
- struct dwo_unit find_dwo_tu, *dwo_tu;
+ if (dwo_cutu != NULL)
+ {
+ if (dwarf2_read_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog, "DWO %s %s(%s) found: @%s\n",
+ kind, dwo_name, hex_string (signature),
+ host_address_to_string (dwo_cutu));
+ }
+ return dwo_cutu;
+ }
+ }
+ }
- find_dwo_tu.signature = this_tu->signature;
- dwo_tu = htab_find (dwo_file->tus, &find_dwo_tu);
+ /* We didn't find it. This could mean a dwo_id mismatch, or
+ someone deleted the DWO/DWP file, or the search path isn't set up
+ correctly to find the file. */
- if (dwo_tu != NULL)
- return dwo_tu;
+ if (dwarf2_read_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog, "DWO %s %s(%s) not found\n",
+ kind, dwo_name, hex_string (signature));
}
- /* We didn't find it. This must mean a dwo_id mismatch. */
-
complaint (&symfile_complaints,
- _("Could not find DWO TU referenced by TU at offset 0x%x"
+ _("Could not find DWO CU referenced by CU at offset 0x%x"
" [in module %s]"),
- this_tu->per_cu.offset.sect_off, objfile->name);
+ this_unit->offset.sect_off, objfile->name);
return NULL;
}
+/* Lookup the DWO CU DWO_NAME/SIGNATURE referenced from THIS_CU.
+ See lookup_dwo_cutu_unit for details. */
+
+static struct dwo_unit *
+lookup_dwo_comp_unit (struct dwarf2_per_cu_data *this_cu,
+ const char *dwo_name, const char *comp_dir,
+ ULONGEST signature)
+{
+ return lookup_dwo_cutu (this_cu, dwo_name, comp_dir, signature, 0);
+}
+
+/* Lookup the DWO TU DWO_NAME/SIGNATURE referenced from THIS_TU.
+ See lookup_dwo_cutu_unit for details. */
+
+static struct dwo_unit *
+lookup_dwo_type_unit (struct signatured_type *this_tu,
+ const char *dwo_name, const char *comp_dir)
+{
+ return lookup_dwo_cutu (&this_tu->per_cu, dwo_name, comp_dir, this_tu->signature, 1);
+}
+
/* Free all resources associated with DWO_FILE.
Close the DWO file and munmap the sections.
All memory should be on the objfile obstack. */
int ix;
struct dwarf2_section_info *section;
- gdb_assert (dwo_file->dwo_bfd != objfile->obfd);
- gdb_bfd_unref (dwo_file->dwo_bfd);
+ gdb_bfd_unref (dwo_file->dbfd);
VEC_free (dwarf2_section_info_def, dwo_file->sections.types);
}
CORE_ADDR highpc;
struct die_info *child_die;
struct attribute *attr, *call_line, *call_file;
- char *name;
+ const char *name;
CORE_ADDR baseaddr;
struct block *block;
int inlined_func = (die->tag == DW_TAG_inlined_subroutine);
lowpc, highpc, objfile);
/* For C++, set the block's scope. */
- if (cu->language == language_cplus || cu->language == language_fortran)
- cp_set_block_scope (new->name, block, &objfile->objfile_obstack,
- determine_prefix (die, cu),
- processing_has_namespace_info);
+ if ((cu->language == language_cplus || cu->language == language_fortran)
+ && cu->processing_has_namespace_info)
+ block_set_scope (block, determine_prefix (die, cu),
+ &objfile->objfile_obstack);
/* If we have address ranges, record them. */
dwarf2_record_block_ranges (die, block, baseaddr, cu);
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;
- param_symbols = new->params;
using_directives = new->using_directives;
/* If we've finished processing a top-level function, subsequent
"physname, for referencing DIE 0x%x [in module %s]"),
die->offset.sect_off, objfile->name);
else
- SET_FIELD_PHYSNAME (call_site->target, (char *) target_physname);
+ SET_FIELD_PHYSNAME (call_site->target, target_physname);
}
else
{
attr = dwarf2_attr (die, DW_AT_ranges, cu);
if (attr != NULL)
{
- unsigned int ranges_offset = DW_UNSND (attr) + cu->ranges_base;
+ /* DW_AT_ranges_base does not apply to DIEs from the DWO skeleton.
+ We take advantage of the fact that DW_AT_ranges does not appear
+ in DW_TAG_compile_unit of DWO files. */
+ int need_ranges_base = die->tag != DW_TAG_compile_unit;
+ unsigned int ranges_offset = (DW_UNSND (attr)
+ + (need_ranges_base
+ ? cu->ranges_base
+ : 0));
/* Value of the DW_AT_ranges attribute is the offset in the
.debug_ranges section. */
if (attr)
{
bfd *obfd = objfile->obfd;
+ /* DW_AT_ranges_base does not apply to DIEs from the DWO skeleton.
+ We take advantage of the fact that DW_AT_ranges does not appear
+ in DW_TAG_compile_unit of DWO files. */
+ int need_ranges_base = die->tag != DW_TAG_compile_unit;
/* The value of the DW_AT_ranges attribute is the offset of the
address range list in the .debug_ranges section. */
- unsigned long offset = DW_UNSND (attr) + cu->ranges_base;
+ unsigned long offset = (DW_UNSND (attr)
+ + (need_ranges_base ? cu->ranges_base : 0));
gdb_byte *buffer = dwarf2_per_objfile->ranges.buffer + offset;
/* For some target architectures, but not others, the
/* Not recognized as GCC. */
}
else
- cu->producer_is_gxx_lt_4_6 = major < 4 || (major == 4 && minor < 6);
+ {
+ 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)
cu->producer_is_icc = 1;
struct nextfield *new_field;
struct attribute *attr;
struct field *fp;
- char *fieldname = "";
+ const char *fieldname = "";
/* Allocate a new field list entry and link it in. */
new_field = (struct nextfield *) xmalloc (sizeof (struct nextfield));
}
}
+/* Return true if this member function is a constructor, false
+ otherwise. */
+
+static int
+dwarf2_is_constructor (struct die_info *die, struct dwarf2_cu *cu)
+{
+ const char *fieldname;
+ const char *typename;
+ int len;
+
+ if (die->parent == NULL)
+ return 0;
+
+ if (die->parent->tag != DW_TAG_structure_type
+ && die->parent->tag != DW_TAG_union_type
+ && die->parent->tag != DW_TAG_class_type)
+ return 0;
+
+ fieldname = dwarf2_name (die, cu);
+ typename = dwarf2_name (die->parent, cu);
+ if (fieldname == NULL || typename == NULL)
+ return 0;
+
+ len = strlen (fieldname);
+ return (strncmp (fieldname, typename, len) == 0
+ && (typename[len] == '\0' || typename[len] == '<'));
+}
+
/* Add a member function to the proper fieldlist. */
static void
struct fnfieldlist *flp;
int i;
struct fn_field *fnp;
- char *fieldname;
+ const char *fieldname;
struct nextfnfield *new_fnfield;
struct type *this_type;
enum dwarf_access_attribute accessibility;
if (attr && DW_UNSND (attr) != 0)
fnp->is_artificial = 1;
+ fnp->is_constructor = dwarf2_is_constructor (die, cu);
+
/* Get index in virtual function table if it is a virtual member
function. For older versions of GCC, this is an offset in the
appropriate virtual table, as specified by DW_AT_containing_type.
struct objfile *objfile = cu->objfile;
struct type *type;
struct attribute *attr;
- char *name;
+ const char *name;
/* If the definition of this type lives in .debug_types, read that type.
Don't follow DW_AT_specification though, that will take us back up
if (cu->language == language_cplus
|| cu->language == language_java)
{
- char *full_name = (char *) dwarf2_full_name (name, die, cu);
+ const char *full_name = dwarf2_full_name (name, die, cu);
/* dwarf2_full_name might have already finished building the DIE's
type. If so, there is no need to continue. */
{
/* The name is already allocated along with this objfile, so
we don't need to duplicate it for the type. */
- TYPE_TAG_NAME (type) = (char *) name;
+ TYPE_TAG_NAME (type) = name;
if (die->tag == DW_TAG_class_type)
TYPE_NAME (type) = TYPE_TAG_NAME (type);
}
TYPE_CODE (type) = TYPE_CODE_ENUM;
name = dwarf2_full_name (NULL, die, cu);
if (name != NULL)
- TYPE_TAG_NAME (type) = (char *) name;
+ TYPE_TAG_NAME (type) = name;
attr = dwarf2_attr (die, DW_AT_byte_size, cu);
if (attr)
struct field *fields = NULL;
int num_fields = 0;
int unsigned_enum = 1;
- char *name;
+ const char *name;
int flag_enum = 1;
ULONGEST mask = 0;
struct attribute *attr;
int ndim = 0;
struct cleanup *back_to;
- char *name;
+ const char *name;
element_type = die_type (die, cu);
return set_die_type (die, set_type, cu);
}
-/* First cut: install each common block member as a global variable. */
+/* A helper for read_common_block that creates a locexpr baton.
+ SYM is the symbol which we are marking as computed.
+ COMMON_DIE is the DIE for the common block.
+ COMMON_LOC is the location expression attribute for the common
+ block itself.
+ MEMBER_LOC is the location expression attribute for the particular
+ member of the common block that we are processing.
+ CU is the CU from which the above come. */
+
+static void
+mark_common_block_symbol_computed (struct symbol *sym,
+ struct die_info *common_die,
+ struct attribute *common_loc,
+ struct attribute *member_loc,
+ struct dwarf2_cu *cu)
+{
+ struct objfile *objfile = dwarf2_per_objfile->objfile;
+ struct dwarf2_locexpr_baton *baton;
+ gdb_byte *ptr;
+ unsigned int cu_off;
+ enum bfd_endian byte_order = gdbarch_byte_order (get_objfile_arch (objfile));
+ LONGEST offset = 0;
+
+ gdb_assert (common_loc && member_loc);
+ gdb_assert (attr_form_is_block (common_loc));
+ gdb_assert (attr_form_is_block (member_loc)
+ || attr_form_is_constant (member_loc));
+
+ baton = obstack_alloc (&objfile->objfile_obstack,
+ sizeof (struct dwarf2_locexpr_baton));
+ baton->per_cu = cu->per_cu;
+ gdb_assert (baton->per_cu);
+
+ baton->size = 5 /* DW_OP_call4 */ + 1 /* DW_OP_plus */;
+
+ if (attr_form_is_constant (member_loc))
+ {
+ offset = dwarf2_get_attr_constant_value (member_loc, 0);
+ baton->size += 1 /* DW_OP_addr */ + cu->header.addr_size;
+ }
+ else
+ baton->size += DW_BLOCK (member_loc)->size;
+
+ ptr = obstack_alloc (&objfile->objfile_obstack, baton->size);
+ baton->data = ptr;
+
+ *ptr++ = DW_OP_call4;
+ cu_off = common_die->offset.sect_off - cu->per_cu->offset.sect_off;
+ store_unsigned_integer (ptr, 4, byte_order, cu_off);
+ ptr += 4;
+
+ if (attr_form_is_constant (member_loc))
+ {
+ *ptr++ = DW_OP_addr;
+ store_unsigned_integer (ptr, cu->header.addr_size, byte_order, offset);
+ ptr += cu->header.addr_size;
+ }
+ else
+ {
+ /* We have to copy the data here, because DW_OP_call4 will only
+ use a DW_AT_location attribute. */
+ memcpy (ptr, DW_BLOCK (member_loc)->data, DW_BLOCK (member_loc)->size);
+ ptr += DW_BLOCK (member_loc)->size;
+ }
+
+ *ptr++ = DW_OP_plus;
+ gdb_assert (ptr - baton->data == baton->size);
+
+ SYMBOL_COMPUTED_OPS (sym) = &dwarf2_locexpr_funcs;
+ SYMBOL_LOCATION_BATON (sym) = baton;
+ SYMBOL_CLASS (sym) = LOC_COMPUTED;
+}
+
+/* Create appropriate locally-scoped variables for all the
+ DW_TAG_common_block entries. Also create a struct common_block
+ listing all such variables for `info common'. COMMON_BLOCK_DOMAIN
+ is used to sepate the common blocks name namespace from regular
+ variable names. */
static void
read_common_block (struct die_info *die, struct dwarf2_cu *cu)
{
- struct die_info *child_die;
struct attribute *attr;
- struct symbol *sym;
- CORE_ADDR base = (CORE_ADDR) 0;
attr = dwarf2_attr (die, DW_AT_location, cu);
if (attr)
/* Support the .debug_loc offsets. */
if (attr_form_is_block (attr))
{
- base = decode_locdesc (DW_BLOCK (attr), cu);
+ /* Ok. */
}
else if (attr_form_is_section_offset (attr))
{
dwarf2_complex_location_expr_complaint ();
+ attr = NULL;
}
else
{
dwarf2_invalid_attrib_class_complaint ("DW_AT_location",
"common block member");
+ attr = NULL;
}
}
+
if (die->child != NULL)
{
- child_die = die->child;
- while (child_die && child_die->tag)
- {
- LONGEST offset;
+ struct objfile *objfile = cu->objfile;
+ struct die_info *child_die;
+ size_t n_entries = 0, size;
+ struct common_block *common_block;
+ struct symbol *sym;
+ for (child_die = die->child;
+ child_die && child_die->tag;
+ child_die = sibling_die (child_die))
+ ++n_entries;
+
+ size = (sizeof (struct common_block)
+ + (n_entries - 1) * sizeof (struct symbol *));
+ common_block = obstack_alloc (&objfile->objfile_obstack, size);
+ memset (common_block->contents, 0, n_entries * sizeof (struct symbol *));
+ common_block->n_entries = 0;
+
+ for (child_die = die->child;
+ child_die && child_die->tag;
+ child_die = sibling_die (child_die))
+ {
+ /* Create the symbol in the DW_TAG_common_block block in the current
+ symbol scope. */
sym = new_symbol (child_die, NULL, cu);
- if (sym != NULL
- && handle_data_member_location (child_die, cu, &offset))
+ if (sym != NULL)
{
- SYMBOL_VALUE_ADDRESS (sym) = base + offset;
- add_symbol_to_list (sym, &global_symbols);
+ struct attribute *member_loc;
+
+ common_block->contents[common_block->n_entries++] = sym;
+
+ member_loc = dwarf2_attr (child_die, DW_AT_data_member_location,
+ cu);
+ if (member_loc)
+ {
+ /* GDB has handled this for a long time, but it is
+ not specified by DWARF. It seems to have been
+ emitted by gfortran at least as recently as:
+ http://gcc.gnu.org/bugzilla/show_bug.cgi?id=23057. */
+ complaint (&symfile_complaints,
+ _("Variable in common block has "
+ "DW_AT_data_member_location "
+ "- DIE at 0x%x [in module %s]"),
+ child_die->offset.sect_off, cu->objfile->name);
+
+ if (attr_form_is_section_offset (member_loc))
+ dwarf2_complex_location_expr_complaint ();
+ else if (attr_form_is_constant (member_loc)
+ || attr_form_is_block (member_loc))
+ {
+ if (attr)
+ mark_common_block_symbol_computed (sym, die, attr,
+ member_loc, cu);
+ }
+ else
+ dwarf2_complex_location_expr_complaint ();
+ }
}
- child_die = sibling_die (child_die);
}
+
+ sym = new_symbol (die, objfile_type (objfile)->builtin_void, cu);
+ SYMBOL_VALUE_COMMON_BLOCK (sym) = common_block;
}
}
/* Create the type. */
type = init_type (TYPE_CODE_NAMESPACE, 0, 0, NULL,
objfile);
- TYPE_NAME (type) = (char *) name;
+ TYPE_NAME (type) = name;
TYPE_TAG_NAME (type) = TYPE_NAME (type);
return set_die_type (die, type, cu);
const char *previous_prefix = determine_prefix (die, cu);
cp_add_using_directive (previous_prefix, TYPE_NAME (type), NULL,
- NULL, NULL, &objfile->objfile_obstack);
+ NULL, NULL, 0, &objfile->objfile_obstack);
}
}
read_module_type (struct die_info *die, struct dwarf2_cu *cu)
{
struct objfile *objfile = cu->objfile;
- char *module_name;
+ const char *module_name;
struct type *type;
module_name = dwarf2_name (die, cu);
if (TYPE_CODE (check_typedef (to_type)) == TYPE_CODE_METHOD)
type = lookup_methodptr_type (to_type);
+ else if (TYPE_CODE (check_typedef (to_type)) == TYPE_CODE_FUNC)
+ {
+ struct type *new_type = alloc_type (cu->objfile);
+
+ smash_to_method_type (new_type, domain, TYPE_TARGET_TYPE (to_type),
+ TYPE_FIELDS (to_type), TYPE_NFIELDS (to_type),
+ TYPE_VARARGS (to_type));
+ type = lookup_methodptr_type (new_type);
+ }
else
type = lookup_memberptr_type (to_type, domain);
return set_die_type (die, cv_type, cu);
}
+/* Handle DW_TAG_restrict_type. */
+
+static struct type *
+read_tag_restrict_type (struct die_info *die, struct dwarf2_cu *cu)
+{
+ struct type *base_type, *cv_type;
+
+ base_type = die_type (die, 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_restrict_type (base_type);
+ return set_die_type (die, cv_type, cu);
+}
+
/* Extract all information from a DW_TAG_string_type DIE and add to
the user defined type vector. It isn't really a user defined type,
but it behaves like one, with other DIE's using an AT_user_def_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;
+ TYPE_NAME (this_type) = name;
set_die_type (die, this_type, cu);
target_type = die_type (die, cu);
if (target_type != this_type)
struct type *type;
struct attribute *attr;
int encoding = 0, size = 0;
- char *name;
+ const char *name;
enum type_code code = TYPE_CODE_INT;
int type_flags = 0;
struct type *target_type = NULL;
struct attribute *attr;
LONGEST low, high;
int low_default_is_valid;
- char *name;
+ const char *name;
LONGEST negative_mask;
base_type = die_type (die, cu);
if (actual_class_name != NULL)
{
struct_pdi->name
- = obsavestring (actual_class_name,
- strlen (actual_class_name),
- &cu->objfile->objfile_obstack);
+ = obstack_copy0 (&cu->objfile->objfile_obstack,
+ actual_class_name,
+ strlen (actual_class_name));
xfree (actual_class_name);
}
break;
else
base = demangled;
- part_die->name = obsavestring (base, strlen (base),
- &cu->objfile->objfile_obstack);
+ part_die->name = obstack_copy0 (&cu->objfile->objfile_obstack,
+ base, strlen (base));
xfree (demangled);
}
}
/* Read dwarf information from a buffer. */
static unsigned int
-read_1_byte (bfd *abfd, gdb_byte *buf)
+read_1_byte (bfd *abfd, const gdb_byte *buf)
{
return bfd_get_8 (abfd, buf);
}
static int
-read_1_signed_byte (bfd *abfd, gdb_byte *buf)
+read_1_signed_byte (bfd *abfd, const gdb_byte *buf)
{
return bfd_get_signed_8 (abfd, buf);
}
static unsigned int
-read_2_bytes (bfd *abfd, gdb_byte *buf)
+read_2_bytes (bfd *abfd, const gdb_byte *buf)
{
return bfd_get_16 (abfd, buf);
}
static int
-read_2_signed_bytes (bfd *abfd, gdb_byte *buf)
+read_2_signed_bytes (bfd *abfd, const gdb_byte *buf)
{
return bfd_get_signed_16 (abfd, buf);
}
static unsigned int
-read_4_bytes (bfd *abfd, gdb_byte *buf)
+read_4_bytes (bfd *abfd, const gdb_byte *buf)
{
return bfd_get_32 (abfd, buf);
}
static int
-read_4_signed_bytes (bfd *abfd, gdb_byte *buf)
+read_4_signed_bytes (bfd *abfd, const gdb_byte *buf)
{
return bfd_get_signed_32 (abfd, buf);
}
static ULONGEST
-read_8_bytes (bfd *abfd, gdb_byte *buf)
+read_8_bytes (bfd *abfd, const gdb_byte *buf)
{
return bfd_get_64 (abfd, buf);
}
We don't need to read the entire CU(/TU).
We just need the header and top level die.
+
IWBN to use the aging mechanism to let us lazily later discard the CU.
- See however init_cutu_and_read_dies_simple. */
+ For now we skip this optimization. */
if (cu != NULL)
{
{
struct dwarf2_read_addr_index_data aidata;
- init_cutu_and_read_dies_simple (per_cu, dwarf2_read_addr_index_reader,
- &aidata);
+ /* Note: We can't use init_cutu_and_read_dies_simple here,
+ we need addr_base. */
+ init_cutu_and_read_dies (per_cu, NULL, 0, 0,
+ dwarf2_read_addr_index_reader, &aidata);
addr_base = aidata.addr_base;
addr_size = aidata.addr_size;
}
in line header LH of PST.
COMP_DIR is the compilation directory (DW_AT_comp_dir) or NULL if unknown.
If space for the result is malloc'd, it will be freed by a cleanup.
- Returns NULL if FILE_INDEX should be ignored, i.e., it is pst->filename. */
+ Returns NULL if FILE_INDEX should be ignored, i.e., it is pst->filename.
+
+ The function creates dangling cleanup registration. */
static char *
psymtab_include_file_name (const struct line_header *lh, int file_index,
static void
dwarf2_start_symtab (struct dwarf2_cu *cu,
- char *name, char *comp_dir, CORE_ADDR low_pc)
+ const char *name, const char *comp_dir, CORE_ADDR low_pc)
{
start_symtab (name, comp_dir, low_pc);
record_debugformat ("DWARF 2");
/* We assume that we're processing GCC output. */
processing_gcc_compilation = 2;
- processing_has_namespace_info = 0;
+ cu->processing_has_namespace_info = 0;
}
static void
{
struct objfile *objfile = cu->objfile;
struct symbol *sym = NULL;
- char *name;
+ const char *name;
struct attribute *attr = NULL;
struct attribute *attr2 = NULL;
CORE_ADDR baseaddr;
if (cu->language == language_fortran
&& symbol_get_demangled_name (&(sym->ginfo)) == NULL)
symbol_set_demangled_name (&(sym->ginfo),
- (char *) dwarf2_full_name (name, die, cu),
+ dwarf2_full_name (name, die, cu),
NULL);
/* Default assumptions.
{
var_decode_location (attr, sym, cu);
attr2 = dwarf2_attr (die, DW_AT_external, cu);
+
+ /* Fortran explicitly imports any global symbols to the local
+ scope by DW_TAG_common_block. */
+ if (cu->language == language_fortran && die->parent
+ && die->parent->tag == DW_TAG_common_block)
+ attr2 = NULL;
+
if (SYMBOL_CLASS (sym) == LOC_STATIC
&& SYMBOL_VALUE_ADDRESS (sym) == 0
&& !dwarf2_per_objfile->has_section_at_zero)
the minimal symbol table whenever the variable is
referenced. */
attr2 = dwarf2_attr (die, DW_AT_external, cu);
- if (attr2 && (DW_UNSND (attr2) != 0)
- && dwarf2_attr (die, DW_AT_type, cu) != NULL)
+
+ /* Fortran explicitly imports any global symbols to the local
+ scope by DW_TAG_common_block. */
+ if (cu->language == language_fortran && die->parent
+ && die->parent->tag == DW_TAG_common_block)
+ {
+ /* SYMBOL_CLASS doesn't matter here because
+ read_common_block is going to reset it. */
+ if (!suppress_add)
+ list_to_add = cu->list_in_scope;
+ }
+ else if (attr2 && (DW_UNSND (attr2) != 0)
+ && dwarf2_attr (die, DW_AT_type, cu) != NULL)
{
/* A variable with DW_AT_external is never static, but it
may be block-scoped. */
SYMBOL_CLASS (sym) = LOC_TYPEDEF;
list_to_add = &global_symbols;
break;
+ case DW_TAG_common_block:
+ SYMBOL_CLASS (sym) = LOC_COMMON_BLOCK;
+ SYMBOL_DOMAIN (sym) = COMMON_BLOCK_DOMAIN;
+ add_symbol_to_list (sym, cu->list_in_scope);
+ break;
default:
/* Not a tag we recognize. Hopefully we aren't processing
trash data, but since we must specifically ignore things
/* For the benefit of old versions of GCC, check for anonymous
namespaces based on the demangled name. */
- if (!processing_has_namespace_info
+ if (!cu->processing_has_namespace_info
&& cu->language == language_cplus)
cp_scan_for_anonymous_namespaces (sym, objfile);
}
case DW_TAG_volatile_type:
this_type = read_tag_volatile_type (die, cu);
break;
+ case DW_TAG_restrict_type:
+ this_type = read_tag_restrict_type (die, cu);
+ break;
case DW_TAG_string_type:
this_type = read_tag_string_type (die, cu);
break;
if (actual_name != NULL)
{
- char *die_name = dwarf2_name (die, cu);
+ const char *die_name = dwarf2_name (die, cu);
if (die_name != NULL
&& strcmp (die_name, actual_name) != 0)
&& actual_name[actual_name_len
- die_name_len - 1] == ':')
name =
- obsavestring (actual_name,
- actual_name_len - die_name_len - 2,
- &cu->objfile->objfile_obstack);
+ obstack_copy0 (&cu->objfile->objfile_obstack,
+ actual_name,
+ actual_name_len - die_name_len - 2);
}
}
xfree (actual_name);
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 obstack_copy0 (&cu->objfile->objfile_obstack,
+ DW_STRING (attr), &base[-1] - DW_STRING (attr));
}
/* Return the name of the namespace/class that DIE is defined within,
/* Get name of a die, return NULL if not found. */
-static char *
-dwarf2_canonicalize_name (char *name, struct dwarf2_cu *cu,
+static const char *
+dwarf2_canonicalize_name (const char *name, struct dwarf2_cu *cu,
struct obstack *obstack)
{
if (name && cu->language == language_cplus)
if (canon_name != NULL)
{
if (strcmp (canon_name, name) != 0)
- name = obsavestring (canon_name, strlen (canon_name),
- obstack);
+ name = obstack_copy0 (obstack, canon_name, strlen (canon_name));
xfree (canon_name);
}
}
/* Get name of a die, return NULL if not found. */
-static char *
+static const char *
dwarf2_name (struct die_info *die, struct dwarf2_cu *cu)
{
struct attribute *attr;
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) = obstack_copy0 (&cu->objfile->objfile_obstack,
+ demangled, strlen (demangled));
DW_STRING_IS_CANONICAL (attr) = 1;
xfree (demangled);
dwarf2_locexpr_baton->data has lifetime of PER_CU->OBJFILE. */
struct dwarf2_locexpr_baton
-dwarf2_fetch_die_location_block (cu_offset offset_in_cu,
- struct dwarf2_per_cu_data *per_cu,
- CORE_ADDR (*get_frame_pc) (void *baton),
- void *baton)
+dwarf2_fetch_die_loc_sect_off (sect_offset offset,
+ struct dwarf2_per_cu_data *per_cu,
+ CORE_ADDR (*get_frame_pc) (void *baton),
+ void *baton)
{
- sect_offset offset = { per_cu->offset.sect_off + offset_in_cu.cu_off };
struct dwarf2_cu *cu;
struct die_info *die;
struct attribute *attr;
return retval;
}
+/* Like dwarf2_fetch_die_loc_sect_off, but take a CU
+ offset. */
+
+struct dwarf2_locexpr_baton
+dwarf2_fetch_die_loc_cu_off (cu_offset offset_in_cu,
+ struct dwarf2_per_cu_data *per_cu,
+ CORE_ADDR (*get_frame_pc) (void *baton),
+ void *baton)
+{
+ sect_offset offset = { per_cu->offset.sect_off + offset_in_cu.cu_off };
+
+ return dwarf2_fetch_die_loc_sect_off (offset, per_cu, get_frame_pc, baton);
+}
+
/* Return the type of the DIE at DIE_OFFSET in the CU named by
PER_CU. */
temp_die.offset.sect_off);
if (die)
{
+ /* For .gdb_index version 7 keep track of included TUs.
+ http://sourceware.org/bugzilla/show_bug.cgi?id=15021. */
+ if (dwarf2_per_objfile->index_table != NULL
+ && dwarf2_per_objfile->index_table->version <= 7)
+ {
+ VEC_safe_push (dwarf2_per_cu_ptr,
+ (*ref_cu)->per_cu->imported_symtabs,
+ sig_cu->per_cu);
+ }
+
*ref_cu = sig_cu;
return die;
}
\f
/* Macro support. */
-/* Return the full name of file number I in *LH's file name table.
- Use COMP_DIR as the name of the current directory of the
- compilation. The result is allocated using xmalloc; the caller is
+/* Return file name relative to the compilation directory of file number I in
+ *LH's file name table. The result is allocated using xmalloc; the caller is
responsible for freeing it. */
+
static char *
-file_full_name (int file, struct line_header *lh, const char *comp_dir)
+file_file_name (int file, struct line_header *lh)
{
/* Is the file number a valid index into the line header's file name
table? Remember that file numbers start with one, not zero. */
{
struct file_entry *fe = &lh->file_names[file - 1];
- if (IS_ABSOLUTE_PATH (fe->name))
+ if (IS_ABSOLUTE_PATH (fe->name) || fe->dir_index == 0)
return xstrdup (fe->name);
- else
- {
- const char *dir;
- int dir_len;
- char *full_name;
-
- if (fe->dir_index)
- dir = lh->include_dirs[fe->dir_index - 1];
- else
- dir = comp_dir;
-
- if (dir)
- {
- dir_len = strlen (dir);
- full_name = xmalloc (dir_len + 1 + strlen (fe->name) + 1);
- strcpy (full_name, dir);
- full_name[dir_len] = '/';
- strcpy (full_name + dir_len + 1, fe->name);
- return full_name;
- }
- else
- return xstrdup (fe->name);
- }
+ return concat (lh->include_dirs[fe->dir_index - 1], SLASH_STRING,
+ fe->name, NULL);
}
else
{
won't be able to find the file by name. */
char fake_name[80];
- sprintf (fake_name, "<bad macro file number %d>", file);
+ xsnprintf (fake_name, sizeof (fake_name),
+ "<bad macro file number %d>", file);
complaint (&symfile_complaints,
_("bad file number in macro information (%d)"),
}
}
+/* Return the full name of file number I in *LH's file name table.
+ Use COMP_DIR as the name of the current directory of the
+ compilation. The result is allocated using xmalloc; the caller is
+ responsible for freeing it. */
+static char *
+file_full_name (int file, struct line_header *lh, const char *comp_dir)
+{
+ /* Is the file number a valid index into the line header's file name
+ table? Remember that file numbers start with one, not zero. */
+ if (1 <= file && file <= lh->num_file_names)
+ {
+ char *relative = file_file_name (file, lh);
+
+ if (IS_ABSOLUTE_PATH (relative) || comp_dir == NULL)
+ return relative;
+ return reconcat (relative, comp_dir, SLASH_STRING, relative, NULL);
+ }
+ else
+ return file_file_name (file, lh);
+}
+
static struct macro_source_file *
macro_start_file (int file, int line,
const char *comp_dir,
struct line_header *lh, struct objfile *objfile)
{
- /* The full name of this source file. */
- char *full_name = file_full_name (file, lh, comp_dir);
+ /* File name relative to the compilation directory of this source file. */
+ char *file_name = file_file_name (file, lh);
/* We don't create a macro table for this compilation unit
at all until we actually get a filename. */
if (! pending_macros)
pending_macros = new_macro_table (&objfile->per_bfd->storage_obstack,
- objfile->per_bfd->macro_cache);
+ objfile->per_bfd->macro_cache,
+ comp_dir);
if (! current_file)
{
/* If we have no current file, then this must be the start_file
directive for the compilation unit's main source file. */
- current_file = macro_set_main (pending_macros, full_name);
+ current_file = macro_set_main (pending_macros, file_name);
macro_define_special (pending_macros);
}
else
- current_file = macro_include (current_file, line, full_name);
+ current_file = macro_include (current_file, line, file_name);
- xfree (full_name);
+ xfree (file_name);
return current_file;
}
static void
dwarf_decode_macro_bytes (bfd *abfd, gdb_byte *mac_ptr, gdb_byte *mac_end,
struct macro_source_file *current_file,
- struct line_header *lh, char *comp_dir,
+ struct line_header *lh, const char *comp_dir,
struct dwarf2_section_info *section,
int section_is_gnu, int section_is_dwz,
unsigned int offset_size,
static void
dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset,
- char *comp_dir, int section_is_gnu)
+ const char *comp_dir, int section_is_gnu)
{
struct objfile *objfile = dwarf2_per_objfile->objfile;
struct line_header *lh = cu->line_header;
for (ix = 0; ix < dwarf2_per_objfile->n_comp_units; ++ix)
VEC_free (dwarf2_per_cu_ptr,
- dwarf2_per_objfile->all_comp_units[ix]->s.imported_symtabs);
+ dwarf2_per_objfile->all_comp_units[ix]->imported_symtabs);
+
+ for (ix = 0; ix < dwarf2_per_objfile->n_type_units; ++ix)
+ VEC_free (dwarf2_per_cu_ptr,
+ dwarf2_per_objfile->all_type_units[ix]->per_cu.imported_symtabs);
VEC_free (dwarf2_section_info_def, data->types);
total_len = size_of_contents;
/* The version number. */
- val = MAYBE_SWAP (7);
+ val = MAYBE_SWAP (8);
obstack_grow (&contents, &val, sizeof (val));
/* The offset of the CU list from the start of the file. */