/* DWARF 2 debugging format support for GDB.
- Copyright (C) 1994-2013 Free Software Foundation, Inc.
+ Copyright (C) 1994-2014 Free Software Foundation, Inc.
Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology,
Inc. with support from Florida State University (under contract
#include "typeprint.h"
#include "jv-lang.h"
#include "psympriv.h"
-#include "exceptions.h"
-#include "gdb_stat.h"
+#include <sys/stat.h>
#include "completer.h"
#include "vec.h"
#include "c-lang.h"
#include "f-lang.h"
#include "source.h"
#include "filestuff.h"
+#include "build-id.h"
#include <fcntl.h>
-#include "gdb_string.h"
-#include "gdb_assert.h"
#include <sys/types.h>
typedef struct symbol *symbolp;
DEF_VEC_P (symbolp);
-/* When non-zero, print basic high level tracing messages.
+/* When == 1, print basic high level tracing messages.
+ When > 1, be more verbose.
This is in contrast to the low level DIE reading of dwarf2_die_debug. */
-static int dwarf2_read_debug = 0;
+static unsigned int dwarf2_read_debug = 0;
/* When non-zero, dump DIEs after they are read in. */
static unsigned int dwarf2_die_debug = 0;
static int dwarf2_locexpr_block_index;
static int dwarf2_loclist_block_index;
+/* A descriptor for dwarf sections.
+
+ S.ASECTION, SIZE are typically initialized when the objfile is first
+ scanned. BUFFER, READIN are filled in later when the section is read.
+ If the section contained compressed data then SIZE is updated to record
+ the uncompressed size of the section.
+
+ DWP file format V2 introduces a wrinkle that is easiest to handle by
+ creating the concept of virtual sections contained within a real section.
+ In DWP V2 the sections of the input DWO files are concatenated together
+ into one section, but section offsets are kept relative to the original
+ input section.
+ If this is a virtual dwp-v2 section, S.CONTAINING_SECTION is a backlink to
+ the real section this "virtual" section is contained in, and BUFFER,SIZE
+ describe the virtual section. */
+
struct dwarf2_section_info
{
- asection *asection;
+ union
+ {
+ /* If this is a real section, the bfd section. */
+ asection *asection;
+ /* If this is a virtual section, pointer to the containing ("real")
+ section. */
+ struct dwarf2_section_info *containing_section;
+ } s;
+ /* Pointer to section data, only valid if readin. */
const gdb_byte *buffer;
+ /* The size of the section, real or virtual. */
bfd_size_type size;
+ /* If this is a virtual section, the offset in the real section.
+ Only valid if is_virtual. */
+ bfd_size_type virtual_offset;
/* True if we have tried to read this section. */
- int readin;
+ char readin;
+ /* True if this is a virtual section, False otherwise.
+ This specifies which of s.asection and s.containing_section to use. */
+ char is_virtual;
};
typedef struct dwarf2_section_info dwarf2_section_info_def;
/* The number of .debug_types-related CUs. */
int n_type_units;
+ /* The number of elements allocated in all_type_units.
+ If there are skeleton-less TUs, we add them to all_type_units lazily. */
+ int n_allocated_type_units;
+
/* The .debug_types-related CUs (TUs).
This is stored in malloc space because we may realloc it. */
struct signatured_type **all_type_units;
- /* The number of entries in all_type_unit_groups. */
- int n_type_unit_groups;
-
- /* Table of type unit groups.
- This exists to make it easy to iterate over all CUs and TU groups. */
- struct type_unit_group **all_type_unit_groups;
-
/* Table of struct type_unit_group objects.
The hash key is the DW_AT_stmt_list value. */
htab_t type_unit_groups;
int nr_symtabs;
int nr_symtab_sharers;
int nr_stmt_less_type_units;
+ int nr_all_type_units_reallocs;
} tu_stats;
/* A chain of compilation units that are currently read in, so that
/* The DW_AT_addr_base attribute if present, zero otherwise
(zero is a valid value though).
- Note this value comes from the stub CU/TU's DIE. */
+ Note this value comes from the Fission stub CU/TU's DIE. */
ULONGEST addr_base;
/* The DW_AT_ranges_base attribute if present, zero otherwise
(zero is a valid value though).
- Note this value comes from the stub CU/TU's DIE.
+ Note this value comes from the Fission stub CU/TU's DIE.
Also note that the value is zero in the non-DWO case so this value can
be used without needing to know whether DWO files are in use or not.
N.B. This does not apply to DW_AT_ranges appearing in
However we can enter this file with just a "per_cu" handle. */
struct objfile *objfile;
- /* When using partial symbol tables, the 'psymtab' field is active.
- Otherwise the 'quick' field is active. */
+ /* When dwarf2_per_objfile->using_index is true, the 'quick' field
+ is active. Otherwise, the 'psymtab' field is active. */
union
{
/* The partial symbol table associated with this compilation unit,
struct symtab **symtabs;
};
-/* These sections are what may appear in a DWO file. */
+/* These sections are what may appear in a (real or virtual) DWO file. */
struct dwo_sections
{
/* The section this CU/TU lives in, in the DWO file. */
struct dwarf2_section_info *section;
- /* Same as dwarf2_per_cu_data:{offset,length} but for the DWO section. */
+ /* Same as dwarf2_per_cu_data:{offset,length} but in the DWO section. */
sect_offset offset;
unsigned int length;
cu_offset type_offset_in_tu;
};
+/* include/dwarf2.h defines the DWP section codes.
+ It defines a max value but it doesn't define a min value, which we
+ use for error checking, so provide one. */
+
+enum dwp_v2_section_ids
+{
+ DW_SECT_MIN = 1
+};
+
/* Data for one DWO file.
This includes virtual DWO files (a virtual DWO file is a DWO file as it
This is unused(NULL) for virtual DWO files where we use dwp_file.dbfd. */
bfd *dbfd;
- /* Section info for this file. */
+ /* The sections that make up this DWO file.
+ Remember that for virtual DWO files in DWP V2, these are virtual
+ sections (for lack of a better name). */
struct dwo_sections sections;
/* The CU in the file.
struct dwp_sections
{
+ /* These are used by both DWP version 1 and 2. */
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 are only used by DWP version 2 files.
+ In DWP version 1 the .debug_info.dwo, .debug_types.dwo, and other
+ sections are referenced by section number, and are not recorded here.
+ In DWP version 2 there is at most one copy of all these sections, each
+ section being (effectively) comprised of the concatenation of all of the
+ individual sections that exist in the version 1 format.
+ To keep the code simple we treat each of these concatenated pieces as a
+ section itself (a virtual section?). */
+ 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_offsets;
+ struct dwarf2_section_info types;
};
-/* These sections are what may appear in a virtual DWO file. */
+/* These sections are what may appear in a virtual DWO file in DWP version 1.
+ A virtual DWO file is a DWO file as it appears in a DWP file. */
-struct virtual_dwo_sections
+struct virtual_v1_dwo_sections
{
struct dwarf2_section_info abbrev;
struct dwarf2_section_info line;
struct dwarf2_section_info info_or_types;
};
+/* Similar to virtual_v1_dwo_sections, but for DWP version 2.
+ In version 2, the sections of the DWO files are concatenated together
+ and stored in one section of that name. Thus each ELF section contains
+ several "virtual" sections. */
+
+struct virtual_v2_dwo_sections
+{
+ bfd_size_type abbrev_offset;
+ bfd_size_type abbrev_size;
+
+ bfd_size_type line_offset;
+ bfd_size_type line_size;
+
+ bfd_size_type loc_offset;
+ bfd_size_type loc_size;
+
+ bfd_size_type macinfo_offset;
+ bfd_size_type macinfo_size;
+
+ bfd_size_type macro_offset;
+ bfd_size_type macro_size;
+
+ bfd_size_type str_offsets_offset;
+ bfd_size_type str_offsets_size;
+
+ /* Each DWP hash table entry records one CU or one TU.
+ That is recorded here, and copied to dwo_unit.section. */
+ bfd_size_type info_or_types_offset;
+ bfd_size_type info_or_types_size;
+};
+
/* Contents of DWP hash tables. */
struct dwp_hash_table
{
+ uint32_t version, nr_columns;
uint32_t nr_units, nr_slots;
- const gdb_byte *hash_table, *unit_table, *section_pool;
+ const gdb_byte *hash_table, *unit_table;
+ union
+ {
+ struct
+ {
+ const gdb_byte *indices;
+ } v1;
+ struct
+ {
+ /* This is indexed by column number and gives the id of the section
+ in that column. */
+#define MAX_NR_V2_DWO_SECTIONS \
+ (1 /* .debug_info or .debug_types */ \
+ + 1 /* .debug_abbrev */ \
+ + 1 /* .debug_line */ \
+ + 1 /* .debug_loc */ \
+ + 1 /* .debug_str_offsets */ \
+ + 1 /* .debug_macro or .debug_macinfo */)
+ int section_ids[MAX_NR_V2_DWO_SECTIONS];
+ const gdb_byte *offsets;
+ const gdb_byte *sizes;
+ } v2;
+ } section_pool;
};
/* Data for one DWP file. */
/* Name of the file. */
const char *name;
+ /* File format version. */
+ int version;
+
/* The bfd. */
bfd *dbfd;
/* 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;
+ /* Tables of loaded CUs/TUs. Each entry is a struct dwo_unit *. */
+ htab_t loaded_cus;
+ htab_t loaded_tus;
- /* Table to map ELF section numbers to their sections. */
+ /* Table to map ELF section numbers to their sections.
+ This is only needed for the DWP V1 file format. */
unsigned int num_sections;
asection **elf_sections;
};
type derived from this DIE. */
unsigned char building_fullname : 1;
+ /* True if this die is in process. PR 16581. */
+ unsigned char in_process : 1;
+
/* Abbrev number */
unsigned int abbrev;
static void add_partial_namespace (struct partial_die_info *pdi,
CORE_ADDR *lowpc, CORE_ADDR *highpc,
- int need_pc, struct dwarf2_cu *cu);
+ int set_addrmap, struct dwarf2_cu *cu);
static void add_partial_module (struct partial_die_info *pdi, CORE_ADDR *lowpc,
- CORE_ADDR *highpc, int need_pc,
+ CORE_ADDR *highpc, int set_addrmap,
struct dwarf2_cu *cu);
static void add_partial_enumeration (struct partial_die_info *enum_pdi,
unsigned int *);
static const char *read_str_index (const struct die_reader_specs *reader,
- struct dwarf2_cu *cu, ULONGEST str_index);
+ ULONGEST str_index);
static void set_cu_language (unsigned int, struct dwarf2_cu *);
static void dwarf_decode_lines (struct line_header *, const char *,
struct dwarf2_cu *, struct partial_symtab *,
- int);
+ CORE_ADDR);
static void dwarf2_start_subfile (const char *, const char *, const char *);
static void read_import_statement (struct die_info *die, struct dwarf2_cu *);
+static int read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu);
+
static struct type *read_module_type (struct die_info *die,
struct dwarf2_cu *cu);
static void read_signatured_type (struct signatured_type *);
-static struct type_unit_group *get_type_unit_group
- (struct dwarf2_cu *, const struct attribute *);
-
-static void build_type_unit_groups (die_reader_func_ftype *, void *);
-
/* memory allocation interface */
static struct dwarf_block *dwarf_alloc_block (struct dwarf2_cu *);
#define MAYBE_SWAP(V) (V)
#endif /* WORDS_BIGENDIAN */
+/* Read the given attribute value as an address, taking the attribute's
+ form into account. */
+
+static CORE_ADDR
+attr_value_as_address (struct attribute *attr)
+{
+ CORE_ADDR addr;
+
+ if (attr->form != DW_FORM_addr && attr->form != DW_FORM_GNU_addr_index)
+ {
+ /* Aside from a few clearly defined exceptions, attributes that
+ contain an address must always be in DW_FORM_addr form.
+ Unfortunately, some compilers happen to be violating this
+ requirement by encoding addresses using other forms, such
+ as DW_FORM_data4 for example. For those broken compilers,
+ we try to do our best, without any guarantee of success,
+ to interpret the address correctly. It would also be nice
+ to generate a complaint, but that would require us to maintain
+ a list of legitimate cases where a non-address form is allowed,
+ as well as update callers to pass in at least the CU's DWARF
+ version. This is more overhead than what we're willing to
+ expand for a pretty rare case. */
+ addr = DW_UNSND (attr);
+ }
+ else
+ addr = DW_ADDR (attr);
+
+ return addr;
+}
+
/* The suffix for an index file. */
#define INDEX_SUFFIX ".gdb-index"
(void *) names);
dwarf2_per_objfile->objfile = objfile;
}
- return (dwarf2_per_objfile->info.asection != NULL
- && dwarf2_per_objfile->abbrev.asection != NULL);
+ return (!dwarf2_per_objfile->info.is_virtual
+ && dwarf2_per_objfile->info.s.asection != NULL
+ && !dwarf2_per_objfile->abbrev.is_virtual
+ && dwarf2_per_objfile->abbrev.s.asection != NULL);
+}
+
+/* Return the containing section of virtual section SECTION. */
+
+static struct dwarf2_section_info *
+get_containing_section (const struct dwarf2_section_info *section)
+{
+ gdb_assert (section->is_virtual);
+ return section->s.containing_section;
}
/* Return the bfd owner of SECTION. */
static struct bfd *
get_section_bfd_owner (const struct dwarf2_section_info *section)
{
- return section->asection->owner;
+ if (section->is_virtual)
+ {
+ section = get_containing_section (section);
+ gdb_assert (!section->is_virtual);
+ }
+ return section->s.asection->owner;
}
/* Return the bfd section of SECTION.
static asection *
get_section_bfd_section (const struct dwarf2_section_info *section)
{
- return section->asection;
+ if (section->is_virtual)
+ {
+ section = get_containing_section (section);
+ gdb_assert (!section->is_virtual);
+ }
+ return section->s.asection;
}
/* Return the name of SECTION. */
}
/* Return the flags of SECTION.
- SECTION must exist. */
+ SECTION (or containing section if this is a virtual section) must exist. */
static int
get_section_flags (const struct dwarf2_section_info *section)
}
else if (section_is_p (sectp->name, &names->info))
{
- dwarf2_per_objfile->info.asection = sectp;
+ dwarf2_per_objfile->info.s.asection = sectp;
dwarf2_per_objfile->info.size = bfd_get_section_size (sectp);
}
else if (section_is_p (sectp->name, &names->abbrev))
{
- dwarf2_per_objfile->abbrev.asection = sectp;
+ dwarf2_per_objfile->abbrev.s.asection = sectp;
dwarf2_per_objfile->abbrev.size = bfd_get_section_size (sectp);
}
else if (section_is_p (sectp->name, &names->line))
{
- dwarf2_per_objfile->line.asection = sectp;
+ dwarf2_per_objfile->line.s.asection = sectp;
dwarf2_per_objfile->line.size = bfd_get_section_size (sectp);
}
else if (section_is_p (sectp->name, &names->loc))
{
- dwarf2_per_objfile->loc.asection = sectp;
+ dwarf2_per_objfile->loc.s.asection = sectp;
dwarf2_per_objfile->loc.size = bfd_get_section_size (sectp);
}
else if (section_is_p (sectp->name, &names->macinfo))
{
- dwarf2_per_objfile->macinfo.asection = sectp;
+ dwarf2_per_objfile->macinfo.s.asection = sectp;
dwarf2_per_objfile->macinfo.size = bfd_get_section_size (sectp);
}
else if (section_is_p (sectp->name, &names->macro))
{
- dwarf2_per_objfile->macro.asection = sectp;
+ dwarf2_per_objfile->macro.s.asection = sectp;
dwarf2_per_objfile->macro.size = bfd_get_section_size (sectp);
}
else if (section_is_p (sectp->name, &names->str))
{
- dwarf2_per_objfile->str.asection = sectp;
+ dwarf2_per_objfile->str.s.asection = sectp;
dwarf2_per_objfile->str.size = bfd_get_section_size (sectp);
}
else if (section_is_p (sectp->name, &names->addr))
{
- dwarf2_per_objfile->addr.asection = sectp;
+ dwarf2_per_objfile->addr.s.asection = sectp;
dwarf2_per_objfile->addr.size = bfd_get_section_size (sectp);
}
else if (section_is_p (sectp->name, &names->frame))
{
- dwarf2_per_objfile->frame.asection = sectp;
+ dwarf2_per_objfile->frame.s.asection = sectp;
dwarf2_per_objfile->frame.size = bfd_get_section_size (sectp);
}
else if (section_is_p (sectp->name, &names->eh_frame))
{
- dwarf2_per_objfile->eh_frame.asection = sectp;
+ dwarf2_per_objfile->eh_frame.s.asection = sectp;
dwarf2_per_objfile->eh_frame.size = bfd_get_section_size (sectp);
}
else if (section_is_p (sectp->name, &names->ranges))
{
- dwarf2_per_objfile->ranges.asection = sectp;
+ dwarf2_per_objfile->ranges.s.asection = sectp;
dwarf2_per_objfile->ranges.size = bfd_get_section_size (sectp);
}
else if (section_is_p (sectp->name, &names->types))
struct dwarf2_section_info type_section;
memset (&type_section, 0, sizeof (type_section));
- type_section.asection = sectp;
+ type_section.s.asection = sectp;
type_section.size = bfd_get_section_size (sectp);
VEC_safe_push (dwarf2_section_info_def, dwarf2_per_objfile->types,
}
else if (section_is_p (sectp->name, &names->gdb_index))
{
- dwarf2_per_objfile->gdb_index.asection = sectp;
+ dwarf2_per_objfile->gdb_index.s.asection = sectp;
dwarf2_per_objfile->gdb_index.size = bfd_get_section_size (sectp);
}
or not present. */
static int
-dwarf2_section_empty_p (struct dwarf2_section_info *info)
+dwarf2_section_empty_p (const struct dwarf2_section_info *section)
{
- return info->asection == NULL || info->size == 0;
+ if (section->is_virtual)
+ return section->size == 0;
+ return section->s.asection == NULL || section->size == 0;
}
/* Read the contents of the section INFO.
asection *sectp;
bfd *abfd;
gdb_byte *buf, *retbuf;
- unsigned char header[4];
if (info->readin)
return;
sectp = get_section_bfd_section (info);
+ /* If this is a virtual section we need to read in the real one first. */
+ if (info->is_virtual)
+ {
+ struct dwarf2_section_info *containing_section =
+ get_containing_section (info);
+
+ gdb_assert (sectp != NULL);
+ if ((sectp->flags & SEC_RELOC) != 0)
+ {
+ error (_("Dwarf Error: DWP format V2 with relocations is not"
+ " supported in section %s [in module %s]"),
+ get_section_name (info), get_section_file_name (info));
+ }
+ dwarf2_read_section (objfile, containing_section);
+ /* Other code should have already caught virtual sections that don't
+ fit. */
+ gdb_assert (info->virtual_offset + info->size
+ <= containing_section->size);
+ /* If the real section is empty or there was a problem reading the
+ section we shouldn't get here. */
+ gdb_assert (containing_section->buffer != NULL);
+ info->buffer = containing_section->buffer + info->virtual_offset;
+ return;
+ }
+
/* If the section has relocations, we must read it ourselves.
Otherwise we attach it to the BFD. */
if ((sectp->flags & SEC_RELOC) == 0)
if (bfd_seek (abfd, sectp->filepos, SEEK_SET) != 0
|| bfd_bread (buf, info->size, abfd) != info->size)
- error (_("Dwarf Error: Can't read DWARF data from '%s'"),
- bfd_get_filename (abfd));
+ {
+ error (_("Dwarf Error: Can't read DWARF data"
+ " in section %s [in module %s]"),
+ bfd_section_name (abfd, sectp), bfd_get_filename (abfd));
+ }
}
/* A helper function that returns the size of a section in a safe way.
is ELF-only (at the time of writing). */
if (section_is_p (sectp->name, &dwarf2_elf_names.abbrev))
{
- dwz_file->abbrev.asection = sectp;
+ dwz_file->abbrev.s.asection = sectp;
dwz_file->abbrev.size = bfd_get_section_size (sectp);
}
else if (section_is_p (sectp->name, &dwarf2_elf_names.info))
{
- dwz_file->info.asection = sectp;
+ dwz_file->info.s.asection = sectp;
dwz_file->info.size = bfd_get_section_size (sectp);
}
else if (section_is_p (sectp->name, &dwarf2_elf_names.str))
{
- dwz_file->str.asection = sectp;
+ dwz_file->str.s.asection = sectp;
dwz_file->str.size = bfd_get_section_size (sectp);
}
else if (section_is_p (sectp->name, &dwarf2_elf_names.line))
{
- dwz_file->line.asection = sectp;
+ dwz_file->line.s.asection = sectp;
dwz_file->line.size = bfd_get_section_size (sectp);
}
else if (section_is_p (sectp->name, &dwarf2_elf_names.macro))
{
- dwz_file->macro.asection = sectp;
+ dwz_file->macro.s.asection = sectp;
dwz_file->macro.size = bfd_get_section_size (sectp);
}
else if (section_is_p (sectp->name, &dwarf2_elf_names.gdb_index))
{
- dwz_file->gdb_index.asection = sectp;
+ dwz_file->gdb_index.s.asection = sectp;
dwz_file->gdb_index.size = bfd_get_section_size (sectp);
}
}
struct cleanup *cleanup;
const char *filename;
struct dwz_file *result;
- unsigned long buildid;
+ bfd_size_type buildid_len_arg;
+ size_t buildid_len;
+ bfd_byte *buildid;
if (dwarf2_per_objfile->dwz_file != NULL)
return dwarf2_per_objfile->dwz_file;
bfd_set_error (bfd_error_no_error);
data = bfd_get_alt_debug_link_info (dwarf2_per_objfile->objfile->obfd,
- &buildid);
+ &buildid_len_arg, &buildid);
if (data == NULL)
{
if (bfd_get_error () == bfd_error_no_error)
bfd_errmsg (bfd_get_error ()));
}
cleanup = make_cleanup (xfree, data);
+ make_cleanup (xfree, buildid);
+
+ buildid_len = (size_t) buildid_len_arg;
filename = (const char *) data;
if (!IS_ABSOLUTE_PATH (filename))
filename = rel;
}
- /* The format is just a NUL-terminated file name, followed by the
- build-id. For now, though, we ignore the build-id. */
+ /* First try the file name given in the section. If that doesn't
+ work, try to use the build-id instead. */
dwz_bfd = gdb_bfd_open (filename, gnutarget, -1);
- if (dwz_bfd == NULL)
- error (_("could not read '%s': %s"), filename,
- bfd_errmsg (bfd_get_error ()));
-
- if (!bfd_check_format (dwz_bfd, bfd_object))
+ if (dwz_bfd != NULL)
{
- gdb_bfd_unref (dwz_bfd);
- error (_("file '%s' was not usable: %s"), filename,
- bfd_errmsg (bfd_get_error ()));
+ if (!build_id_verify (dwz_bfd, buildid_len, buildid))
+ {
+ gdb_bfd_unref (dwz_bfd);
+ dwz_bfd = NULL;
+ }
}
+ if (dwz_bfd == NULL)
+ dwz_bfd = build_id_to_debug_bfd (buildid_len, buildid);
+
+ if (dwz_bfd == NULL)
+ error (_("could not find '.gnu_debugaltlink' file for %s"),
+ objfile_name (dwarf2_per_objfile->objfile));
+
result = OBSTACK_ZALLOC (&dwarf2_per_objfile->objfile->objfile_obstack,
struct dwz_file);
result->dwz_bfd = dwz_bfd;
do_cleanups (cleanup);
+ gdb_bfd_record_inclusion (dwarf2_per_objfile->objfile->obfd, dwz_bfd);
dwarf2_per_objfile->dwz_file = result;
return result;
}
return per_cu->v.quick->symtab;
}
-/* Return the CU given its index.
+/* Return the CU/TU given its index.
This is intended for loops like:
for (i = 0; i < (dwarf2_per_objfile->n_comp_units
+ dwarf2_per_objfile->n_type_units); ++i)
{
- struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
+ struct dwarf2_per_cu_data *per_cu = dw2_get_cutu (i);
...;
}
*/
static struct dwarf2_per_cu_data *
-dw2_get_cu (int index)
+dw2_get_cutu (int index)
{
if (index >= dwarf2_per_objfile->n_comp_units)
{
return dwarf2_per_objfile->all_comp_units[index];
}
-/* Return the primary CU given its index.
- The difference between this function and dw2_get_cu is in the handling
- of type units (TUs). Here we return the type_unit_group object.
-
- This is intended for loops like:
-
- for (i = 0; i < (dwarf2_per_objfile->n_comp_units
- + dwarf2_per_objfile->n_type_unit_groups); ++i)
- {
- struct dwarf2_per_cu_data *per_cu = dw2_get_primary_cu (i);
-
- ...;
- }
-*/
+/* Return the CU given its index.
+ This differs from dw2_get_cutu in that it's for when you know INDEX
+ refers to a CU. */
static struct dwarf2_per_cu_data *
-dw2_get_primary_cu (int index)
+dw2_get_cu (int index)
{
- if (index >= dwarf2_per_objfile->n_comp_units)
- {
- index -= dwarf2_per_objfile->n_comp_units;
- gdb_assert (index < dwarf2_per_objfile->n_type_unit_groups);
- return &dwarf2_per_objfile->all_type_unit_groups[index]->per_cu;
- }
+ gdb_assert (index >= 0 && index < dwarf2_per_objfile->n_comp_units);
return dwarf2_per_objfile->all_comp_units[index];
}
offset_type i;
htab_t sig_types_hash;
- dwarf2_per_objfile->n_type_units = elements / 3;
+ dwarf2_per_objfile->n_type_units
+ = dwarf2_per_objfile->n_allocated_type_units
+ = elements / 3;
dwarf2_per_objfile->all_type_units
= xmalloc (dwarf2_per_objfile->n_type_units
* sizeof (struct signatured_type *));
}
addrmap_set_empty (mutable_map, lo + baseaddr, hi + baseaddr - 1,
- dw2_get_cu (cu_index));
+ dw2_get_cutu (cu_index));
}
objfile->psymtabs_addrmap = addrmap_create_fixed (mutable_map,
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. */
+ of the TU (for symbols coming from TUs),
+ http://sourceware.org/bugzilla/show_bug.cgi?id=15021.
+ Plus gold-generated indices can have duplicate entries for global symbols,
+ http://sourceware.org/bugzilla/show_bug.cgi?id=15646.
+ These are just performance bugs, and we can't distinguish gdb-generated
+ indices from gold-generated ones, so issue no warning here. */
/* Indexes with higher version than the one supported by GDB may be no
longer backward compatible. */
{
if (qfn->real_names == NULL)
qfn->real_names = OBSTACK_CALLOC (&objfile->objfile_obstack,
- qfn->num_file_names, sizeof (char *));
+ qfn->num_file_names, const char *);
if (qfn->real_names[index] == NULL)
qfn->real_names[index] = gdb_realpath (qfn->file_names[index]);
dw2_setup (objfile);
index = dwarf2_per_objfile->n_comp_units - 1;
- return dw2_instantiate_symtab (dw2_get_cu (index));
+ return dw2_instantiate_symtab (dw2_get_cutu (index));
}
/* Traversal function for dw2_forget_cached_source_info. */
for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
{
int j;
- struct dwarf2_per_cu_data *per_cu = dw2_get_primary_cu (i);
+ struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
struct quick_file_names *file_data;
/* We only need to look at symtabs not already expanded. */
int next;
/* The number of elements in VEC, or zero if there is no match. */
int length;
+ /* Have we seen a global version of the symbol?
+ If so we can ignore all further global instances.
+ This is to work around gold/15646, inefficient gold-generated
+ indices. */
+ int global_seen;
};
/* Initialize the index symtab iterator ITER.
iter->block_index = block_index;
iter->domain = domain;
iter->next = 0;
+ iter->global_seen = 0;
if (find_slot_in_mapped_hash (index, name, &iter->vec))
iter->length = MAYBE_SWAP (*iter->vec);
continue;
}
- per_cu = dw2_get_cu (cu_index);
+ per_cu = dw2_get_cutu (cu_index);
/* Skip if already read in. */
if (per_cu->v.quick->symtab)
continue;
- if (attrs_valid
- && iter->want_specific_block
- && want_static != is_static)
- continue;
+ /* Check static vs global. */
+ if (attrs_valid)
+ {
+ if (iter->want_specific_block
+ && want_static != is_static)
+ continue;
+ /* Work around gold/15646. */
+ if (!is_static && iter->global_seen)
+ continue;
+ if (!is_static)
+ iter->global_seen = 1;
+ }
/* Only check the symbol's kind if it has one. */
if (attrs_valid)
information (but NAME might contain it). */
if (stab->primary)
{
- struct blockvector *bv = BLOCKVECTOR (stab);
+ const struct blockvector *bv = BLOCKVECTOR (stab);
struct block *block = BLOCKVECTOR_BLOCK (bv, block_index);
sym = lookup_block_symbol (block, name, domain);
count = 0;
for (i = 0; i < total; ++i)
{
- struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
+ struct dwarf2_per_cu_data *per_cu = dw2_get_cutu (i);
if (!per_cu->v.quick->symtab)
++count;
for (i = 0; i < (dwarf2_per_objfile->n_comp_units
+ dwarf2_per_objfile->n_type_units); ++i)
{
- struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
+ struct dwarf2_per_cu_data *per_cu = dw2_get_cutu (i);
dw2_instantiate_symtab (per_cu);
}
for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
{
int j;
- struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
+ struct dwarf2_per_cu_data *per_cu = dw2_get_cutu (i);
struct quick_file_names *file_data;
/* We only need to look at symtabs not already expanded. */
static void
dw2_expand_symtabs_matching
(struct objfile *objfile,
- int (*file_matcher) (const char *, void *, int basenames),
- int (*name_matcher) (const char *, void *),
+ expand_symtabs_file_matcher_ftype *file_matcher,
+ expand_symtabs_symbol_matcher_ftype *symbol_matcher,
enum search_domain kind,
void *data)
{
for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
{
int j;
- struct dwarf2_per_cu_data *per_cu = dw2_get_primary_cu (i);
+ struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
struct quick_file_names *file_data;
void **slot;
offset_type idx = 2 * iter;
const char *name;
offset_type *vec, vec_len, vec_idx;
+ int global_seen = 0;
if (index->symbol_table[idx] == 0 && index->symbol_table[idx + 1] == 0)
continue;
name = index->constant_pool + MAYBE_SWAP (index->symbol_table[idx]);
- if (! (*name_matcher) (name, data))
+ if (! (*symbol_matcher) (name, data))
continue;
/* The name was matched, now expand corresponding CUs that were
{
struct dwarf2_per_cu_data *per_cu;
offset_type cu_index_and_attrs = MAYBE_SWAP (vec[vec_idx + 1]);
+ /* 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);
int cu_index = GDB_INDEX_CU_VALUE (cu_index_and_attrs);
(index->version >= 7
&& symbol_kind != GDB_INDEX_SYMBOL_KIND_NONE);
+ /* Work around gold/15646. */
+ if (attrs_valid)
+ {
+ if (!is_static && global_seen)
+ continue;
+ if (!is_static)
+ global_seen = 1;
+ }
+
/* Only check the symbol's kind if it has one. */
if (attrs_valid)
{
continue;
}
- per_cu = dw2_get_cu (cu_index);
+ per_cu = dw2_get_cutu (cu_index);
if (file_matcher == NULL || per_cu->v.quick->mark)
dw2_instantiate_symtab (per_cu);
}
static struct symtab *
dw2_find_pc_sect_symtab (struct objfile *objfile,
- struct minimal_symbol *msymbol,
+ struct bound_minimal_symbol msymbol,
CORE_ADDR pc,
struct obj_section *section,
int warn_if_readin)
for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
{
- struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
+ struct dwarf2_per_cu_data *per_cu = dw2_get_cutu (i);
if (per_cu->v.quick->symtab)
{
for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
{
int j;
- struct dwarf2_per_cu_data *per_cu = dw2_get_primary_cu (i);
+ struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
struct quick_file_names *file_data;
void **slot;
for (i = 0; i < (dwarf2_per_objfile->n_comp_units
+ dwarf2_per_objfile->n_type_units); ++i)
{
- struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
+ struct dwarf2_per_cu_data *per_cu = dw2_get_cutu (i);
per_cu->v.quick = OBSTACK_ZALLOC (&objfile->objfile_obstack,
struct dwarf2_per_cu_quick_data);
attr = dwarf2_attr (die, DW_AT_entry_pc, cu);
if (attr)
{
- cu->base_address = DW_ADDR (attr);
+ cu->base_address = attr_value_as_address (attr);
cu->base_known = 1;
}
else
attr = dwarf2_attr (die, DW_AT_low_pc, cu);
if (attr)
{
- cu->base_address = DW_ADDR (attr);
+ cu->base_address = attr_value_as_address (attr);
cu->base_known = 1;
}
}
return; /* No linetable, so no includes. */
/* NOTE: pst->dirname is DW_AT_comp_dir (if present). */
- dwarf_decode_lines (lh, pst->dirname, cu, pst, 1);
+ dwarf_decode_lines (lh, pst->dirname, cu, pst, pst->textlow);
free_line_header (lh);
}
}
*slot = dwo_file ? (void *) dwo_tu : (void *) sig_type;
- if (dwarf2_read_debug)
+ if (dwarf2_read_debug > 1)
fprintf_unfiltered (gdb_stdlog, " offset 0x%x, signature %s\n",
offset.sect_off,
hex_string (signature));
dwarf2_per_objfile->signatured_types = types_htab;
- dwarf2_per_objfile->n_type_units = htab_elements (types_htab);
+ dwarf2_per_objfile->n_type_units
+ = dwarf2_per_objfile->n_allocated_type_units
+ = htab_elements (types_htab);
dwarf2_per_objfile->all_type_units
= xmalloc (dwarf2_per_objfile->n_type_units
* sizeof (struct signatured_type *));
return 1;
}
+/* Add an entry for signature SIG to dwarf2_per_objfile->signatured_types.
+ If SLOT is non-NULL, it is the entry to use in the hash table.
+ Otherwise we find one. */
+
+static struct signatured_type *
+add_type_unit (ULONGEST sig, void **slot)
+{
+ struct objfile *objfile = dwarf2_per_objfile->objfile;
+ int n_type_units = dwarf2_per_objfile->n_type_units;
+ struct signatured_type *sig_type;
+
+ gdb_assert (n_type_units <= dwarf2_per_objfile->n_allocated_type_units);
+ ++n_type_units;
+ if (n_type_units > dwarf2_per_objfile->n_allocated_type_units)
+ {
+ if (dwarf2_per_objfile->n_allocated_type_units == 0)
+ dwarf2_per_objfile->n_allocated_type_units = 1;
+ dwarf2_per_objfile->n_allocated_type_units *= 2;
+ dwarf2_per_objfile->all_type_units
+ = xrealloc (dwarf2_per_objfile->all_type_units,
+ dwarf2_per_objfile->n_allocated_type_units
+ * sizeof (struct signatured_type *));
+ ++dwarf2_per_objfile->tu_stats.nr_all_type_units_reallocs;
+ }
+ dwarf2_per_objfile->n_type_units = n_type_units;
+
+ sig_type = OBSTACK_ZALLOC (&objfile->objfile_obstack,
+ struct signatured_type);
+ dwarf2_per_objfile->all_type_units[n_type_units - 1] = sig_type;
+ sig_type->signature = sig;
+ sig_type->per_cu.is_debug_types = 1;
+ if (dwarf2_per_objfile->using_index)
+ {
+ sig_type->per_cu.v.quick =
+ OBSTACK_ZALLOC (&objfile->objfile_obstack,
+ struct dwarf2_per_cu_quick_data);
+ }
+
+ if (slot == NULL)
+ {
+ slot = htab_find_slot (dwarf2_per_objfile->signatured_types,
+ sig_type, INSERT);
+ }
+ gdb_assert (*slot == NULL);
+ *slot = sig_type;
+ /* The rest of sig_type must be filled in by the caller. */
+ return sig_type;
+}
+
/* Subroutine of lookup_dwo_signatured_type and lookup_dwp_signatured_type.
Fill in SIG_ENTRY with DWO_ENTRY. */
/* Make sure we're not clobbering something we don't expect to. */
gdb_assert (! sig_entry->per_cu.queued);
gdb_assert (sig_entry->per_cu.cu == NULL);
- gdb_assert (sig_entry->per_cu.v.quick != NULL);
- gdb_assert (sig_entry->per_cu.v.quick->symtab == NULL);
+ if (dwarf2_per_objfile->using_index)
+ {
+ gdb_assert (sig_entry->per_cu.v.quick != NULL);
+ gdb_assert (sig_entry->per_cu.v.quick->symtab == NULL);
+ }
+ else
+ gdb_assert (sig_entry->per_cu.v.psymtab == NULL);
gdb_assert (sig_entry->signature == dwo_entry->signature);
gdb_assert (sig_entry->type_offset_in_section.sect_off == 0);
gdb_assert (sig_entry->type_unit_group == NULL);
struct dwo_file *dwo_file;
struct dwo_unit find_dwo_entry, *dwo_entry;
struct signatured_type find_sig_entry, *sig_entry;
+ void **slot;
gdb_assert (cu->dwo_unit && dwarf2_per_objfile->using_index);
- /* Note: cu->dwo_unit is the dwo_unit that references this TU, not the
- dwo_unit of the TU itself. */
- dwo_file = cu->dwo_unit->dwo_file;
+ /* If TU skeletons have been removed then we may not have read in any
+ TUs yet. */
+ if (dwarf2_per_objfile->signatured_types == NULL)
+ {
+ dwarf2_per_objfile->signatured_types
+ = allocate_signatured_type_table (objfile);
+ }
/* We only ever need to read in one copy of a signatured type.
- Just use the global signatured_types array. If this is the first time
- we're reading this type, replace the recorded data from .gdb_index with
- this TU. */
+ Use the global signatured_types array to do our own comdat-folding
+ of types. If this is the first time we're reading this TU, and
+ the TU has an entry in .gdb_index, replace the recorded data from
+ .gdb_index with this TU. */
- if (dwarf2_per_objfile->signatured_types == NULL)
- return NULL;
find_sig_entry.signature = sig;
- sig_entry = htab_find (dwarf2_per_objfile->signatured_types, &find_sig_entry);
- if (sig_entry == NULL)
- return NULL;
+ slot = htab_find_slot (dwarf2_per_objfile->signatured_types,
+ &find_sig_entry, INSERT);
+ sig_entry = *slot;
/* We can get here with the TU already read, *or* in the process of being
- read. Don't reassign it if that's the case. Also note that if the TU is
- already being read, it may not have come from a DWO, the program may be
- a mix of Fission-compiled code and non-Fission-compiled code. */
- /* Have we already tried to read this TU? */
- if (sig_entry->per_cu.tu_read)
+ read. Don't reassign the global entry to point to this DWO if that's
+ the case. Also note that if the TU is already being read, it may not
+ have come from a DWO, the program may be a mix of Fission-compiled
+ code and non-Fission-compiled code. */
+
+ /* Have we already tried to read this TU?
+ Note: sig_entry can be NULL if the skeleton TU was removed (thus it
+ needn't exist in the global table yet). */
+ if (sig_entry != NULL && sig_entry->per_cu.tu_read)
return sig_entry;
+ /* Note: cu->dwo_unit is the dwo_unit that references this TU, not the
+ dwo_unit of the TU itself. */
+ dwo_file = cu->dwo_unit->dwo_file;
+
/* Ok, this is the first time we're reading this TU. */
if (dwo_file->tus == NULL)
return NULL;
if (dwo_entry == NULL)
return NULL;
+ /* If the global table doesn't have an entry for this TU, add one. */
+ if (sig_entry == NULL)
+ sig_entry = add_type_unit (sig, slot);
+
fill_in_sig_entry_from_dwo_entry (objfile, sig_entry, dwo_entry);
sig_entry->per_cu.tu_read = 1;
return sig_entry;
}
-/* Subroutine of lookup_dwp_signatured_type.
- Add an entry for signature SIG to dwarf2_per_objfile->signatured_types. */
-
-static struct signatured_type *
-add_type_unit (ULONGEST sig)
-{
- struct objfile *objfile = dwarf2_per_objfile->objfile;
- int n_type_units = dwarf2_per_objfile->n_type_units;
- struct signatured_type *sig_type;
- void **slot;
-
- ++n_type_units;
- dwarf2_per_objfile->all_type_units =
- xrealloc (dwarf2_per_objfile->all_type_units,
- n_type_units * sizeof (struct signatured_type *));
- dwarf2_per_objfile->n_type_units = n_type_units;
- sig_type = OBSTACK_ZALLOC (&objfile->objfile_obstack,
- struct signatured_type);
- dwarf2_per_objfile->all_type_units[n_type_units - 1] = sig_type;
- sig_type->signature = sig;
- sig_type->per_cu.is_debug_types = 1;
- sig_type->per_cu.v.quick =
- OBSTACK_ZALLOC (&objfile->objfile_obstack,
- struct dwarf2_per_cu_quick_data);
- slot = htab_find_slot (dwarf2_per_objfile->signatured_types,
- sig_type, INSERT);
- gdb_assert (*slot == NULL);
- *slot = sig_type;
- /* The rest of sig_type must be filled in by the caller. */
- return sig_type;
-}
-
/* Subroutine of lookup_signatured_type.
Look up the type for signature SIG, and if we can't find SIG in .gdb_index
- then try the DWP file.
- Normally this "can't happen", but if there's a bug in signature
- generation and/or the DWP file is built incorrectly, it can happen.
- Using the type directly from the DWP file means we don't have the stub
- which has some useful attributes (e.g., DW_AT_comp_dir), but they're
- not critical. [Eventually the stub may go away for type units anyway.] */
+ then try the DWP file. If the TU stub (skeleton) has been removed then
+ it won't be in .gdb_index. */
static struct signatured_type *
lookup_dwp_signatured_type (struct dwarf2_cu *cu, ULONGEST sig)
struct dwp_file *dwp_file = get_dwp_file ();
struct dwo_unit *dwo_entry;
struct signatured_type find_sig_entry, *sig_entry;
+ void **slot;
gdb_assert (cu->dwo_unit && dwarf2_per_objfile->using_index);
gdb_assert (dwp_file != NULL);
- if (dwarf2_per_objfile->signatured_types != NULL)
+ /* If TU skeletons have been removed then we may not have read in any
+ TUs yet. */
+ if (dwarf2_per_objfile->signatured_types == NULL)
{
- find_sig_entry.signature = sig;
- sig_entry = htab_find (dwarf2_per_objfile->signatured_types,
- &find_sig_entry);
- if (sig_entry != NULL)
- return sig_entry;
+ dwarf2_per_objfile->signatured_types
+ = allocate_signatured_type_table (objfile);
}
- /* This is the "shouldn't happen" case.
- Try the DWP file and hope for the best. */
+ find_sig_entry.signature = sig;
+ slot = htab_find_slot (dwarf2_per_objfile->signatured_types,
+ &find_sig_entry, INSERT);
+ sig_entry = *slot;
+
+ /* Have we already tried to read this TU?
+ Note: sig_entry can be NULL if the skeleton TU was removed (thus it
+ needn't exist in the global table yet). */
+ if (sig_entry != NULL)
+ return sig_entry;
+
if (dwp_file->tus == NULL)
return NULL;
dwo_entry = lookup_dwo_unit_in_dwp (dwp_file, NULL,
if (dwo_entry == NULL)
return NULL;
- sig_entry = add_type_unit (sig);
+ sig_entry = add_type_unit (sig, slot);
fill_in_sig_entry_from_dwo_entry (objfile, sig_entry, dwo_entry);
- /* The caller will signal a complaint if we return NULL.
- Here we don't return NULL but we still want to complain. */
- complaint (&symfile_complaints,
- _("Bad type signature %s referenced by %s at 0x%x,"
- " coping by using copy in DWP [in module %s]"),
- hex_string (sig),
- cu->per_cu->is_debug_types ? "TU" : "CU",
- cu->per_cu->offset.sect_off,
- objfile_name (objfile));
-
return sig_entry;
}
from it to the DIE in the DWO. If NULL we are skipping the stub.
STUB_COMP_DIR is similar to STUB_COMP_UNIT_DIE: When reading a TU directly
from the DWO file, bypassing the stub, it contains the DW_AT_comp_dir
- attribute of the referencing CU. Exactly one of STUB_COMP_UNIT_DIE and
- COMP_DIR must be non-NULL.
+ attribute of the referencing CU. At most one of STUB_COMP_UNIT_DIE and
+ STUB_COMP_DIR may be non-NULL.
*RESULT_READER,*RESULT_INFO_PTR,*RESULT_COMP_UNIT_DIE,*RESULT_HAS_CHILDREN
are filled in with the info of the DIE from the DWO file.
ABBREV_TABLE_PROVIDED is non-zero if the caller of init_cutu_and_read_dies
struct dwarf2_section_info *section;
bfd *abfd;
const gdb_byte *begin_info_ptr, *info_ptr;
- const char *comp_dir_string;
ULONGEST signature; /* Or dwo_id. */
struct attribute *comp_dir, *stmt_list, *low_pc, *high_pc, *ranges;
int i,num_extra_attrs;
struct dwarf2_section_info *dwo_abbrev_section;
struct attribute *attr;
- struct attribute comp_dir_attr;
struct die_info *comp_unit_die;
- /* Both can't be provided. */
- gdb_assert (! (stub_comp_unit_die && stub_comp_dir));
+ /* At most one of these may be provided. */
+ gdb_assert ((stub_comp_unit_die != NULL) + (stub_comp_dir != NULL) <= 1);
/* These attributes aren't processed until later:
DW_AT_stmt_list, DW_AT_low_pc, DW_AT_high_pc, DW_AT_ranges.
- However, the attribute is found in the stub which we won't have later.
- In order to not impose this complication on the rest of the code,
- we read them here and copy them to the DWO CU/TU die. */
+ DW_AT_comp_dir is used now, to find the DWO file, but it is also
+ referenced later. However, these attributes are found in the stub
+ which we won't have later. In order to not impose this complication
+ on the rest of the code, we read them here and copy them to the
+ DWO CU/TU die. */
stmt_list = NULL;
low_pc = NULL;
}
/* Subroutine of init_cutu_and_read_dies to simplify it.
- Read a TU directly from a DWO file, bypassing the stub. */
+ See it for a description of the parameters.
+ Read a TU directly from a DWO file, bypassing the stub.
+
+ Note: This function could be a little bit simpler if we shared cleanups
+ with our caller, init_cutu_and_read_dies. That's generally a fragile thing
+ to do, so we keep this function self-contained. Or we could move this
+ into our caller, but it's complex enough already. */
static void
-init_tu_and_read_dwo_dies (struct dwarf2_per_cu_data *this_cu, int keep,
+init_tu_and_read_dwo_dies (struct dwarf2_per_cu_data *this_cu,
+ int use_existing_cu, int keep,
die_reader_func_ftype *die_reader_func,
void *data)
{
struct dwarf2_cu *cu;
struct signatured_type *sig_type;
- struct cleanup *cleanups, *free_cu_cleanup;
+ struct cleanup *cleanups, *free_cu_cleanup = NULL;
struct die_reader_specs reader;
const gdb_byte *info_ptr;
struct die_info *comp_unit_die;
cleanups = make_cleanup (null_cleanup, NULL);
- gdb_assert (this_cu->cu == NULL);
- cu = xmalloc (sizeof (*cu));
- init_one_comp_unit (cu, this_cu);
- /* If an error occurs while loading, release our storage. */
- free_cu_cleanup = make_cleanup (free_heap_comp_unit, cu);
+ if (use_existing_cu && this_cu->cu != NULL)
+ {
+ gdb_assert (this_cu->cu->dwo_unit == sig_type->dwo_unit);
+ cu = this_cu->cu;
+ /* There's no need to do the rereading_dwo_cu handling that
+ init_cutu_and_read_dies does since we don't read the stub. */
+ }
+ else
+ {
+ /* If !use_existing_cu, this_cu->cu must be NULL. */
+ gdb_assert (this_cu->cu == NULL);
+ cu = xmalloc (sizeof (*cu));
+ init_one_comp_unit (cu, this_cu);
+ /* If an error occurs while loading, release our storage. */
+ free_cu_cleanup = make_cleanup (free_heap_comp_unit, cu);
+ }
+
+ /* A future optimization, if needed, would be to use an existing
+ abbrev table. When reading DWOs with skeletonless TUs, all the TUs
+ could share abbrev tables. */
if (read_cutu_die_from_dwo (this_cu, sig_type->dwo_unit,
0 /* abbrev_table_provided */,
/* All the "real" work is done here. */
die_reader_func (&reader, info_ptr, comp_unit_die, has_children, data);
- /* This duplicates some code in init_cutu_and_read_dies,
+ /* This duplicates the code in init_cutu_and_read_dies,
but the alternative is making the latter more complex.
This function is only for the special case of using DWO files directly:
no point in overly complicating the general case just to handle this. */
- if (keep)
+ if (free_cu_cleanup != NULL)
{
- /* We've successfully allocated this compilation unit. Let our
- caller clean it up when finished with it. */
- discard_cleanups (free_cu_cleanup);
+ if (keep)
+ {
+ /* We've successfully allocated this compilation unit. Let our
+ caller clean it up when finished with it. */
+ discard_cleanups (free_cu_cleanup);
- /* We can only discard free_cu_cleanup and all subsequent cleanups.
- So we have to manually free the abbrev table. */
- dwarf2_free_abbrev_table (cu);
+ /* We can only discard free_cu_cleanup and all subsequent cleanups.
+ So we have to manually free the abbrev table. */
+ dwarf2_free_abbrev_table (cu);
- /* Link this CU into read_in_chain. */
- this_cu->cu->read_in_chain = dwarf2_per_objfile->read_in_chain;
- dwarf2_per_objfile->read_in_chain = this_cu;
+ /* Link this CU into read_in_chain. */
+ this_cu->cu->read_in_chain = dwarf2_per_objfile->read_in_chain;
+ dwarf2_per_objfile->read_in_chain = this_cu;
+ }
+ else
+ do_cleanups (free_cu_cleanup);
}
- else
- do_cleanups (free_cu_cleanup);
do_cleanups (cleanups);
}
/* Narrow down the scope of possibilities to have to understand. */
gdb_assert (this_cu->is_debug_types);
gdb_assert (abbrev_table == NULL);
- gdb_assert (!use_existing_cu);
- init_tu_and_read_dwo_dies (this_cu, keep, die_reader_func, data);
+ init_tu_and_read_dwo_dies (this_cu, use_existing_cu, keep,
+ die_reader_func, data);
return;
}
if (use_existing_cu && this_cu->cu != NULL)
{
cu = this_cu->cu;
-
/* If this CU is from a DWO file we need to start over, we need to
refetch the attributes from the skeleton CU.
This could be optimized by retrieving those attributes from when we
{
/* If !use_existing_cu, this_cu->cu must be NULL. */
gdb_assert (this_cu->cu == NULL);
-
cu = xmalloc (sizeof (*cu));
init_one_comp_unit (cu, this_cu);
-
/* If an error occurs while loading, release our storage. */
free_cu_cleanup = make_cleanup (free_heap_comp_unit, cu);
}
do_cleanups (cleanups);
}
-/* Read CU/TU THIS_CU in section SECTION,
- but do not follow DW_AT_GNU_dwo_name if present.
- DWOP_FILE, if non-NULL, is the DWO/DWP file to read (the caller is assumed
- to have already done the lookup to find the DWO/DWP file).
+/* Read CU/TU THIS_CU but do not follow DW_AT_GNU_dwo_name if present.
+ DWO_FILE, if non-NULL, is the DWO file to read (the caller is assumed
+ to have already done the lookup to find the DWO file).
The caller is required to fill in THIS_CU->section, THIS_CU->offset, and
THIS_CU->is_debug_types, but nothing else.
static void
init_cutu_and_read_dies_no_follow (struct dwarf2_per_cu_data *this_cu,
- struct dwarf2_section_info *abbrev_section,
struct dwo_file *dwo_file,
die_reader_func_ftype *die_reader_func,
void *data)
struct objfile *objfile = dwarf2_per_objfile->objfile;
struct dwarf2_section_info *section = this_cu->section;
bfd *abfd = get_section_bfd_owner (section);
+ struct dwarf2_section_info *abbrev_section;
struct dwarf2_cu cu;
const gdb_byte *begin_info_ptr, *info_ptr;
struct die_reader_specs reader;
gdb_assert (this_cu->cu == NULL);
+ abbrev_section = (dwo_file != NULL
+ ? &dwo_file->sections.abbrev
+ : get_abbrev_section_for_cu (this_cu));
+
/* This is cheap if the section is already read in. */
dwarf2_read_section (objfile, section);
die_reader_func_ftype *die_reader_func,
void *data)
{
- init_cutu_and_read_dies_no_follow (this_cu,
- get_abbrev_section_for_cu (this_cu),
- NULL,
- die_reader_func, data);
+ init_cutu_and_read_dies_no_follow (this_cu, NULL, die_reader_func, data);
}
\f
/* Type Unit Groups.
return tu_group;
}
+\f
+/* Partial symbol tables. */
-/* Struct used to sort TUs by their abbreviation table offset. */
+/* Create a psymtab named NAME and assign it to PER_CU.
-struct tu_abbrev_offset
-{
- struct signatured_type *sig_type;
- sect_offset abbrev_offset;
-};
-
-/* Helper routine for build_type_unit_groups, passed to qsort. */
-
-static int
-sort_tu_by_abbrev_offset (const void *ap, const void *bp)
-{
- const struct tu_abbrev_offset * const *a = ap;
- const struct tu_abbrev_offset * const *b = bp;
- unsigned int aoff = (*a)->abbrev_offset.sect_off;
- unsigned int boff = (*b)->abbrev_offset.sect_off;
-
- return (aoff > boff) - (aoff < boff);
-}
-
-/* A helper function to add a type_unit_group to a table. */
-
-static int
-add_type_unit_group_to_table (void **slot, void *datum)
-{
- struct type_unit_group *tu_group = *slot;
- struct type_unit_group ***datap = datum;
-
- **datap = tu_group;
- ++*datap;
-
- return 1;
-}
-
-/* Efficiently read all the type units, calling init_cutu_and_read_dies on
- each one passing FUNC,DATA.
-
- The efficiency is because we sort TUs by the abbrev table they use and
- only read each abbrev table once. In one program there are 200K TUs
- sharing 8K abbrev tables.
-
- The main purpose of this function is to support building the
- dwarf2_per_objfile->type_unit_groups table.
- TUs typically share the DW_AT_stmt_list of the CU they came from, so we
- can collapse the search space by grouping them by stmt_list.
- The savings can be significant, in the same program from above the 200K TUs
- share 8K stmt_list tables.
-
- FUNC is expected to call get_type_unit_group, which will create the
- struct type_unit_group if necessary and add it to
- dwarf2_per_objfile->type_unit_groups. */
-
-static void
-build_type_unit_groups (die_reader_func_ftype *func, void *data)
-{
- struct objfile *objfile = dwarf2_per_objfile->objfile;
- struct tu_stats *tu_stats = &dwarf2_per_objfile->tu_stats;
- struct cleanup *cleanups;
- struct abbrev_table *abbrev_table;
- sect_offset abbrev_offset;
- struct tu_abbrev_offset *sorted_by_abbrev;
- struct type_unit_group **iter;
- int i;
-
- /* It's up to the caller to not call us multiple times. */
- gdb_assert (dwarf2_per_objfile->type_unit_groups == NULL);
-
- if (dwarf2_per_objfile->n_type_units == 0)
- return;
-
- /* TUs typically share abbrev tables, and there can be way more TUs than
- abbrev tables. Sort by abbrev table to reduce the number of times we
- read each abbrev table in.
- Alternatives are to punt or to maintain a cache of abbrev tables.
- This is simpler and efficient enough for now.
-
- Later we group TUs by their DW_AT_stmt_list value (as this defines the
- symtab to use). Typically TUs with the same abbrev offset have the same
- stmt_list value too so in practice this should work well.
-
- The basic algorithm here is:
-
- sort TUs by abbrev table
- for each TU with same abbrev table:
- read abbrev table if first user
- read TU top level DIE
- [IWBN if DWO skeletons had DW_AT_stmt_list]
- call FUNC */
-
- if (dwarf2_read_debug)
- fprintf_unfiltered (gdb_stdlog, "Building type unit groups ...\n");
-
- /* Sort in a separate table to maintain the order of all_type_units
- for .gdb_index: TU indices directly index all_type_units. */
- sorted_by_abbrev = XNEWVEC (struct tu_abbrev_offset,
- dwarf2_per_objfile->n_type_units);
- for (i = 0; i < dwarf2_per_objfile->n_type_units; ++i)
- {
- struct signatured_type *sig_type = dwarf2_per_objfile->all_type_units[i];
-
- sorted_by_abbrev[i].sig_type = sig_type;
- sorted_by_abbrev[i].abbrev_offset =
- read_abbrev_offset (sig_type->per_cu.section,
- sig_type->per_cu.offset);
- }
- cleanups = make_cleanup (xfree, sorted_by_abbrev);
- qsort (sorted_by_abbrev, dwarf2_per_objfile->n_type_units,
- sizeof (struct tu_abbrev_offset), sort_tu_by_abbrev_offset);
-
- /* Note: In the .gdb_index case, get_type_unit_group may have already been
- called any number of times, so we don't reset tu_stats here. */
-
- abbrev_offset.sect_off = ~(unsigned) 0;
- abbrev_table = NULL;
- make_cleanup (abbrev_table_free_cleanup, &abbrev_table);
-
- for (i = 0; i < dwarf2_per_objfile->n_type_units; ++i)
- {
- const struct tu_abbrev_offset *tu = &sorted_by_abbrev[i];
-
- /* Switch to the next abbrev table if necessary. */
- if (abbrev_table == NULL
- || tu->abbrev_offset.sect_off != abbrev_offset.sect_off)
- {
- if (abbrev_table != NULL)
- {
- abbrev_table_free (abbrev_table);
- /* Reset to NULL in case abbrev_table_read_table throws
- an error: abbrev_table_free_cleanup will get called. */
- abbrev_table = NULL;
- }
- abbrev_offset = tu->abbrev_offset;
- abbrev_table =
- abbrev_table_read_table (&dwarf2_per_objfile->abbrev,
- abbrev_offset);
- ++tu_stats->nr_uniq_abbrev_tables;
- }
-
- init_cutu_and_read_dies (&tu->sig_type->per_cu, abbrev_table, 0, 0,
- func, data);
- }
-
- /* type_unit_groups can be NULL if there is an error in the debug info.
- Just create an empty table so the rest of gdb doesn't have to watch
- for this error case. */
- if (dwarf2_per_objfile->type_unit_groups == NULL)
- {
- dwarf2_per_objfile->type_unit_groups =
- allocate_type_unit_groups_table ();
- dwarf2_per_objfile->n_type_unit_groups = 0;
- }
-
- /* Create a vector of pointers to primary type units to make it easy to
- iterate over them and CUs. See dw2_get_primary_cu. */
- dwarf2_per_objfile->n_type_unit_groups =
- htab_elements (dwarf2_per_objfile->type_unit_groups);
- dwarf2_per_objfile->all_type_unit_groups =
- obstack_alloc (&objfile->objfile_obstack,
- dwarf2_per_objfile->n_type_unit_groups
- * sizeof (struct type_unit_group *));
- iter = &dwarf2_per_objfile->all_type_unit_groups[0];
- htab_traverse_noresize (dwarf2_per_objfile->type_unit_groups,
- add_type_unit_group_to_table, &iter);
- gdb_assert (iter - &dwarf2_per_objfile->all_type_unit_groups[0]
- == dwarf2_per_objfile->n_type_unit_groups);
-
- do_cleanups (cleanups);
-
- if (dwarf2_read_debug)
- {
- fprintf_unfiltered (gdb_stdlog, "Done building type unit groups:\n");
- fprintf_unfiltered (gdb_stdlog, " %d TUs\n",
- dwarf2_per_objfile->n_type_units);
- fprintf_unfiltered (gdb_stdlog, " %d uniq abbrev tables\n",
- tu_stats->nr_uniq_abbrev_tables);
- fprintf_unfiltered (gdb_stdlog, " %d symtabs from stmt_list entries\n",
- tu_stats->nr_symtabs);
- fprintf_unfiltered (gdb_stdlog, " %d symtab sharers\n",
- tu_stats->nr_symtab_sharers);
- fprintf_unfiltered (gdb_stdlog, " %d type units without a stmt_list\n",
- tu_stats->nr_stmt_less_type_units);
- }
-}
-\f
-/* Partial symbol tables. */
-
-/* Create a psymtab named NAME and assign it to PER_CU.
-
- The caller must fill in the following details:
- dirname, textlow, texthigh. */
+ The caller must fill in the following details:
+ dirname, textlow, texthigh. */
static struct partial_symtab *
create_partial_symtab (struct dwarf2_per_cu_data *per_cu, const char *name)
sort_pst_symbols (objfile, pst);
}
+/* Struct used to sort TUs by their abbreviation table offset. */
+
+struct tu_abbrev_offset
+{
+ struct signatured_type *sig_type;
+ sect_offset abbrev_offset;
+};
+
+/* Helper routine for build_type_psymtabs_1, passed to qsort. */
+
+static int
+sort_tu_by_abbrev_offset (const void *ap, const void *bp)
+{
+ const struct tu_abbrev_offset * const *a = ap;
+ const struct tu_abbrev_offset * const *b = bp;
+ unsigned int aoff = (*a)->abbrev_offset.sect_off;
+ unsigned int boff = (*b)->abbrev_offset.sect_off;
+
+ return (aoff > boff) - (aoff < boff);
+}
+
+/* Efficiently read all the type units.
+ This does the bulk of the work for build_type_psymtabs.
+
+ The efficiency is because we sort TUs by the abbrev table they use and
+ only read each abbrev table once. In one program there are 200K TUs
+ sharing 8K abbrev tables.
+
+ The main purpose of this function is to support building the
+ dwarf2_per_objfile->type_unit_groups table.
+ TUs typically share the DW_AT_stmt_list of the CU they came from, so we
+ can collapse the search space by grouping them by stmt_list.
+ The savings can be significant, in the same program from above the 200K TUs
+ share 8K stmt_list tables.
+
+ FUNC is expected to call get_type_unit_group, which will create the
+ struct type_unit_group if necessary and add it to
+ dwarf2_per_objfile->type_unit_groups. */
+
+static void
+build_type_psymtabs_1 (void)
+{
+ struct objfile *objfile = dwarf2_per_objfile->objfile;
+ struct tu_stats *tu_stats = &dwarf2_per_objfile->tu_stats;
+ struct cleanup *cleanups;
+ struct abbrev_table *abbrev_table;
+ sect_offset abbrev_offset;
+ struct tu_abbrev_offset *sorted_by_abbrev;
+ struct type_unit_group **iter;
+ int i;
+
+ /* It's up to the caller to not call us multiple times. */
+ gdb_assert (dwarf2_per_objfile->type_unit_groups == NULL);
+
+ if (dwarf2_per_objfile->n_type_units == 0)
+ return;
+
+ /* TUs typically share abbrev tables, and there can be way more TUs than
+ abbrev tables. Sort by abbrev table to reduce the number of times we
+ read each abbrev table in.
+ Alternatives are to punt or to maintain a cache of abbrev tables.
+ This is simpler and efficient enough for now.
+
+ Later we group TUs by their DW_AT_stmt_list value (as this defines the
+ symtab to use). Typically TUs with the same abbrev offset have the same
+ stmt_list value too so in practice this should work well.
+
+ The basic algorithm here is:
+
+ sort TUs by abbrev table
+ for each TU with same abbrev table:
+ read abbrev table if first user
+ read TU top level DIE
+ [IWBN if DWO skeletons had DW_AT_stmt_list]
+ call FUNC */
+
+ if (dwarf2_read_debug)
+ fprintf_unfiltered (gdb_stdlog, "Building type unit groups ...\n");
+
+ /* Sort in a separate table to maintain the order of all_type_units
+ for .gdb_index: TU indices directly index all_type_units. */
+ sorted_by_abbrev = XNEWVEC (struct tu_abbrev_offset,
+ dwarf2_per_objfile->n_type_units);
+ for (i = 0; i < dwarf2_per_objfile->n_type_units; ++i)
+ {
+ struct signatured_type *sig_type = dwarf2_per_objfile->all_type_units[i];
+
+ sorted_by_abbrev[i].sig_type = sig_type;
+ sorted_by_abbrev[i].abbrev_offset =
+ read_abbrev_offset (sig_type->per_cu.section,
+ sig_type->per_cu.offset);
+ }
+ cleanups = make_cleanup (xfree, sorted_by_abbrev);
+ qsort (sorted_by_abbrev, dwarf2_per_objfile->n_type_units,
+ sizeof (struct tu_abbrev_offset), sort_tu_by_abbrev_offset);
+
+ abbrev_offset.sect_off = ~(unsigned) 0;
+ abbrev_table = NULL;
+ make_cleanup (abbrev_table_free_cleanup, &abbrev_table);
+
+ for (i = 0; i < dwarf2_per_objfile->n_type_units; ++i)
+ {
+ const struct tu_abbrev_offset *tu = &sorted_by_abbrev[i];
+
+ /* Switch to the next abbrev table if necessary. */
+ if (abbrev_table == NULL
+ || tu->abbrev_offset.sect_off != abbrev_offset.sect_off)
+ {
+ if (abbrev_table != NULL)
+ {
+ abbrev_table_free (abbrev_table);
+ /* Reset to NULL in case abbrev_table_read_table throws
+ an error: abbrev_table_free_cleanup will get called. */
+ abbrev_table = NULL;
+ }
+ abbrev_offset = tu->abbrev_offset;
+ abbrev_table =
+ abbrev_table_read_table (&dwarf2_per_objfile->abbrev,
+ abbrev_offset);
+ ++tu_stats->nr_uniq_abbrev_tables;
+ }
+
+ init_cutu_and_read_dies (&tu->sig_type->per_cu, abbrev_table, 0, 0,
+ build_type_psymtabs_reader, NULL);
+ }
+
+ do_cleanups (cleanups);
+}
+
+/* Print collected type unit statistics. */
+
+static void
+print_tu_stats (void)
+{
+ struct tu_stats *tu_stats = &dwarf2_per_objfile->tu_stats;
+
+ fprintf_unfiltered (gdb_stdlog, "Type unit statistics:\n");
+ fprintf_unfiltered (gdb_stdlog, " %d TUs\n",
+ dwarf2_per_objfile->n_type_units);
+ fprintf_unfiltered (gdb_stdlog, " %d uniq abbrev tables\n",
+ tu_stats->nr_uniq_abbrev_tables);
+ fprintf_unfiltered (gdb_stdlog, " %d symtabs from stmt_list entries\n",
+ tu_stats->nr_symtabs);
+ fprintf_unfiltered (gdb_stdlog, " %d symtab sharers\n",
+ tu_stats->nr_symtab_sharers);
+ fprintf_unfiltered (gdb_stdlog, " %d type units without a stmt_list\n",
+ tu_stats->nr_stmt_less_type_units);
+ fprintf_unfiltered (gdb_stdlog, " %d all_type_units reallocs\n",
+ tu_stats->nr_all_type_units_reallocs);
+}
+
/* Traversal function for build_type_psymtabs. */
static int
if (! create_all_type_units (objfile))
return;
- build_type_unit_groups (build_type_psymtabs_reader, NULL);
+ build_type_psymtabs_1 ();
+}
- /* Now that all TUs have been processed we can fill in the dependencies. */
- htab_traverse_noresize (dwarf2_per_objfile->type_unit_groups,
- build_type_psymtab_dependencies, NULL);
+/* Traversal function for process_skeletonless_type_unit.
+ Read a TU in a DWO file and build partial symbols for it. */
+
+static int
+process_skeletonless_type_unit (void **slot, void *info)
+{
+ struct dwo_unit *dwo_unit = (struct dwo_unit *) *slot;
+ struct objfile *objfile = info;
+ struct signatured_type find_entry, *entry;
+
+ /* If this TU doesn't exist in the global table, add it and read it in. */
+
+ if (dwarf2_per_objfile->signatured_types == NULL)
+ {
+ dwarf2_per_objfile->signatured_types
+ = allocate_signatured_type_table (objfile);
+ }
+
+ find_entry.signature = dwo_unit->signature;
+ slot = htab_find_slot (dwarf2_per_objfile->signatured_types, &find_entry,
+ INSERT);
+ /* If we've already seen this type there's nothing to do. What's happening
+ is we're doing our own version of comdat-folding here. */
+ if (*slot != NULL)
+ return 1;
+
+ /* This does the job that create_all_type_units would have done for
+ this TU. */
+ entry = add_type_unit (dwo_unit->signature, slot);
+ fill_in_sig_entry_from_dwo_entry (objfile, entry, dwo_unit);
+ *slot = entry;
+
+ /* This does the job that build_type_psymtabs_1 would have done. */
+ init_cutu_and_read_dies (&entry->per_cu, NULL, 0, 0,
+ build_type_psymtabs_reader, NULL);
+
+ return 1;
+}
+
+/* Traversal function for process_skeletonless_type_units. */
+
+static int
+process_dwo_file_for_skeletonless_type_units (void **slot, void *info)
+{
+ struct dwo_file *dwo_file = (struct dwo_file *) *slot;
+
+ if (dwo_file->tus != NULL)
+ {
+ htab_traverse_noresize (dwo_file->tus,
+ process_skeletonless_type_unit, info);
+ }
+
+ return 1;
+}
+
+/* Scan all TUs of DWO files, verifying we've processed them.
+ This is needed in case a TU was emitted without its skeleton.
+ Note: This can't be done until we know what all the DWO files are. */
+
+static void
+process_skeletonless_type_units (struct objfile *objfile)
+{
+ /* Skeletonless TUs in DWP files without .gdb_index is not supported yet. */
+ if (get_dwp_file () == NULL
+ && dwarf2_per_objfile->dwo_files != NULL)
+ {
+ htab_traverse_noresize (dwarf2_per_objfile->dwo_files,
+ process_dwo_file_for_skeletonless_type_units,
+ objfile);
+ }
}
/* A cleanup function that clears objfile's psymtabs_addrmap field. */
for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
{
- struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
+ struct dwarf2_per_cu_data *per_cu = dw2_get_cutu (i);
struct partial_symtab *pst = per_cu->v.psymtab;
int j;
for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
{
- struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
+ struct dwarf2_per_cu_data *per_cu = dw2_get_cutu (i);
process_psymtab_comp_unit (per_cu, 0, language_minimal);
}
+ /* This has to wait until we read the CUs, we need the list of DWOs. */
+ process_skeletonless_type_units (objfile);
+
+ /* Now that all TUs have been processed we can fill in the dependencies. */
+ if (dwarf2_per_objfile->type_unit_groups != NULL)
+ {
+ htab_traverse_noresize (dwarf2_per_objfile->type_unit_groups,
+ build_type_psymtab_dependencies, NULL);
+ }
+
+ if (dwarf2_read_debug)
+ print_tu_stats ();
+
set_partial_user (objfile);
objfile->psymtabs_addrmap = addrmap_create_fixed (objfile->psymtabs_addrmap,
}
/* Process all loaded DIEs for compilation unit CU, starting at
- FIRST_DIE. The caller should pass NEED_PC == 1 if the compilation
+ FIRST_DIE. The caller should pass SET_ADDRMAP == 1 if the compilation
unit DIE did not have PC info (DW_AT_low_pc and DW_AT_high_pc, or
- DW_AT_ranges). If NEED_PC is set, then this function will set
- *LOWPC and *HIGHPC to the lowest and highest PC values found in CU
- and record the covered ranges in the addrmap. */
+ DW_AT_ranges). See the comments of add_partial_subprogram on how
+ SET_ADDRMAP is used and how *LOWPC and *HIGHPC are updated. */
static void
scan_partial_symbols (struct partial_die_info *first_die, CORE_ADDR *lowpc,
- CORE_ADDR *highpc, int need_pc, struct dwarf2_cu *cu)
+ CORE_ADDR *highpc, int set_addrmap,
+ struct dwarf2_cu *cu)
{
struct partial_die_info *pdi;
switch (pdi->tag)
{
case DW_TAG_subprogram:
- add_partial_subprogram (pdi, lowpc, highpc, need_pc, cu);
+ add_partial_subprogram (pdi, lowpc, highpc, set_addrmap, cu);
break;
case DW_TAG_constant:
case DW_TAG_variable:
add_partial_symbol (pdi, cu);
break;
case DW_TAG_namespace:
- add_partial_namespace (pdi, lowpc, highpc, need_pc, cu);
+ add_partial_namespace (pdi, lowpc, highpc, set_addrmap, cu);
break;
case DW_TAG_module:
- add_partial_module (pdi, lowpc, highpc, need_pc, cu);
+ add_partial_module (pdi, lowpc, highpc, set_addrmap, cu);
break;
case DW_TAG_imported_unit:
{
cu->per_cu->imported_symtabs, per_cu);
}
break;
+ case DW_TAG_imported_declaration:
+ add_partial_symbol (pdi, cu);
+ break;
default:
break;
}
&objfile->static_psymbols,
0, (CORE_ADDR) 0, cu->language, objfile);
break;
+ case DW_TAG_imported_declaration:
case DW_TAG_namespace:
add_psymbol_to_list (actual_name, strlen (actual_name),
built_actual_name != NULL,
&objfile->global_psymbols,
0, (CORE_ADDR) 0, cu->language, objfile);
break;
+ case DW_TAG_module:
+ add_psymbol_to_list (actual_name, strlen (actual_name),
+ built_actual_name != NULL,
+ MODULE_DOMAIN, LOC_TYPEDEF,
+ &objfile->global_psymbols,
+ 0, (CORE_ADDR) 0, cu->language, objfile);
+ break;
case DW_TAG_class_type:
case DW_TAG_interface_type:
case DW_TAG_structure_type:
static void
add_partial_namespace (struct partial_die_info *pdi,
CORE_ADDR *lowpc, CORE_ADDR *highpc,
- int need_pc, struct dwarf2_cu *cu)
+ int set_addrmap, struct dwarf2_cu *cu)
{
/* Add a symbol for the namespace. */
/* Now scan partial symbols in that namespace. */
if (pdi->has_children)
- scan_partial_symbols (pdi->die_child, lowpc, highpc, need_pc, cu);
+ scan_partial_symbols (pdi->die_child, lowpc, highpc, set_addrmap, cu);
}
/* Read a partial die corresponding to a Fortran module. */
static void
add_partial_module (struct partial_die_info *pdi, CORE_ADDR *lowpc,
- CORE_ADDR *highpc, int need_pc, struct dwarf2_cu *cu)
+ CORE_ADDR *highpc, int set_addrmap, struct dwarf2_cu *cu)
{
+ /* Add a symbol for the namespace. */
+
+ add_partial_symbol (pdi, cu);
+
/* Now scan partial symbols in that module. */
if (pdi->has_children)
- scan_partial_symbols (pdi->die_child, lowpc, highpc, need_pc, cu);
+ scan_partial_symbols (pdi->die_child, lowpc, highpc, set_addrmap, cu);
}
/* Read a partial die corresponding to a subprogram and create a partial
symbol for that subprogram. When the CU language allows it, this
routine also defines a partial symbol for each nested subprogram
- that this subprogram contains.
+ that this subprogram contains. If SET_ADDRMAP is true, record the
+ covered ranges in the addrmap. Set *LOWPC and *HIGHPC to the lowest
+ and highest PC values found in PDI.
- DIE my also be a lexical block, in which case we simply search
- recursively for suprograms defined inside that lexical block.
+ PDI may also be a lexical block, in which case we simply search
+ recursively for subprograms defined inside that lexical block.
Again, this is only performed when the CU language allows this
type of definitions. */
static void
add_partial_subprogram (struct partial_die_info *pdi,
CORE_ADDR *lowpc, CORE_ADDR *highpc,
- int need_pc, struct dwarf2_cu *cu)
+ int set_addrmap, struct dwarf2_cu *cu)
{
if (pdi->tag == DW_TAG_subprogram)
{
*lowpc = pdi->lowpc;
if (pdi->highpc > *highpc)
*highpc = pdi->highpc;
- if (need_pc)
+ if (set_addrmap)
{
CORE_ADDR baseaddr;
struct objfile *objfile = cu->objfile;
fixup_partial_die (pdi, cu);
if (pdi->tag == DW_TAG_subprogram
|| pdi->tag == DW_TAG_lexical_block)
- add_partial_subprogram (pdi, lowpc, highpc, need_pc, cu);
+ add_partial_subprogram (pdi, lowpc, highpc, set_addrmap, cu);
pdi = pdi->die_sibling;
}
}
complaint (&symfile_complaints,
_("ignoring absolute DW_AT_sibling"));
else
- return buffer + dwarf2_get_ref_die_offset (&attr).sect_off;
+ {
+ unsigned int off = dwarf2_get_ref_die_offset (&attr).sect_off;
+ const gdb_byte *sibling_ptr = buffer + off;
+
+ if (sibling_ptr < info_ptr)
+ complaint (&symfile_complaints,
+ _("DW_AT_sibling points backwards"));
+ else if (sibling_ptr > reader->buffer_end)
+ dwarf2_section_buffer_overflow_complaint (reader->die_section);
+ else
+ return sibling_ptr;
+ }
}
/* If it isn't DW_AT_sibling, skip this attribute. */
: (item->per_cu->v.psymtab && !item->per_cu->v.psymtab->readin))
{
struct dwarf2_per_cu_data *per_cu = item->per_cu;
+ unsigned int debug_print_threshold;
char buf[100];
if (per_cu->is_debug_types)
(struct signatured_type *) per_cu;
sprintf (buf, "TU %s at offset 0x%x",
- hex_string (sig_type->signature), per_cu->offset.sect_off);
+ hex_string (sig_type->signature),
+ per_cu->offset.sect_off);
+ /* There can be 100s of TUs.
+ Only print them in verbose mode. */
+ debug_print_threshold = 2;
}
else
- sprintf (buf, "CU at offset 0x%x", per_cu->offset.sect_off);
+ {
+ sprintf (buf, "CU at offset 0x%x", per_cu->offset.sect_off);
+ debug_print_threshold = 1;
+ }
- if (dwarf2_read_debug)
+ if (dwarf2_read_debug >= debug_print_threshold)
fprintf_unfiltered (gdb_stdlog, "Expanding symtab of %s\n", buf);
if (per_cu->is_debug_types)
else
process_full_comp_unit (per_cu, item->pretend_language);
- if (dwarf2_read_debug)
+ if (dwarf2_read_debug >= debug_print_threshold)
fprintf_unfiltered (gdb_stdlog, "Done expanding %s\n", buf);
}
if (package_name != NULL)
{
struct objfile *objfile = cu->objfile;
- const char *saved_package_name = obstack_copy0 (&objfile->objfile_obstack,
- package_name,
- strlen (package_name));
+ const char *saved_package_name
+ = obstack_copy0 (&objfile->per_bfd->storage_obstack,
+ package_name,
+ strlen (package_name));
struct type *type = init_type (TYPE_CODE_MODULE, 0, 0,
saved_package_name, objfile);
struct symbol *sym;
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->imported_symtabs,
- per_cu);
- }
+ VEC_safe_push (dwarf2_per_cu_ptr, cu->per_cu->imported_symtabs,
+ per_cu);
+ }
+}
+
+/* Reset the in_process bit of a die. */
+
+static void
+reset_die_in_process (void *arg)
+{
+ struct die_info *die = arg;
+
+ die->in_process = 0;
}
/* Process a die and its children. */
static void
process_die (struct die_info *die, struct dwarf2_cu *cu)
{
+ struct cleanup *in_process;
+
+ /* We should only be processing those not already in process. */
+ gdb_assert (!die->in_process);
+
+ die->in_process = 1;
+ in_process = make_cleanup (reset_die_in_process,die);
+
switch (die->tag)
{
case DW_TAG_padding:
read_module (die, cu);
break;
case DW_TAG_imported_declaration:
+ cu->processing_has_namespace_info = 1;
+ if (read_namespace_alias (die, cu))
+ break;
+ /* The declaration is not a global namespace alias: fall through. */
case DW_TAG_imported_module:
cu->processing_has_namespace_info = 1;
if (die->child != NULL && (die->tag == DW_TAG_imported_declaration
new_symbol (die, NULL, cu);
break;
}
+
+ do_cleanups (in_process);
}
\f
/* DWARF name computation. */
case DW_TAG_enumerator:
case DW_TAG_subprogram:
case DW_TAG_member:
+ case DW_TAG_imported_declaration:
return 1;
case DW_TAG_variable:
long length;
const char *prefix;
struct ui_file *buf;
+ char *intermediate_name;
+ const char *canonical_name = NULL;
prefix = determine_prefix (die, cu);
buf = mem_fileopen ();
}
}
- name = ui_file_obsavestring (buf, &objfile->objfile_obstack,
- &length);
+ intermediate_name = ui_file_xstrdup (buf, &length);
ui_file_delete (buf);
if (cu->language == language_cplus)
- {
- const char *cname
- = dwarf2_canonicalize_name (name, cu,
- &objfile->objfile_obstack);
+ canonical_name
+ = dwarf2_canonicalize_name (intermediate_name, cu,
+ &objfile->per_bfd->storage_obstack);
+
+ /* If we only computed INTERMEDIATE_NAME, or if
+ INTERMEDIATE_NAME is already canonical, then we need to
+ copy it to the appropriate obstack. */
+ if (canonical_name == NULL || canonical_name == intermediate_name)
+ name = obstack_copy0 (&objfile->per_bfd->storage_obstack,
+ intermediate_name,
+ strlen (intermediate_name));
+ else
+ name = canonical_name;
- if (cname != NULL)
- name = cname;
- }
+ xfree (intermediate_name);
}
}
/* Return the fully qualified name of DIE, based on its DW_AT_name.
If scope qualifiers are appropriate they will be added. The result
- will be allocated on the objfile_obstack, or NULL if the DIE does
+ will be allocated on the storage_obstack, or NULL if the DIE does
not have a name. NAME may either be from a previous call to
dwarf2_name or NULL.
retval = canon;
if (need_copy)
- retval = obstack_copy0 (&objfile->objfile_obstack, retval, strlen (retval));
+ retval = obstack_copy0 (&objfile->per_bfd->storage_obstack,
+ retval, strlen (retval));
do_cleanups (back_to);
return retval;
}
+/* Inspect DIE in CU for a namespace alias. If one exists, record
+ a new symbol for it.
+
+ Returns 1 if a namespace alias was recorded, 0 otherwise. */
+
+static int
+read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
+{
+ struct attribute *attr;
+
+ /* If the die does not have a name, this is not a namespace
+ alias. */
+ attr = dwarf2_attr (die, DW_AT_name, cu);
+ if (attr != NULL)
+ {
+ int num;
+ struct die_info *d = die;
+ struct dwarf2_cu *imported_cu = cu;
+
+ /* If the compiler has nested DW_AT_imported_declaration DIEs,
+ keep inspecting DIEs until we hit the underlying import. */
+#define MAX_NESTED_IMPORTED_DECLARATIONS 100
+ for (num = 0; num < MAX_NESTED_IMPORTED_DECLARATIONS; ++num)
+ {
+ attr = dwarf2_attr (d, DW_AT_import, cu);
+ if (attr == NULL)
+ break;
+
+ d = follow_die_ref (d, attr, &imported_cu);
+ if (d->tag != DW_TAG_imported_declaration)
+ break;
+ }
+
+ if (num == MAX_NESTED_IMPORTED_DECLARATIONS)
+ {
+ complaint (&symfile_complaints,
+ _("DIE at 0x%x has too many recursively imported "
+ "declarations"), d->offset.sect_off);
+ return 0;
+ }
+
+ if (attr != NULL)
+ {
+ struct type *type;
+ sect_offset offset = dwarf2_get_ref_die_offset (attr);
+
+ type = get_die_type_at_offset (offset, cu->per_cu);
+ if (type != NULL && TYPE_CODE (type) == TYPE_CODE_NAMESPACE)
+ {
+ /* This declaration is a global namespace alias. Add
+ a symbol for it whose type is the aliased namespace. */
+ new_symbol (die, type, cu);
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
/* Read the import statement specified by the given die and record it. */
static void
/* Handle DW_AT_stmt_list for a compilation unit.
DIE is the DW_TAG_compile_unit die for CU.
- COMP_DIR is the compilation directory.
- WANT_LINE_INFO is non-zero if the pc/line-number mapping is needed. */
+ COMP_DIR is the compilation directory. LOWPC is passed to
+ dwarf_decode_lines. See dwarf_decode_lines comments about it. */
static void
handle_DW_AT_stmt_list (struct die_info *die, struct dwarf2_cu *cu,
- const char *comp_dir) /* ARI: editCase function */
+ const char *comp_dir, CORE_ADDR lowpc) /* ARI: editCase function */
{
struct attribute *attr;
{
cu->line_header = line_header;
make_cleanup (free_cu_line_header, cu);
- dwarf_decode_lines (line_header, comp_dir, cu, NULL, 1);
+ dwarf_decode_lines (line_header, comp_dir, cu, NULL, lowpc);
}
}
}
/* Decode line number information if present. We do this before
processing child DIEs, so that the line header table is available
for DW_AT_decl_file. */
- handle_DW_AT_stmt_list (die, cu, comp_dir);
+ handle_DW_AT_stmt_list (die, cu, comp_dir, lowpc);
/* Process all dies in compilation unit. */
if (die->child != NULL)
per_cu.offset.sect_off = info_ptr - section->buffer;
per_cu.section = section;
- init_cutu_and_read_dies_no_follow (&per_cu,
- &dwo_file->sections.abbrev,
- dwo_file,
+ init_cutu_and_read_dies_no_follow (&per_cu, dwo_file,
create_dwo_cu_reader,
&create_dwo_cu_data);
Numbers are recorded using the byte order of the application binary.
- 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 16 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.
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.
+ The pool of section numbers begins immediately following the hash table
+ (at offset 16 + 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.
+
+ ---
+
+ DWP Version 2:
+
+ DWP Version 2 combines all the .debug_info, etc. sections into one,
+ and the entries in the index tables are now offsets into these sections.
+ CU offsets begin at 0. TU offsets begin at the size of the .debug_info
+ section.
+
+ Index Section Contents:
+ Header
+ Hash Table of Signatures dwp_hash_table.hash_table
+ Parallel Table of Indices dwp_hash_table.unit_table
+ Table of Section Offsets dwp_hash_table.v2.{section_ids,offsets}
+ Table of Section Sizes dwp_hash_table.v2.sizes
+
+ The index section header consists of:
+
+ V, 32 bit version number
+ L, 32 bit number of columns in the table of section offsets
+ N, 32 bit number of compilation units or type units in the index
+ M, 32 bit number of slots in the hash table
+
+ Numbers are recorded using the byte order of the application binary.
+
+ The hash table has the same format as version 1.
+ The parallel table of indices has the same format as version 1,
+ except that the entries are origin-1 indices into the table of sections
+ offsets and the table of section sizes.
+
+ The table of offsets begins immediately following the parallel table
+ (at offset 16 + 12 * M from the beginning of the section). The table is
+ a two-dimensional array of 32-bit words (using the byte order of the
+ application binary), with L columns and N+1 rows, in row-major order.
+ Each row in the array is indexed starting from 0. The first row provides
+ a key to the remaining rows: each column in this row provides an identifier
+ for a debug section, and the offsets in the same column of subsequent rows
+ refer to that section. The section identifiers are:
+
+ DW_SECT_INFO 1 .debug_info.dwo
+ DW_SECT_TYPES 2 .debug_types.dwo
+ DW_SECT_ABBREV 3 .debug_abbrev.dwo
+ DW_SECT_LINE 4 .debug_line.dwo
+ DW_SECT_LOC 5 .debug_loc.dwo
+ DW_SECT_STR_OFFSETS 6 .debug_str_offsets.dwo
+ DW_SECT_MACINFO 7 .debug_macinfo.dwo
+ DW_SECT_MACRO 8 .debug_macro.dwo
+
+ The offsets provided by the CU and TU index sections are the base offsets
+ for the contributions made by each CU or TU to the corresponding section
+ in the package file. Each CU and TU header contains an abbrev_offset
+ field, used to find the abbreviations table for that CU or TU within the
+ contribution to the .debug_abbrev.dwo section for that CU or TU, and should
+ be interpreted as relative to the base offset given in the index section.
+ Likewise, offsets into .debug_line.dwo from DW_AT_stmt_list attributes
+ should be interpreted as relative to the base offset for .debug_line.dwo,
+ and offsets into other debug sections obtained from DWARF attributes should
+ also be interpreted as relative to the corresponding base offset.
+
+ The table of sizes begins immediately following the table of offsets.
+ Like the table of offsets, it is a two-dimensional array of 32-bit words,
+ with L columns and N rows, in row-major order. Each row in the array is
+ indexed starting from 1 (row 0 is shared by the two tables).
+
+ ---
+
+ Hash table lookup is handled the same in version 1 and 2:
+
+ 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.
+
Given a 64-bit compilation unit signature or a type signature S, an entry
in the hash table is located as follows:
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 16 + 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. */
+ to stop at an unused slot or find the match. */
/* Create a hash table to map DWO IDs to their CU/TU entry in
.debug_{info,types}.dwo in DWP_FILE.
bfd *dbfd = dwp_file->dbfd;
const gdb_byte *index_ptr, *index_end;
struct dwarf2_section_info *index;
- uint32_t version, nr_units, nr_slots;
+ uint32_t version, nr_columns, nr_units, nr_slots;
struct dwp_hash_table *htab;
if (is_debug_types)
index_end = index_ptr + index->size;
version = read_4_bytes (dbfd, index_ptr);
- index_ptr += 8; /* Skip the unused word. */
+ index_ptr += 4;
+ if (version == 2)
+ nr_columns = read_4_bytes (dbfd, index_ptr);
+ else
+ nr_columns = 0;
+ index_ptr += 4;
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)
+ if (version != 1 && version != 2)
{
error (_("Dwarf Error: unsupported DWP file version (%s)"
" [in module %s]"),
}
htab = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwp_hash_table);
+ htab->version = version;
+ htab->nr_columns = nr_columns;
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;
+
+ /* Exit early if the table is empty. */
+ if (nr_slots == 0 || nr_units == 0
+ || (version == 2 && nr_columns == 0))
+ {
+ /* All must be zero. */
+ if (nr_slots != 0 || nr_units != 0
+ || (version == 2 && nr_columns != 0))
+ {
+ complaint (&symfile_complaints,
+ _("Empty DWP but nr_slots,nr_units,nr_columns not"
+ " all zero [in modules %s]"),
+ dwp_file->name);
+ }
+ return htab;
+ }
+
+ if (version == 1)
+ {
+ htab->section_pool.v1.indices =
+ htab->unit_table + sizeof (uint32_t) * nr_slots;
+ /* It's harder to decide whether the section is too small in v1.
+ V1 is deprecated anyway so we punt. */
+ }
+ else
+ {
+ const gdb_byte *ids_ptr = htab->unit_table + sizeof (uint32_t) * nr_slots;
+ int *ids = htab->section_pool.v2.section_ids;
+ /* Reverse map for error checking. */
+ int ids_seen[DW_SECT_MAX + 1];
+ int i;
+
+ if (nr_columns < 2)
+ {
+ error (_("Dwarf Error: bad DWP hash table, too few columns"
+ " in section table [in module %s]"),
+ dwp_file->name);
+ }
+ if (nr_columns > MAX_NR_V2_DWO_SECTIONS)
+ {
+ error (_("Dwarf Error: bad DWP hash table, too many columns"
+ " in section table [in module %s]"),
+ dwp_file->name);
+ }
+ memset (ids, 255, (DW_SECT_MAX + 1) * sizeof (int32_t));
+ memset (ids_seen, 255, (DW_SECT_MAX + 1) * sizeof (int32_t));
+ for (i = 0; i < nr_columns; ++i)
+ {
+ int id = read_4_bytes (dbfd, ids_ptr + i * sizeof (uint32_t));
+
+ if (id < DW_SECT_MIN || id > DW_SECT_MAX)
+ {
+ error (_("Dwarf Error: bad DWP hash table, bad section id %d"
+ " in section table [in module %s]"),
+ id, dwp_file->name);
+ }
+ if (ids_seen[id] != -1)
+ {
+ error (_("Dwarf Error: bad DWP hash table, duplicate section"
+ " id %d in section table [in module %s]"),
+ id, dwp_file->name);
+ }
+ ids_seen[id] = i;
+ ids[i] = id;
+ }
+ /* Must have exactly one info or types section. */
+ if (((ids_seen[DW_SECT_INFO] != -1)
+ + (ids_seen[DW_SECT_TYPES] != -1))
+ != 1)
+ {
+ error (_("Dwarf Error: bad DWP hash table, missing/duplicate"
+ " DWO info/types section [in module %s]"),
+ dwp_file->name);
+ }
+ /* Must have an abbrev section. */
+ if (ids_seen[DW_SECT_ABBREV] == -1)
+ {
+ error (_("Dwarf Error: bad DWP hash table, missing DWO abbrev"
+ " section [in module %s]"),
+ dwp_file->name);
+ }
+ htab->section_pool.v2.offsets = ids_ptr + sizeof (uint32_t) * nr_columns;
+ htab->section_pool.v2.sizes =
+ htab->section_pool.v2.offsets + (sizeof (uint32_t)
+ * nr_units * nr_columns);
+ if ((htab->section_pool.v2.sizes + (sizeof (uint32_t)
+ * nr_units * nr_columns))
+ > index_end)
+ {
+ error (_("Dwarf Error: DWP index section is corrupt (too small)"
+ " [in module %s]"),
+ dwp_file->name);
+ }
+ }
return htab;
}
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.
+ read comes from the DWP V1 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)
+locate_v1_virtual_dwo_sections (asection *sectp,
+ struct virtual_v1_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)
+ if (sections->abbrev.s.asection != NULL)
return 0;
- sections->abbrev.asection = sectp;
+ sections->abbrev.s.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)
+ if (sections->info_or_types.s.asection != NULL)
return 0;
- sections->info_or_types.asection = sectp;
+ sections->info_or_types.s.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)
+ if (sections->line.s.asection != NULL)
return 0;
- sections->line.asection = sectp;
+ sections->line.s.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)
+ if (sections->loc.s.asection != NULL)
return 0;
- sections->loc.asection = sectp;
+ sections->loc.s.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)
+ if (sections->macinfo.s.asection != NULL)
return 0;
- sections->macinfo.asection = sectp;
+ sections->macinfo.s.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)
+ if (sections->macro.s.asection != NULL)
return 0;
- sections->macro.asection = sectp;
+ sections->macro.s.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)
+ if (sections->str_offsets.s.asection != NULL)
return 0;
- sections->str_offsets.asection = sectp;
+ sections->str_offsets.s.asection = sectp;
sections->str_offsets.size = bfd_get_section_size (sectp);
}
else
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.
- COMP_DIR is the DW_AT_comp_dir attribute of the referencing CU. */
+/* Create a dwo_unit object for the DWO unit with signature SIGNATURE.
+ UNIT_INDEX is the index of the DWO unit in the DWP hash table.
+ COMP_DIR is the DW_AT_comp_dir attribute of the referencing CU.
+ This is for DWP version 1 files. */
static struct dwo_unit *
-create_dwo_in_dwp (struct dwp_file *dwp_file,
- const struct dwp_hash_table *htab,
- uint32_t section_index,
- const char *comp_dir,
- ULONGEST signature, int is_debug_types)
+create_dwo_unit_in_dwp_v1 (struct dwp_file *dwp_file,
+ uint32_t unit_index,
+ const char *comp_dir,
+ ULONGEST signature, int is_debug_types)
{
struct objfile *objfile = dwarf2_per_objfile->objfile;
+ const struct dwp_hash_table *dwp_htab =
+ is_debug_types ? dwp_file->tus : dwp_file->cus;
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;
+ struct virtual_v1_dwo_sections sections;
void **dwo_file_slot;
char *virtual_dwo_name;
struct dwarf2_section_info *cutu;
struct cleanup *cleanups;
int i;
+ gdb_assert (dwp_file->version == 1);
+
if (dwarf2_read_debug)
{
- fprintf_unfiltered (gdb_stdlog, "Reading %s %s/%s in DWP file: %s\n",
+ fprintf_unfiltered (gdb_stdlog, "Reading %s %s/%s in DWP V1 file: %s\n",
kind,
- pulongest (section_index), hex_string (signature),
+ pulongest (unit_index), hex_string (signature),
dwp_file->name);
}
- /* Fetch the sections of this DWO.
+ /* Fetch the sections of this DWO unit.
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 \
+#define MAX_NR_V1_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 /* .debug_macro or .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)
+ for (i = 0; i < MAX_NR_V1_DWO_SECTIONS; ++i)
{
asection *sectp;
uint32_t section_nr =
read_4_bytes (dbfd,
- htab->section_pool
- + (section_index + i) * sizeof (uint32_t));
+ dwp_htab->section_pool.v1.indices
+ + (unit_index + i) * sizeof (uint32_t));
if (section_nr == 0)
break;
}
sectp = dwp_file->elf_sections[section_nr];
- if (! locate_virtual_dwo_sections (sectp, §ions))
+ if (! locate_v1_virtual_dwo_sections (sectp, §ions))
{
error (_("Dwarf Error: bad DWP hash table, invalid section found"
" [in module %s]"),
" [in module %s]"),
dwp_file->name);
}
- if (i == MAX_NR_DWO_SECTIONS)
+ if (i == MAX_NR_V1_DWO_SECTIONS)
{
error (_("Dwarf Error: bad DWP hash table, too many DWO sections"
" [in module %s]"),
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",
- get_section_id (§ions.abbrev),
- get_section_id (§ions.line),
- get_section_id (§ions.loc),
- get_section_id (§ions.str_offsets));
+ xstrprintf ("virtual-dwo/%d-%d-%d-%d",
+ get_section_id (§ions.abbrev),
+ get_section_id (§ions.line),
+ get_section_id (§ions.loc),
+ get_section_id (§ions.str_offsets));
+ make_cleanup (xfree, virtual_dwo_name);
+ /* Can we use an existing virtual DWO file? */
+ dwo_file_slot = lookup_dwo_file_slot (virtual_dwo_name, comp_dir);
+ /* 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->dwo_name = obstack_copy0 (&objfile->objfile_obstack,
+ virtual_dwo_name,
+ strlen (virtual_dwo_name));
+ dwo_file->comp_dir = comp_dir;
+ 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 below 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 copies of pointers into the previous
+ contents. */
+ *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->section = obstack_alloc (&objfile->objfile_obstack,
+ sizeof (struct dwarf2_section_info));
+ *dwo_unit->section = sections.info_or_types;
+ /* dwo_unit->{offset,length,type_offset_in_tu} are set later. */
+
+ return dwo_unit;
+}
+
+/* Subroutine of create_dwo_unit_in_dwp_v2 to simplify it.
+ Given a pointer to the containing section SECTION, and OFFSET,SIZE of the
+ piece within that section used by a TU/CU, return a virtual section
+ of just that piece. */
+
+static struct dwarf2_section_info
+create_dwp_v2_section (struct dwarf2_section_info *section,
+ bfd_size_type offset, bfd_size_type size)
+{
+ struct dwarf2_section_info result;
+ asection *sectp;
+
+ gdb_assert (section != NULL);
+ gdb_assert (!section->is_virtual);
+
+ memset (&result, 0, sizeof (result));
+ result.s.containing_section = section;
+ result.is_virtual = 1;
+
+ if (size == 0)
+ return result;
+
+ sectp = get_section_bfd_section (section);
+
+ /* Flag an error if the piece denoted by OFFSET,SIZE is outside the
+ bounds of the real section. This is a pretty-rare event, so just
+ flag an error (easier) instead of a warning and trying to cope. */
+ if (sectp == NULL
+ || offset + size > bfd_get_section_size (sectp))
+ {
+ bfd *abfd = sectp->owner;
+
+ error (_("Dwarf Error: Bad DWP V2 section info, doesn't fit"
+ " in section %s [in module %s]"),
+ sectp ? bfd_section_name (abfd, sectp) : "<unknown>",
+ objfile_name (dwarf2_per_objfile->objfile));
+ }
+
+ result.virtual_offset = offset;
+ result.size = size;
+ return result;
+}
+
+/* Create a dwo_unit object for the DWO unit with signature SIGNATURE.
+ UNIT_INDEX is the index of the DWO unit in the DWP hash table.
+ COMP_DIR is the DW_AT_comp_dir attribute of the referencing CU.
+ This is for DWP version 2 files. */
+
+static struct dwo_unit *
+create_dwo_unit_in_dwp_v2 (struct dwp_file *dwp_file,
+ uint32_t unit_index,
+ const char *comp_dir,
+ ULONGEST signature, int is_debug_types)
+{
+ struct objfile *objfile = dwarf2_per_objfile->objfile;
+ const struct dwp_hash_table *dwp_htab =
+ is_debug_types ? dwp_file->tus : dwp_file->cus;
+ 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_v2_dwo_sections sections;
+ void **dwo_file_slot;
+ char *virtual_dwo_name;
+ struct dwarf2_section_info *cutu;
+ struct cleanup *cleanups;
+ int i;
+
+ gdb_assert (dwp_file->version == 2);
+
+ if (dwarf2_read_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog, "Reading %s %s/%s in DWP V2 file: %s\n",
+ kind,
+ pulongest (unit_index), hex_string (signature),
+ dwp_file->name);
+ }
+
+ /* Fetch the section offsets of this DWO unit. */
+
+ memset (§ions, 0, sizeof (sections));
+ cleanups = make_cleanup (null_cleanup, 0);
+
+ for (i = 0; i < dwp_htab->nr_columns; ++i)
+ {
+ uint32_t offset = read_4_bytes (dbfd,
+ dwp_htab->section_pool.v2.offsets
+ + (((unit_index - 1) * dwp_htab->nr_columns
+ + i)
+ * sizeof (uint32_t)));
+ uint32_t size = read_4_bytes (dbfd,
+ dwp_htab->section_pool.v2.sizes
+ + (((unit_index - 1) * dwp_htab->nr_columns
+ + i)
+ * sizeof (uint32_t)));
+
+ switch (dwp_htab->section_pool.v2.section_ids[i])
+ {
+ case DW_SECT_INFO:
+ case DW_SECT_TYPES:
+ sections.info_or_types_offset = offset;
+ sections.info_or_types_size = size;
+ break;
+ case DW_SECT_ABBREV:
+ sections.abbrev_offset = offset;
+ sections.abbrev_size = size;
+ break;
+ case DW_SECT_LINE:
+ sections.line_offset = offset;
+ sections.line_size = size;
+ break;
+ case DW_SECT_LOC:
+ sections.loc_offset = offset;
+ sections.loc_size = size;
+ break;
+ case DW_SECT_STR_OFFSETS:
+ sections.str_offsets_offset = offset;
+ sections.str_offsets_size = size;
+ break;
+ case DW_SECT_MACINFO:
+ sections.macinfo_offset = offset;
+ sections.macinfo_size = size;
+ break;
+ case DW_SECT_MACRO:
+ sections.macro_offset = offset;
+ sections.macro_size = size;
+ break;
+ }
+ }
+
+ /* 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 can combine them back into a virtual DWO file to save space
+ (fewer struct dwo_file objects to allocate). 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/%ld-%ld-%ld-%ld",
+ (long) (sections.abbrev_size ? sections.abbrev_offset : 0),
+ (long) (sections.line_size ? sections.line_offset : 0),
+ (long) (sections.loc_size ? sections.loc_offset : 0),
+ (long) (sections.str_offsets_size
+ ? sections.str_offsets_offset : 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, comp_dir);
virtual_dwo_name,
strlen (virtual_dwo_name));
dwo_file->comp_dir = comp_dir;
- 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;
+ dwo_file->sections.abbrev =
+ create_dwp_v2_section (&dwp_file->sections.abbrev,
+ sections.abbrev_offset, sections.abbrev_size);
+ dwo_file->sections.line =
+ create_dwp_v2_section (&dwp_file->sections.line,
+ sections.line_offset, sections.line_size);
+ dwo_file->sections.loc =
+ create_dwp_v2_section (&dwp_file->sections.loc,
+ sections.loc_offset, sections.loc_size);
+ dwo_file->sections.macinfo =
+ create_dwp_v2_section (&dwp_file->sections.macinfo,
+ sections.macinfo_offset, sections.macinfo_size);
+ dwo_file->sections.macro =
+ create_dwp_v2_section (&dwp_file->sections.macro,
+ sections.macro_offset, sections.macro_size);
+ dwo_file->sections.str_offsets =
+ create_dwp_v2_section (&dwp_file->sections.str_offsets,
+ sections.str_offsets_offset,
+ sections.str_offsets_size);
/* 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 below to dwo_unit,
dwo_unit->signature = signature;
dwo_unit->section = obstack_alloc (&objfile->objfile_obstack,
sizeof (struct dwarf2_section_info));
- *dwo_unit->section = sections.info_or_types;
+ *dwo_unit->section = create_dwp_v2_section (is_debug_types
+ ? &dwp_file->sections.types
+ : &dwp_file->sections.info,
+ sections.info_or_types_offset,
+ sections.info_or_types_size);
/* dwo_unit->{offset,length,type_offset_in_tu} are set later. */
return dwo_unit;
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);
+ slot = htab_find_slot (is_debug_types
+ ? dwp_file->loaded_tus
+ : dwp_file->loaded_cus,
+ &find_dwo_cu, INSERT);
if (*slot != NULL)
return *slot;
read_4_bytes (dbfd,
dwp_htab->unit_table + hash * sizeof (uint32_t));
- *slot = create_dwo_in_dwp (dwp_file, dwp_htab, unit_index,
- comp_dir, signature, is_debug_types);
+ if (dwp_file->version == 1)
+ {
+ *slot = create_dwo_unit_in_dwp_v1 (dwp_file, unit_index,
+ comp_dir, signature,
+ is_debug_types);
+ }
+ else
+ {
+ *slot = create_dwo_unit_in_dwp_v2 (dwp_file, unit_index,
+ comp_dir, signature,
+ is_debug_types);
+ }
return *slot;
}
if (signature_in_table == 0)
If IS_DWP is TRUE, we're opening a DWP file, otherwise a DWO file.
SEARCH_CWD is true if the current directory is to be searched.
It will be searched before debug-file-directory.
+ If successful, the file is added to the bfd include table of the
+ objfile's bfd (see gdb_bfd_record_inclusion).
If unable to find/open the file, return NULL.
NOTE: This function is derived from symfile_bfd_open. */
return NULL;
}
+ /* Success. Record the bfd as having been included by the objfile's bfd.
+ This is important because things like demangled_names_hash lives in the
+ objfile's per_bfd space and may have references to things like symbol
+ names that live in the DWO/DWP file's per_bfd space. PR 16426. */
+ gdb_bfd_record_inclusion (dwarf2_per_objfile->objfile->obfd, sym_bfd);
+
return sym_bfd;
}
if (section_is_p (sectp->name, &names->abbrev_dwo))
{
- dwo_sections->abbrev.asection = sectp;
+ dwo_sections->abbrev.s.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.s.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.s.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.s.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.s.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.s.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.s.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.s.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.s.asection = sectp;
type_section.size = bfd_get_section_size (sectp);
VEC_safe_push (dwarf2_section_info_def, dwo_sections->types,
&type_section);
}
/* This function is mapped across the sections and remembers the offset and
- size of each of the DWP debugging sections we are interested in. */
+ size of each of the DWP debugging sections common to version 1 and 2 that
+ we are interested in. */
static void
-dwarf2_locate_dwp_sections (bfd *abfd, asection *sectp, void *dwp_file_ptr)
+dwarf2_locate_common_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. */
+ .debug_cu_index,.debug_tu_index tables use in DWP V1. */
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.s.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.s.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.s.asection = sectp;
dwp_file->sections.tu_index.size = bfd_get_section_size (sectp);
}
}
+/* This function is mapped across the sections and remembers the offset and
+ size of each of the DWP version 2 debugging sections that we are interested
+ in. This is split into a separate function because we don't know if we
+ have version 1 or 2 until we parse the cu_index/tu_index sections. */
+
+static void
+dwarf2_locate_v2_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 in DWP V1. */
+ 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->abbrev_dwo))
+ {
+ dwp_file->sections.abbrev.s.asection = sectp;
+ dwp_file->sections.abbrev.size = bfd_get_section_size (sectp);
+ }
+ else if (section_is_p (sectp->name, &names->info_dwo))
+ {
+ dwp_file->sections.info.s.asection = sectp;
+ dwp_file->sections.info.size = bfd_get_section_size (sectp);
+ }
+ else if (section_is_p (sectp->name, &names->line_dwo))
+ {
+ dwp_file->sections.line.s.asection = sectp;
+ dwp_file->sections.line.size = bfd_get_section_size (sectp);
+ }
+ else if (section_is_p (sectp->name, &names->loc_dwo))
+ {
+ dwp_file->sections.loc.s.asection = sectp;
+ dwp_file->sections.loc.size = bfd_get_section_size (sectp);
+ }
+ else if (section_is_p (sectp->name, &names->macinfo_dwo))
+ {
+ dwp_file->sections.macinfo.s.asection = sectp;
+ dwp_file->sections.macinfo.size = bfd_get_section_size (sectp);
+ }
+ else if (section_is_p (sectp->name, &names->macro_dwo))
+ {
+ dwp_file->sections.macro.s.asection = sectp;
+ dwp_file->sections.macro.size = bfd_get_section_size (sectp);
+ }
+ else if (section_is_p (sectp->name, &names->str_offsets_dwo))
+ {
+ dwp_file->sections.str_offsets.s.asection = sectp;
+ dwp_file->sections.str_offsets.size = bfd_get_section_size (sectp);
+ }
+ else if (section_is_p (sectp->name, &names->types_dwo))
+ {
+ dwp_file->sections.types.s.asection = sectp;
+ dwp_file->sections.types.size = bfd_get_section_size (sectp);
+ }
+}
+
/* Hash function for dwp_file loaded CUs/TUs. */
static hashval_t
OBSTACK_CALLOC (&objfile->objfile_obstack,
dwp_file->num_sections, asection *);
- bfd_map_over_sections (dbfd, dwarf2_locate_dwp_sections, dwp_file);
+ bfd_map_over_sections (dbfd, dwarf2_locate_common_dwp_sections, dwp_file);
dwp_file->cus = create_dwp_hash_table (dwp_file, 0);
dwp_file->tus = create_dwp_hash_table (dwp_file, 1);
- dwp_file->loaded_cutus = allocate_dwp_loaded_cutus_table (objfile);
+ /* The DWP file version is stored in the hash table. Oh well. */
+ if (dwp_file->cus->version != dwp_file->tus->version)
+ {
+ /* Technically speaking, we should try to limp along, but this is
+ pretty bizarre. We use pulongest here because that's the established
+ portability solution (e.g, we cannot use %u for uint32_t). */
+ error (_("Dwarf Error: DWP file CU version %s doesn't match"
+ " TU version %s [in DWP file %s]"),
+ pulongest (dwp_file->cus->version),
+ pulongest (dwp_file->tus->version), dwp_name);
+ }
+ dwp_file->version = dwp_file->cus->version;
+
+ if (dwp_file->version == 2)
+ bfd_map_over_sections (dbfd, dwarf2_locate_v2_dwp_sections, dwp_file);
+
+ dwp_file->loaded_cus = allocate_dwp_loaded_cutus_table (objfile);
+ dwp_file->loaded_tus = allocate_dwp_loaded_cutus_table (objfile);
if (dwarf2_read_debug)
{
/* This is a warning and not a complaint because it can be caused by
pilot error (e.g., user accidentally deleting the DWO). */
- warning (_("Could not find DWO %s %s(%s) referenced by %s at offset 0x%x"
- " [in module %s]"),
- kind, dwo_name, hex_string (signature),
- this_unit->is_debug_types ? "TU" : "CU",
- this_unit->offset.sect_off, objfile_name (objfile));
+ {
+ /* Print the name of the DWP file if we looked there, helps the user
+ better diagnose the problem. */
+ char *dwp_text = NULL;
+ struct cleanup *cleanups;
+
+ if (dwp_file != NULL)
+ dwp_text = xstrprintf (" [in DWP file %s]", lbasename (dwp_file->name));
+ cleanups = make_cleanup (xfree, dwp_text);
+
+ warning (_("Could not find DWO %s %s(%s)%s referenced by %s at offset 0x%x"
+ " [in module %s]"),
+ kind, dwo_name, hex_string (signature),
+ dwp_text != NULL ? dwp_text : "",
+ this_unit->is_debug_types ? "TU" : "CU",
+ this_unit->offset.sect_off, objfile_name (objfile));
+
+ do_cleanups (cleanups);
+ }
return NULL;
}
if (offsetp >= offsets_end
|| offsetp->sect_off > origin_child_die->offset.sect_off)
{
- /* Found that ORIGIN_CHILD_DIE is really not referenced. */
- process_die (origin_child_die, origin_cu);
+ /* Found that ORIGIN_CHILD_DIE is really not referenced.
+ Check whether we're already processing ORIGIN_CHILD_DIE.
+ This can happen with mutually referenced abstract_origins.
+ PR 16581. */
+ if (!origin_child_die->in_process)
+ process_die (origin_child_die, origin_cu);
}
origin_child_die = sibling_die (origin_child_die);
}
die->offset.sect_off, objfile_name (objfile));
return;
}
- pc = DW_ADDR (attr) + baseaddr;
+ pc = attr_value_as_address (attr) + baseaddr;
if (cu->call_site_htab == NULL)
cu->call_site_htab = htab_create_alloc_ex (16, core_addr_hash, core_addr_eq,
attr = dwarf2_attr (die, DW_AT_low_pc, cu);
if (attr)
{
- low = DW_ADDR (attr);
- if (attr_high->form == DW_FORM_addr
- || attr_high->form == DW_FORM_GNU_addr_index)
- high = DW_ADDR (attr_high);
- else
- high = low + DW_UNSND (attr_high);
+ low = attr_value_as_address (attr);
+ high = attr_value_as_address (attr_high);
+ if (cu->header.version >= 4 && attr_form_is_constant (attr_high))
+ high += low;
}
else
/* Found high w/o low attribute. */
attr = dwarf2_attr (die, DW_AT_low_pc, cu);
if (attr)
{
- CORE_ADDR low = DW_ADDR (attr);
- CORE_ADDR high;
- if (attr_high->form == DW_FORM_addr
- || attr_high->form == DW_FORM_GNU_addr_index)
- high = DW_ADDR (attr_high);
- else
- high = low + DW_UNSND (attr_high);
+ CORE_ADDR low = attr_value_as_address (attr);
+ CORE_ADDR high = attr_value_as_address (attr_high);
+
+ if (cu->header.version >= 4 && attr_form_is_constant (attr_high))
+ high += low;
record_block_range (block, baseaddr + low, baseaddr + high - 1);
}
/* Called when we find the DIE that starts a structure or union scope
(definition) to create a type for the structure or union. Fill in
the type's name and general properties; the members will not be
- processed until process_structure_scope.
+ processed until process_structure_scope. A symbol table entry for
+ the type will also not be done until process_structure_scope (assuming
+ the type has a name).
NOTE: we need to call these functions regardless of whether or not the
DIE has a DW_AT_name attribute, since it might be an anonymous
structure or union. This gets the type entered into our set of
- user defined types.
-
- However, if the structure is incomplete (an opaque struct/union)
- then suppress creating a symbol table entry for it since gdb only
- wants to find the one with the complete definition. Note that if
- it is complete, we just call new_symbol, which does it's own
- checking about whether the struct/union is anonymous or not (and
- suppresses creating a symbol table entry itself). */
+ user defined types. */
static struct type *
read_structure_type (struct die_info *die, struct dwarf2_cu *cu)
TYPE_LENGTH (type) = 0;
}
- if (producer_is_icc (cu))
+ if (producer_is_icc (cu) && (TYPE_LENGTH (type) == 0))
{
/* ICC does not output the required DW_AT_declaration
on incomplete types, but gives them a size of zero. */
+ TYPE_STUB (type) = 1;
}
else
TYPE_STUB_SUPPORTED (type) = 1;
new_symbol (die, type, cu);
}
+/* Assuming DIE is an enumeration type, and TYPE is its associated type,
+ update TYPE using some information only available in DIE's children. */
+
+static void
+update_enumeration_type_from_children (struct die_info *die,
+ struct type *type,
+ struct dwarf2_cu *cu)
+{
+ struct obstack obstack;
+ struct die_info *child_die = die->child;
+ int unsigned_enum = 1;
+ int flag_enum = 1;
+ ULONGEST mask = 0;
+ struct cleanup *old_chain;
+
+ obstack_init (&obstack);
+ old_chain = make_cleanup_obstack_free (&obstack);
+
+ while (child_die != NULL && child_die->tag)
+ {
+ struct attribute *attr;
+ LONGEST value;
+ const gdb_byte *bytes;
+ struct dwarf2_locexpr_baton *baton;
+ const char *name;
+ if (child_die->tag != DW_TAG_enumerator)
+ continue;
+
+ attr = dwarf2_attr (child_die, DW_AT_const_value, cu);
+ if (attr == NULL)
+ continue;
+
+ name = dwarf2_name (child_die, cu);
+ if (name == NULL)
+ name = "<anonymous enumerator>";
+
+ dwarf2_const_value_attr (attr, type, name, &obstack, cu,
+ &value, &bytes, &baton);
+ if (value < 0)
+ {
+ unsigned_enum = 0;
+ flag_enum = 0;
+ }
+ else if ((mask & value) != 0)
+ flag_enum = 0;
+ else
+ mask |= value;
+
+ /* If we already know that the enum type is neither unsigned, nor
+ a flag type, no need to look at the rest of the enumerates. */
+ if (!unsigned_enum && !flag_enum)
+ break;
+ child_die = sibling_die (child_die);
+ }
+
+ if (unsigned_enum)
+ TYPE_UNSIGNED (type) = 1;
+ if (flag_enum)
+ TYPE_FLAG_ENUM (type) = 1;
+
+ do_cleanups (old_chain);
+}
+
/* Given a DW_AT_enumeration_type die, set its type. We do not
complete the type's fields yet, or create any symbols. */
if (name != NULL)
TYPE_TAG_NAME (type) = name;
+ attr = dwarf2_attr (die, DW_AT_type, cu);
+ if (attr != NULL)
+ {
+ struct type *underlying_type = die_type (die, cu);
+
+ TYPE_TARGET_TYPE (type) = underlying_type;
+ }
+
attr = dwarf2_attr (die, DW_AT_byte_size, cu);
if (attr)
{
if (die_is_declaration (die, cu))
TYPE_STUB (type) = 1;
+ /* Finish the creation of this type by using the enum's children.
+ We must call this even when the underlying type has been provided
+ so that we can determine if we're looking at a "flag" enum. */
+ update_enumeration_type_from_children (die, type, cu);
+
+ /* If this type has an underlying type that is not a stub, then we
+ may use its attributes. We always use the "unsigned" attribute
+ in this situation, because ordinarily we guess whether the type
+ is unsigned -- but the guess can be wrong and the underlying type
+ can tell us the reality. However, we defer to a local size
+ attribute if one exists, because this lets the compiler override
+ the underlying type if needed. */
+ if (TYPE_TARGET_TYPE (type) != NULL && !TYPE_STUB (TYPE_TARGET_TYPE (type)))
+ {
+ TYPE_UNSIGNED (type) = TYPE_UNSIGNED (TYPE_TARGET_TYPE (type));
+ if (TYPE_LENGTH (type) == 0)
+ TYPE_LENGTH (type) = TYPE_LENGTH (TYPE_TARGET_TYPE (type));
+ }
+
+ TYPE_DECLARED_CLASS (type) = dwarf2_flag_true_p (die, DW_AT_enum_class, cu);
+
return set_die_type (die, type, cu);
}
struct symbol *sym;
struct field *fields = NULL;
int num_fields = 0;
- int unsigned_enum = 1;
const char *name;
- int flag_enum = 1;
- ULONGEST mask = 0;
child_die = die->child;
while (child_die && child_die->tag)
if (name)
{
sym = new_symbol (child_die, this_type, cu);
- if (SYMBOL_VALUE (sym) < 0)
- {
- unsigned_enum = 0;
- flag_enum = 0;
- }
- else if ((mask & SYMBOL_VALUE (sym)) != 0)
- flag_enum = 0;
- else
- mask |= SYMBOL_VALUE (sym);
if ((num_fields % DW_FIELD_ALLOC_CHUNK) == 0)
{
sizeof (struct field) * num_fields);
xfree (fields);
}
- if (unsigned_enum)
- TYPE_UNSIGNED (this_type) = 1;
- if (flag_enum)
- TYPE_FLAG_ENUM (this_type) = 1;
}
/* If we are reading an enum from a .debug_types unit, and the enum
int ndim = 0;
struct cleanup *back_to;
const char *name;
+ unsigned int bit_stride = 0;
element_type = die_type (die, cu);
if (type)
return type;
+ attr = dwarf2_attr (die, DW_AT_byte_stride, cu);
+ if (attr != NULL)
+ bit_stride = DW_UNSND (attr) * 8;
+
+ attr = dwarf2_attr (die, DW_AT_bit_stride, cu);
+ if (attr != NULL)
+ bit_stride = DW_UNSND (attr);
+
/* Irix 6.2 native cc creates array types without children for
arrays with unspecified length. */
if (die->child == NULL)
{
index_type = objfile_type (objfile)->builtin_int;
- range_type = create_range_type (NULL, index_type, 0, -1);
- type = create_array_type (NULL, element_type, range_type);
+ range_type = create_static_range_type (NULL, index_type, 0, -1);
+ type = create_array_type_with_stride (NULL, element_type, range_type,
+ bit_stride);
return set_die_type (die, type, cu);
}
int i = 0;
while (i < ndim)
- type = create_array_type (NULL, type, range_types[i++]);
+ type = create_array_type_with_stride (NULL, type, range_types[i++],
+ bit_stride);
}
else
{
while (ndim-- > 0)
- type = create_array_type (NULL, type, range_types[ndim]);
+ type = create_array_type_with_stride (NULL, type, range_types[ndim],
+ bit_stride);
}
/* Understand Dwarf2 support for vector types (like they occur on
read_module (struct die_info *die, struct dwarf2_cu *cu)
{
struct die_info *child_die = die->child;
+ struct type *type;
+
+ type = read_type_die (die, cu);
+ new_symbol (die, type, cu);
while (child_die && child_die->tag)
{
return set_die_type (die, type, cu);
}
+/* Add the given cv-qualifiers to the element type of the array. GCC
+ outputs DWARF type qualifiers that apply to an array, not the
+ element type. But GDB relies on the array element type to carry
+ the cv-qualifiers. This mimics section 6.7.3 of the C99
+ specification. */
+
+static struct type *
+add_array_cv_type (struct die_info *die, struct dwarf2_cu *cu,
+ struct type *base_type, int cnst, int voltl)
+{
+ struct type *el_type, *inner_array;
+
+ base_type = copy_type (base_type);
+ inner_array = base_type;
+
+ while (TYPE_CODE (TYPE_TARGET_TYPE (inner_array)) == TYPE_CODE_ARRAY)
+ {
+ TYPE_TARGET_TYPE (inner_array) =
+ copy_type (TYPE_TARGET_TYPE (inner_array));
+ inner_array = TYPE_TARGET_TYPE (inner_array);
+ }
+
+ el_type = TYPE_TARGET_TYPE (inner_array);
+ cnst |= TYPE_CONST (el_type);
+ voltl |= TYPE_VOLATILE (el_type);
+ TYPE_TARGET_TYPE (inner_array) = make_cv_type (cnst, voltl, el_type, NULL);
+
+ return set_die_type (die, base_type, cu);
+}
+
static struct type *
read_tag_const_type (struct die_info *die, struct dwarf2_cu *cu)
{
/* In case the const qualifier is applied to an array type, the element type
is so qualified, not the array type (section 6.7.3 of C99). */
if (TYPE_CODE (base_type) == TYPE_CODE_ARRAY)
- {
- struct type *el_type, *inner_array;
-
- base_type = copy_type (base_type);
- inner_array = base_type;
-
- while (TYPE_CODE (TYPE_TARGET_TYPE (inner_array)) == TYPE_CODE_ARRAY)
- {
- TYPE_TARGET_TYPE (inner_array) =
- copy_type (TYPE_TARGET_TYPE (inner_array));
- inner_array = TYPE_TARGET_TYPE (inner_array);
- }
-
- el_type = TYPE_TARGET_TYPE (inner_array);
- TYPE_TARGET_TYPE (inner_array) =
- make_cv_type (1, TYPE_VOLATILE (el_type), el_type, NULL);
-
- return set_die_type (die, base_type, cu);
- }
+ return add_array_cv_type (die, cu, base_type, 1, 0);
cv_type = make_cv_type (1, TYPE_VOLATILE (base_type), base_type, 0);
return set_die_type (die, cv_type, cu);
if (cv_type)
return cv_type;
+ /* In case the volatile qualifier is applied to an array type, the
+ element type is so qualified, not the array type (section 6.7.3
+ of C99). */
+ if (TYPE_CODE (base_type) == TYPE_CODE_ARRAY)
+ return add_array_cv_type (die, cu, base_type, 0, 1);
+
cv_type = make_cv_type (TYPE_CONST (base_type), 1, base_type, 0);
return set_die_type (die, cv_type, cu);
}
}
index_type = objfile_type (objfile)->builtin_int;
- range_type = create_range_type (NULL, index_type, 1, length);
+ range_type = create_static_range_type (NULL, index_type, 1, length);
char_type = language_string_char_type (cu->language_defn, gdbarch);
type = create_string_type (NULL, char_type, range_type);
return set_die_type (die, type, cu);
}
+/* Parse dwarf attribute if it's a block, reference or constant and put the
+ resulting value of the attribute into struct bound_prop.
+ Returns 1 if ATTR could be resolved into PROP, 0 otherwise. */
+
+static int
+attr_to_dynamic_prop (const struct attribute *attr, struct die_info *die,
+ struct dwarf2_cu *cu, struct dynamic_prop *prop)
+{
+ struct dwarf2_property_baton *baton;
+ struct obstack *obstack = &cu->objfile->objfile_obstack;
+
+ if (attr == NULL || prop == NULL)
+ return 0;
+
+ if (attr_form_is_block (attr))
+ {
+ baton = obstack_alloc (obstack, sizeof (*baton));
+ baton->referenced_type = NULL;
+ baton->locexpr.per_cu = cu->per_cu;
+ baton->locexpr.size = DW_BLOCK (attr)->size;
+ baton->locexpr.data = DW_BLOCK (attr)->data;
+ prop->data.baton = baton;
+ prop->kind = PROP_LOCEXPR;
+ gdb_assert (prop->data.baton != NULL);
+ }
+ else if (attr_form_is_ref (attr))
+ {
+ struct dwarf2_cu *target_cu = cu;
+ struct die_info *target_die;
+ struct attribute *target_attr;
+
+ target_die = follow_die_ref (die, attr, &target_cu);
+ target_attr = dwarf2_attr (target_die, DW_AT_location, target_cu);
+ if (target_attr == NULL)
+ return 0;
+
+ if (attr_form_is_section_offset (target_attr))
+ {
+ baton = obstack_alloc (obstack, sizeof (*baton));
+ baton->referenced_type = die_type (target_die, target_cu);
+ fill_in_loclist_baton (cu, &baton->loclist, target_attr);
+ prop->data.baton = baton;
+ prop->kind = PROP_LOCLIST;
+ gdb_assert (prop->data.baton != NULL);
+ }
+ else if (attr_form_is_block (target_attr))
+ {
+ baton = obstack_alloc (obstack, sizeof (*baton));
+ baton->referenced_type = die_type (target_die, target_cu);
+ baton->locexpr.per_cu = cu->per_cu;
+ baton->locexpr.size = DW_BLOCK (target_attr)->size;
+ baton->locexpr.data = DW_BLOCK (target_attr)->data;
+ prop->data.baton = baton;
+ prop->kind = PROP_LOCEXPR;
+ gdb_assert (prop->data.baton != NULL);
+ }
+ else
+ {
+ dwarf2_invalid_attrib_class_complaint ("DW_AT_location",
+ "dynamic property");
+ return 0;
+ }
+ }
+ else if (attr_form_is_constant (attr))
+ {
+ prop->data.const_val = dwarf2_get_attr_constant_value (attr, 0);
+ prop->kind = PROP_CONST;
+ }
+ else
+ {
+ dwarf2_invalid_attrib_class_complaint (dwarf_form_name (attr->form),
+ dwarf2_name (die, cu));
+ return 0;
+ }
+
+ return 1;
+}
+
/* Read the given DW_AT_subrange DIE. */
static struct type *
struct type *base_type, *orig_base_type;
struct type *range_type;
struct attribute *attr;
- LONGEST low, high;
+ struct dynamic_prop low, high;
int low_default_is_valid;
+ int high_bound_is_count = 0;
const char *name;
LONGEST negative_mask;
if (range_type)
return range_type;
+ low.kind = PROP_CONST;
+ high.kind = PROP_CONST;
+ high.data.const_val = 0;
+
/* Set LOW_DEFAULT_IS_VALID if current language and DWARF version allow
omitting DW_AT_lower_bound. */
switch (cu->language)
{
case language_c:
case language_cplus:
- low = 0;
+ low.data.const_val = 0;
low_default_is_valid = 1;
break;
case language_fortran:
- low = 1;
+ low.data.const_val = 1;
low_default_is_valid = 1;
break;
case language_d:
case language_java:
case language_objc:
- low = 0;
+ low.data.const_val = 0;
low_default_is_valid = (cu->header.version >= 4);
break;
case language_ada:
case language_m2:
case language_pascal:
- low = 1;
+ low.data.const_val = 1;
low_default_is_valid = (cu->header.version >= 4);
break;
default:
- low = 0;
+ low.data.const_val = 0;
low_default_is_valid = 0;
break;
}
- /* FIXME: For variable sized arrays either of these could be
- a variable rather than a constant value. We'll allow it,
- but we don't know how to handle it. */
attr = dwarf2_attr (die, DW_AT_lower_bound, cu);
if (attr)
- low = dwarf2_get_attr_constant_value (attr, low);
+ attr_to_dynamic_prop (attr, die, cu, &low);
else if (!low_default_is_valid)
complaint (&symfile_complaints, _("Missing DW_AT_lower_bound "
"- DIE at 0x%x [in module %s]"),
die->offset.sect_off, objfile_name (cu->objfile));
attr = dwarf2_attr (die, DW_AT_upper_bound, cu);
- if (attr)
- {
- if (attr_form_is_block (attr) || attr_form_is_ref (attr))
- {
- /* GCC encodes arrays with unspecified or dynamic length
- with a DW_FORM_block1 attribute or a reference attribute.
- FIXME: GDB does not yet know how to handle dynamic
- arrays properly, treat them as arrays with unspecified
- length for now.
-
- FIXME: jimb/2003-09-22: GDB does not really know
- how to handle arrays of unspecified length
- either; we just represent them as zero-length
- arrays. Choose an appropriate upper bound given
- the lower bound we've computed above. */
- high = low - 1;
- }
- else
- high = dwarf2_get_attr_constant_value (attr, 1);
- }
- else
+ if (!attr_to_dynamic_prop (attr, die, cu, &high))
{
attr = dwarf2_attr (die, DW_AT_count, cu);
- if (attr)
+ if (attr_to_dynamic_prop (attr, die, cu, &high))
{
- int count = dwarf2_get_attr_constant_value (attr, 1);
- high = low + count - 1;
- }
- else
- {
- /* Unspecified array length. */
- high = low - 1;
+ /* If bounds are constant do the final calculation here. */
+ if (low.kind == PROP_CONST && high.kind == PROP_CONST)
+ high.data.const_val = low.data.const_val + high.data.const_val - 1;
+ else
+ high_bound_is_count = 1;
}
}
}
}
+ /* Normally, the DWARF producers are expected to use a signed
+ constant form (Eg. DW_FORM_sdata) to express negative bounds.
+ But this is unfortunately not always the case, as witnessed
+ with GCC, for instance, where the ambiguous DW_FORM_dataN form
+ is used instead. To work around that ambiguity, we treat
+ the bounds as signed, and thus sign-extend their values, when
+ the base type is signed. */
negative_mask =
(LONGEST) -1 << (TYPE_LENGTH (base_type) * TARGET_CHAR_BIT - 1);
- if (!TYPE_UNSIGNED (base_type) && (low & negative_mask))
- low |= negative_mask;
- if (!TYPE_UNSIGNED (base_type) && (high & negative_mask))
- high |= negative_mask;
+ if (low.kind == PROP_CONST
+ && !TYPE_UNSIGNED (base_type) && (low.data.const_val & negative_mask))
+ low.data.const_val |= negative_mask;
+ if (high.kind == PROP_CONST
+ && !TYPE_UNSIGNED (base_type) && (high.data.const_val & negative_mask))
+ high.data.const_val |= negative_mask;
- range_type = create_range_type (NULL, orig_base_type, low, high);
+ range_type = create_range_type (NULL, orig_base_type, &low, &high);
- /* Mark arrays with dynamic length at least as an array of unspecified
- length. GDB could check the boundary but before it gets implemented at
- least allow accessing the array elements. */
- if (attr && attr_form_is_block (attr))
- TYPE_HIGH_BOUND_UNDEFINED (range_type) = 1;
+ if (high_bound_is_count)
+ TYPE_RANGE_DATA (range_type)->flag_upper_bound_is_count = 1;
/* Ada expects an empty array on no boundary attributes. */
if (attr == NULL && cu->language != language_ada)
- TYPE_HIGH_BOUND_UNDEFINED (range_type) = 1;
+ TYPE_HIGH_BOUND_KIND (range_type) = PROP_UNDEFINED;
name = dwarf2_name (die, cu);
if (name)
struct attr_abbrev *cur_attrs;
unsigned int allocated_attrs;
- abbrev_table = XMALLOC (struct abbrev_table);
+ abbrev_table = XNEW (struct abbrev_table);
abbrev_table->offset = offset;
obstack_init (&abbrev_table->abbrev_obstack);
abbrev_table->abbrevs = obstack_alloc (&abbrev_table->abbrev_obstack,
/* Same as abbrev_table_free but as a cleanup.
We pass in a pointer to the pointer to the table so that we can
set the pointer to NULL when we're done. It also simplifies
- build_type_unit_groups. */
+ build_type_psymtabs_1. */
static void
abbrev_table_free_cleanup (void *table_ptr)
&& abbrev->tag != DW_TAG_namespace
&& abbrev->tag != DW_TAG_module
&& abbrev->tag != DW_TAG_member
- && abbrev->tag != DW_TAG_imported_unit)
+ && abbrev->tag != DW_TAG_imported_unit
+ && abbrev->tag != DW_TAG_imported_declaration)
{
/* Otherwise we skip to the next sibling, if any. */
info_ptr = skip_one_die (reader, info_ptr + bytes_read, abbrev);
default:
part_die->name
= dwarf2_canonicalize_name (DW_STRING (&attr), cu,
- &objfile->objfile_obstack);
+ &objfile->per_bfd->storage_obstack);
break;
}
break;
break;
case DW_AT_low_pc:
has_low_pc_attr = 1;
- part_die->lowpc = DW_ADDR (&attr);
+ part_die->lowpc = attr_value_as_address (&attr);
break;
case DW_AT_high_pc:
has_high_pc_attr = 1;
- if (attr.form == DW_FORM_addr
- || attr.form == DW_FORM_GNU_addr_index)
- part_die->highpc = DW_ADDR (&attr);
- else
- {
- high_pc_relative = 1;
- part_die->highpc = DW_UNSND (&attr);
- }
+ part_die->highpc = attr_value_as_address (&attr);
+ if (cu->header.version >= 4 && attr_form_is_constant (&attr))
+ high_pc_relative = 1;
break;
case DW_AT_location:
/* Support the .debug_loc offsets. */
complaint (&symfile_complaints,
_("ignoring absolute DW_AT_sibling"));
else
- part_die->sibling = buffer + dwarf2_get_ref_die_offset (&attr).sect_off;
+ {
+ unsigned int off = dwarf2_get_ref_die_offset (&attr).sect_off;
+ const gdb_byte *sibling_ptr = buffer + off;
+
+ if (sibling_ptr < info_ptr)
+ complaint (&symfile_complaints,
+ _("DW_AT_sibling points backwards"));
+ else if (sibling_ptr > reader->buffer_end)
+ dwarf2_section_buffer_overflow_complaint (reader->die_section);
+ else
+ part_die->sibling = sibling_ptr;
+ }
break;
case DW_AT_byte_size:
part_die->has_byte_size = 1;
practice. */
if (DW_UNSND (&attr) == DW_CC_program
&& cu->language == language_fortran)
- {
- set_main_name (part_die->name);
-
- /* As this DIE has a static linkage the name would be difficult
- to look up later. */
- language_of_main = language_fortran;
- }
+ set_objfile_main_name (objfile, part_die->name, language_fortran);
break;
case DW_AT_inline:
if (DW_UNSND (&attr) == DW_INL_inlined
if (actual_class_name != NULL)
{
struct_pdi->name
- = obstack_copy0 (&cu->objfile->objfile_obstack,
+ = obstack_copy0 (&cu->objfile->per_bfd->storage_obstack,
actual_class_name,
strlen (actual_class_name));
xfree (actual_class_name);
else
base = demangled;
- part_die->name = obstack_copy0 (&cu->objfile->objfile_obstack,
- base, strlen (base));
+ part_die->name
+ = obstack_copy0 (&cu->objfile->per_bfd->storage_obstack,
+ base, strlen (base));
xfree (demangled);
}
}
ULONGEST str_index =
read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
- DW_STRING (attr) = read_str_index (reader, cu, str_index);
+ DW_STRING (attr) = read_str_index (reader, str_index);
DW_STRING_IS_CANONICAL (attr) = 0;
info_ptr += bytes_read;
}
This is only used by the Fission support. */
static const char *
-read_str_index (const struct die_reader_specs *reader,
- struct dwarf2_cu *cu, ULONGEST str_index)
+read_str_index (const struct die_reader_specs *reader, ULONGEST str_index)
{
struct objfile *objfile = dwarf2_per_objfile->objfile;
- const char *dwo_name = objfile_name (objfile);
+ const char *objf_name = objfile_name (objfile);
bfd *abfd = objfile->obfd;
- struct dwo_sections *sections = &reader->dwo_file->sections;
+ struct dwarf2_cu *cu = reader->cu;
+ struct dwarf2_section_info *str_section = &reader->dwo_file->sections.str;
+ struct dwarf2_section_info *str_offsets_section =
+ &reader->dwo_file->sections.str_offsets;
const gdb_byte *info_ptr;
ULONGEST str_offset;
static const char form_name[] = "DW_FORM_GNU_str_index";
- dwarf2_read_section (objfile, §ions->str);
- dwarf2_read_section (objfile, §ions->str_offsets);
- if (sections->str.buffer == NULL)
+ dwarf2_read_section (objfile, str_section);
+ dwarf2_read_section (objfile, str_offsets_section);
+ if (str_section->buffer == NULL)
error (_("%s used without .debug_str.dwo section"
" in CU at offset 0x%lx [in module %s]"),
- form_name, (long) cu->header.offset.sect_off, dwo_name);
- if (sections->str_offsets.buffer == NULL)
+ form_name, (long) cu->header.offset.sect_off, objf_name);
+ if (str_offsets_section->buffer == NULL)
error (_("%s used without .debug_str_offsets.dwo section"
" in CU at offset 0x%lx [in module %s]"),
- form_name, (long) cu->header.offset.sect_off, dwo_name);
- if (str_index * cu->header.offset_size >= sections->str_offsets.size)
+ form_name, (long) cu->header.offset.sect_off, objf_name);
+ if (str_index * cu->header.offset_size >= str_offsets_section->size)
error (_("%s pointing outside of .debug_str_offsets.dwo"
" section in CU at offset 0x%lx [in module %s]"),
- form_name, (long) cu->header.offset.sect_off, dwo_name);
- info_ptr = (sections->str_offsets.buffer
+ form_name, (long) cu->header.offset.sect_off, objf_name);
+ info_ptr = (str_offsets_section->buffer
+ str_index * cu->header.offset_size);
if (cu->header.offset_size == 4)
str_offset = bfd_get_32 (abfd, info_ptr);
else
str_offset = bfd_get_64 (abfd, info_ptr);
- if (str_offset >= sections->str.size)
+ if (str_offset >= str_section->size)
error (_("Offset from %s pointing outside of"
" .debug_str.dwo section in CU at offset 0x%lx [in module %s]"),
- form_name, (long) cu->header.offset.sect_off, dwo_name);
- return (const char *) (sections->str.buffer + str_offset);
+ form_name, (long) cu->header.offset.sect_off, objf_name);
+ return (const char *) (str_section->buffer + str_offset);
}
/* Return the length of an LEB128 number in BUF. */
include_name = "hello.c"
dir_name = "."
DW_AT_comp_dir = comp_dir = "/tmp"
- DW_AT_name = "./hello.c" */
+ DW_AT_name = "./hello.c"
+
+ */
if (dir_name != NULL)
{
return;
}
+/* Return non-zero if we should add LINE to the line number table.
+ LINE is the line to add, LAST_LINE is the last line that was added,
+ LAST_SUBFILE is the subfile for LAST_LINE.
+ LINE_HAS_NON_ZERO_DISCRIMINATOR is non-zero if LINE has ever
+ had a non-zero discriminator.
+
+ We have to be careful in the presence of discriminators.
+ E.g., for this line:
+
+ for (i = 0; i < 100000; i++);
+
+ clang can emit four line number entries for that one line,
+ each with a different discriminator.
+ See gdb.dwarf2/dw2-single-line-discriminators.exp for an example.
+
+ However, we want gdb to coalesce all four entries into one.
+ Otherwise the user could stepi into the middle of the line and
+ gdb would get confused about whether the pc really was in the
+ middle of the line.
+
+ Things are further complicated by the fact that two consecutive
+ line number entries for the same line is a heuristic used by gcc
+ to denote the end of the prologue. So we can't just discard duplicate
+ entries, we have to be selective about it. The heuristic we use is
+ that we only collapse consecutive entries for the same line if at least
+ one of those entries has a non-zero discriminator. PR 17276.
+
+ Note: Addresses in the line number state machine can never go backwards
+ within one sequence, thus this coalescing is ok. */
+
+static int
+dwarf_record_line_p (unsigned int line, unsigned int last_line,
+ int line_has_non_zero_discriminator,
+ struct subfile *last_subfile)
+{
+ if (current_subfile != last_subfile)
+ return 1;
+ if (line != last_line)
+ return 1;
+ /* Same line for the same file that we've seen already.
+ As a last check, for pr 17276, only record the line if the line
+ has never had a non-zero discriminator. */
+ if (!line_has_non_zero_discriminator)
+ return 1;
+ return 0;
+}
+
+/* Use P_RECORD_LINE to record line number LINE beginning at address ADDRESS
+ in the line table of subfile SUBFILE. */
+
+static void
+dwarf_record_line (struct gdbarch *gdbarch, struct subfile *subfile,
+ unsigned int line, CORE_ADDR address,
+ record_line_ftype p_record_line)
+{
+ CORE_ADDR addr = gdbarch_addr_bits_remove (gdbarch, address);
+
+ (*p_record_line) (subfile, line, addr);
+}
+
+/* Subroutine of dwarf_decode_lines_1 to simplify it.
+ Mark the end of a set of line number records.
+ The arguments are the same as for dwarf_record_line.
+ If SUBFILE is NULL the request is ignored. */
+
+static void
+dwarf_finish_line (struct gdbarch *gdbarch, struct subfile *subfile,
+ CORE_ADDR address, record_line_ftype p_record_line)
+{
+ if (subfile != NULL)
+ dwarf_record_line (gdbarch, subfile, 0, address, p_record_line);
+}
+
/* Subroutine of dwarf_decode_lines to simplify it.
Process the line number information in LH. */
static void
dwarf_decode_lines_1 (struct line_header *lh, const char *comp_dir,
- struct dwarf2_cu *cu, struct partial_symtab *pst)
+ struct dwarf2_cu *cu, const int decode_for_pst_p,
+ CORE_ADDR lowpc)
{
const gdb_byte *line_ptr, *extended_end;
const gdb_byte *line_end;
unsigned int bytes_read, extended_len;
- unsigned char op_code, extended_op, adj_opcode;
+ unsigned char op_code, extended_op;
CORE_ADDR baseaddr;
struct objfile *objfile = cu->objfile;
bfd *abfd = objfile->obfd;
struct gdbarch *gdbarch = get_objfile_arch (objfile);
- const int decode_for_pst_p = (pst != NULL);
struct subfile *last_subfile = NULL;
void (*p_record_line) (struct subfile *subfile, int line, CORE_ADDR pc)
= record_line;
CORE_ADDR address = 0;
unsigned int file = 1;
unsigned int line = 1;
- unsigned int column = 0;
int is_stmt = lh->default_is_stmt;
- int basic_block = 0;
int end_sequence = 0;
- CORE_ADDR addr;
unsigned char op_index = 0;
+ unsigned int discriminator = 0;
+ /* The last line number that was recorded, used to coalesce
+ consecutive entries for the same line. This can happen, for
+ example, when discriminators are present. PR 17276. */
+ unsigned int last_line = 0;
+ int line_has_non_zero_discriminator = 0;
if (!decode_for_pst_p && lh->num_file_names >= file)
{
if (op_code >= lh->opcode_base)
{
- /* Special operand. */
+ /* Special opcode. */
+ unsigned char adj_opcode;
+ int line_delta;
+
adj_opcode = op_code - lh->opcode_base;
address += (((op_index + (adj_opcode / lh->line_range))
/ lh->maximum_ops_per_instruction)
* lh->minimum_instruction_length);
op_index = ((op_index + (adj_opcode / lh->line_range))
% lh->maximum_ops_per_instruction);
- line += lh->line_base + (adj_opcode % lh->line_range);
+ line_delta = lh->line_base + (adj_opcode % lh->line_range);
+ line += line_delta;
+ if (line_delta != 0)
+ line_has_non_zero_discriminator = discriminator != 0;
if (lh->num_file_names < file || file == 0)
dwarf2_debug_line_missing_file_complaint ();
/* For now we ignore lines not starting on an
{
if (last_subfile != current_subfile)
{
- addr = gdbarch_addr_bits_remove (gdbarch, address);
- if (last_subfile)
- (*p_record_line) (last_subfile, 0, addr);
- last_subfile = current_subfile;
+ dwarf_finish_line (gdbarch, last_subfile,
+ address, p_record_line);
+ }
+ if (dwarf_record_line_p (line, last_line,
+ line_has_non_zero_discriminator,
+ last_subfile))
+ {
+ dwarf_record_line (gdbarch, current_subfile,
+ line, address, p_record_line);
}
- /* Append row to matrix using current values. */
- addr = gdbarch_addr_bits_remove (gdbarch, address);
- (*p_record_line) (current_subfile, line, addr);
+ last_subfile = current_subfile;
+ last_line = line;
}
}
- basic_block = 0;
+ discriminator = 0;
}
else switch (op_code)
{
case DW_LNE_set_address:
address = read_address (abfd, line_ptr, cu, &bytes_read);
- if (address == 0 && !dwarf2_per_objfile->has_section_at_zero)
+ /* If address < lowpc then it's not a usable value, it's
+ outside the pc range of the CU. However, we restrict
+ the test to only address values of zero to preserve
+ GDB's previous behaviour which is to handle the specific
+ case of a function being GC'd by the linker. */
+ if (address == 0 && address < lowpc)
{
/* This line table is for a function which has been
GCd by the linker. Ignore it. PR gdb/12528 */
"[in module %s]"),
line_offset, objfile_name (objfile));
p_record_line = noop_record_line;
+ /* Note: p_record_line is left as noop_record_line
+ until we see DW_LNE_end_sequence. */
}
op_index = 0;
break;
case DW_LNE_set_discriminator:
/* The discriminator is not interesting to the debugger;
- just ignore it. */
- line_ptr = extended_end;
+ just ignore it. We still need to check its value though:
+ if there are consecutive entries for the same
+ (non-prologue) line we want to coalesce them.
+ PR 17276. */
+ discriminator = read_unsigned_leb128 (abfd, line_ptr,
+ &bytes_read);
+ line_has_non_zero_discriminator |= discriminator != 0;
+ line_ptr += bytes_read;
break;
default:
complaint (&symfile_complaints,
{
if (last_subfile != current_subfile)
{
- addr = gdbarch_addr_bits_remove (gdbarch, address);
- if (last_subfile)
- (*p_record_line) (last_subfile, 0, addr);
- last_subfile = current_subfile;
+ dwarf_finish_line (gdbarch, last_subfile,
+ address, p_record_line);
}
- addr = gdbarch_addr_bits_remove (gdbarch, address);
- (*p_record_line) (current_subfile, line, addr);
+ if (dwarf_record_line_p (line, last_line,
+ line_has_non_zero_discriminator,
+ last_subfile))
+ {
+ dwarf_record_line (gdbarch, current_subfile,
+ line, address, p_record_line);
+ }
+ last_subfile = current_subfile;
+ last_line = line;
}
}
- basic_block = 0;
+ discriminator = 0;
break;
case DW_LNS_advance_pc:
{
}
break;
case DW_LNS_advance_line:
- line += read_signed_leb128 (abfd, line_ptr, &bytes_read);
- line_ptr += bytes_read;
+ {
+ int line_delta
+ = read_signed_leb128 (abfd, line_ptr, &bytes_read);
+
+ line += line_delta;
+ if (line_delta != 0)
+ line_has_non_zero_discriminator = discriminator != 0;
+ line_ptr += bytes_read;
+ }
break;
case DW_LNS_set_file:
{
if (!decode_for_pst_p)
{
last_subfile = current_subfile;
+ line_has_non_zero_discriminator = discriminator != 0;
dwarf2_start_subfile (fe->name, dir, comp_dir);
}
}
}
break;
case DW_LNS_set_column:
- column = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+ (void) read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
line_ptr += bytes_read;
break;
case DW_LNS_negate_stmt:
is_stmt = (!is_stmt);
break;
case DW_LNS_set_basic_block:
- basic_block = 1;
break;
/* Add to the address register of the state machine the
address increment value corresponding to special opcode
lh->file_names[file - 1].included_p = 1;
if (!decode_for_pst_p)
{
- addr = gdbarch_addr_bits_remove (gdbarch, address);
- (*p_record_line) (current_subfile, 0, addr);
+ dwarf_finish_line (gdbarch, current_subfile, address,
+ p_record_line);
}
}
}
as the corresponding symtab. Since COMP_DIR is not used in the name of the
symtab we don't use it in the name of the psymtabs we create.
E.g. expand_line_sal requires this when finding psymtabs to expand.
- A good testcase for this is mb-inline.exp. */
+ A good testcase for this is mb-inline.exp.
+
+ LOWPC is the lowest address in CU (or 0 if not known). */
static void
dwarf_decode_lines (struct line_header *lh, const char *comp_dir,
struct dwarf2_cu *cu, struct partial_symtab *pst,
- int want_line_info)
+ CORE_ADDR lowpc)
{
struct objfile *objfile = cu->objfile;
const int decode_for_pst_p = (pst != NULL);
struct subfile *first_subfile = current_subfile;
- if (want_line_info)
- dwarf_decode_lines_1 (lh, comp_dir, cu, pst);
+ dwarf_decode_lines_1 (lh, comp_dir, cu, decode_for_pst_p, lowpc);
if (decode_for_pst_p)
{
case DW_TAG_label:
attr = dwarf2_attr (die, DW_AT_low_pc, cu);
if (attr)
- {
- SYMBOL_VALUE_ADDRESS (sym) = DW_ADDR (attr) + baseaddr;
- }
+ SYMBOL_VALUE_ADDRESS (sym)
+ = attr_value_as_address (attr) + baseaddr;
SYMBOL_TYPE (sym) = objfile_type (objfile)->builtin_core_addr;
SYMBOL_DOMAIN (sym) = LABEL_DOMAIN;
SYMBOL_ACLASS_INDEX (sym) = LOC_LABEL;
? &global_symbols : cu->list_in_scope);
}
break;
+ case DW_TAG_imported_declaration:
case DW_TAG_namespace:
SYMBOL_ACLASS_INDEX (sym) = LOC_TYPEDEF;
list_to_add = &global_symbols;
break;
+ case DW_TAG_module:
+ SYMBOL_ACLASS_INDEX (sym) = LOC_TYPEDEF;
+ SYMBOL_DOMAIN (sym) = MODULE_DOMAIN;
+ list_to_add = &global_symbols;
+ break;
case DW_TAG_common_block:
SYMBOL_ACLASS_INDEX (sym) = LOC_COMMON_BLOCK;
SYMBOL_DOMAIN (sym) = COMMON_BLOCK_DOMAIN;
&& actual_name[actual_name_len
- die_name_len - 1] == ':')
name =
- obstack_copy0 (&cu->objfile->objfile_obstack,
+ obstack_copy0 (&cu->objfile->per_bfd->storage_obstack,
actual_name,
actual_name_len - die_name_len - 2);
}
if (base == NULL || base == DW_STRING (attr) || base[-1] != ':')
return "";
- return obstack_copy0 (&cu->objfile->objfile_obstack,
+ return obstack_copy0 (&cu->objfile->per_bfd->storage_obstack,
DW_STRING (attr), &base[-1] - DW_STRING (attr));
}
return name;
}
return "";
+ case DW_TAG_enumeration_type:
+ parent_type = read_type_die (parent, cu);
+ if (TYPE_DECLARED_CLASS (parent_type))
+ {
+ if (TYPE_TAG_NAME (parent_type) != NULL)
+ return TYPE_TAG_NAME (parent_type);
+ return "";
+ }
+ /* Fall through. */
default:
return determine_prefix (parent, cu);
}
/* GCJ will output '<init>' for Java constructor names.
For this special case, return the name of the parent class. */
- /* GCJ may output suprogram DIEs with AT_specification set.
+ /* GCJ may output subprogram DIEs with AT_specification set.
If so, use the name of the specified DIE. */
spec_die = die_specification (die, &spec_cu);
if (spec_die != NULL)
char *base;
/* FIXME: we already did this for the partial symbol... */
- DW_STRING (attr) = obstack_copy0 (&cu->objfile->objfile_obstack,
- demangled, strlen (demangled));
+ DW_STRING (attr)
+ = obstack_copy0 (&cu->objfile->per_bfd->storage_obstack,
+ demangled, strlen (demangled));
DW_STRING_IS_CANONICAL (attr) = 1;
xfree (demangled);
{
DW_STRING (attr)
= dwarf2_canonicalize_name (DW_STRING (attr), cu,
- &cu->objfile->objfile_obstack);
+ &cu->objfile->per_bfd->storage_obstack);
DW_STRING_IS_CANONICAL (attr) = 1;
}
return DW_STRING (attr);
{
struct dwarf2_per_cu_offset_and_type **slot, ofs;
struct objfile *objfile = cu->objfile;
+ struct attribute *attr;
+ struct dynamic_prop prop;
/* For Ada types, make sure that the gnat-specific data is always
initialized (if not already set). There are a few types where
&& !HAVE_GNAT_AUX_INFO (type))
INIT_GNAT_SPECIFIC (type);
+ /* Read DW_AT_data_location and set in type. */
+ attr = dwarf2_attr (die, DW_AT_data_location, cu);
+ if (attr_to_dynamic_prop (attr, die, cu, &prop))
+ {
+ TYPE_DATA_LOCATION (type)
+ = obstack_alloc (&objfile->objfile_obstack, sizeof (prop));
+ *TYPE_DATA_LOCATION (type) = prop;
+ }
+
if (dwarf2_per_objfile->die_type_hash == NULL)
{
dwarf2_per_objfile->die_type_hash =
static void
set_dwarf2_cmd (char *args, int from_tty)
{
- help_list (set_dwarf2_cmdlist, "maintenance set dwarf2 ", -1, gdb_stdout);
+ help_list (set_dwarf2_cmdlist, "maintenance set dwarf2 ", all_commands,
+ gdb_stdout);
}
static void
&set_dwarf2_cmdlist,
&show_dwarf2_cmdlist);
- add_setshow_boolean_cmd ("dwarf2-read", no_class, &dwarf2_read_debug, _("\
+ add_setshow_zuinteger_cmd ("dwarf2-read", no_class, &dwarf2_read_debug, _("\
Set debugging of the dwarf2 reader."), _("\
Show debugging of the dwarf2 reader."), _("\
-When enabled, debugging messages are printed during dwarf2 reading\n\
-and symtab expansion."),
+When enabled (non-zero), debugging messages are printed during dwarf2\n\
+reading and symtab expansion. A value of 1 (one) provides basic\n\
+information. A value greater than 1 provides more verbose information."),
NULL,
NULL,
&setdebuglist, &showdebuglist);