#include "dwarf2/read.h"
#include "dwarf2/abbrev.h"
#include "dwarf2/attribute.h"
+#include "dwarf2/comp-unit.h"
#include "dwarf2/index-cache.h"
#include "dwarf2/index-common.h"
#include "dwarf2/leb.h"
#include "dwarf2/line-header.h"
+#include "dwarf2/dwz.h"
+#include "dwarf2/macro.h"
+#include "dwarf2/die.h"
#include "bfd.h"
#include "elf-bfd.h"
#include "symtab.h"
#include "demangle.h"
#include "gdb-demangle.h"
#include "filenames.h" /* for DOSish file names */
-#include "macrotab.h"
#include "language.h"
#include "complaints.h"
#include "dwarf2/expr.h"
#include "gdbsupport/selftest.h"
#include "rust-lang.h"
#include "gdbsupport/pathstuff.h"
+#include "count-one-bits.h"
+#include "debuginfod-support.h"
/* When == 1, print basic high level tracing messages.
When > 1, be more verbose.
/* local data types */
-/* The data in a compilation unit header, after target2host
- translation, looks like this. */
-struct comp_unit_head
-{
- unsigned int length;
- short version;
- unsigned char addr_size;
- unsigned char signed_addr_p;
- sect_offset abbrev_sect_off;
-
- /* Size of file offsets; either 4 or 8. */
- unsigned int offset_size;
-
- /* Size of the length field; either 4 or 12. */
- unsigned int initial_length_size;
-
- enum dwarf_unit_type unit_type;
-
- /* Offset to the first byte of this compilation unit header in the
- .debug_info section, for resolving relative reference dies. */
- sect_offset sect_off;
-
- /* Offset to first die in this cu from the start of the cu.
- This will be the first byte following the compilation unit header. */
- cu_offset first_die_cu_offset;
-
-
- /* 64-bit signature of this unit. For type units, it denotes the signature of
- the type (DW_UT_type in DWARF 4, additionally DW_UT_split_type in DWARF 5).
- Also used in DWARF 5, to denote the dwo id when the unit type is
- DW_UT_skeleton or DW_UT_split_compile. */
- ULONGEST signature;
-
- /* For types, offset in the type's DIE of the type defined by this TU. */
- cu_offset type_cu_offset_in_tu;
-};
-
/* Type used for delaying computation of method physnames.
See comments for compute_delayed_physnames. */
struct delayed_method_info
struct comp_unit_head header {};
/* Base address of this compilation unit. */
- CORE_ADDR base_address = 0;
-
- /* Non-zero if base_address has been set. */
- int base_known = 0;
+ gdb::optional<CORE_ADDR> base_address;
/* The language we are debugging. */
enum language language = language_unknown;
/* dwarf2read.c's main "handle" on a TU symtab.
To simplify things we create an artificial CU that "includes" all the
type units using this stmt_list so that the rest of the code still has
- a "per_cu" handle on the symtab.
- This PER_CU is recognized by having no section. */
-#define IS_TYPE_UNIT_GROUP(per_cu) ((per_cu)->section == NULL)
+ a "per_cu" handle on the symtab. */
struct dwarf2_per_cu_data per_cu;
/* The TUs that share this DW_AT_stmt_list entry.
/* The data used to construct the hash key. */
struct stmt_list_hash hash;
- /* The number of symtabs from the line header.
- The value here must match line_header.num_file_names. */
- unsigned int num_symtabs;
-
/* The symbol tables for this TU (obtained from the files listed in
DW_AT_stmt_list).
WARNING: The order of entries here must match the order of entries
cutu_reader (struct dwarf2_per_cu_data *this_cu,
struct abbrev_table *abbrev_table,
- int use_existing_cu, int keep,
+ int use_existing_cu,
bool skip_partial);
explicit cutu_reader (struct dwarf2_per_cu_data *this_cu,
struct dwarf2_cu *parent_cu = nullptr,
struct dwo_file *dwo_file = nullptr);
- ~cutu_reader ();
-
DISABLE_COPY_AND_ASSIGN (cutu_reader);
const gdb_byte *info_ptr = nullptr;
struct die_info *comp_unit_die = nullptr;
bool dummy_p = false;
+ /* Release the new CU, putting it on the chain. This cannot be done
+ for dummy CUs. */
+ void keep ();
+
private:
void init_tu_and_read_dwo_dies (struct dwarf2_per_cu_data *this_cu,
- int use_existing_cu, int keep);
+ int use_existing_cu);
struct dwarf2_per_cu_data *m_this_cu;
- int m_keep = 0;
std::unique_ptr<dwarf2_cu> m_new_cu;
/* The ordinary abbreviation table. */
}
};
-/* This data structure holds a complete die structure. */
-struct die_info
- {
- /* DWARF-2 tag for this DIE. */
- ENUM_BITFIELD(dwarf_tag) tag : 16;
-
- /* Number of attributes */
- unsigned char num_attrs;
-
- /* True if we're presently building the full type name for the
- type derived from this DIE. */
- unsigned char building_fullname : 1;
-
- /* True if this die is in process. PR 16581. */
- unsigned char in_process : 1;
-
- /* True if this DIE has children. */
- unsigned char has_children : 1;
-
- /* Abbrev number */
- unsigned int abbrev;
-
- /* Offset in .debug_info or .debug_types section. */
- sect_offset sect_off;
-
- /* The dies in a compilation unit form an n-ary tree. PARENT
- points to this die's parent; CHILD points to the first child of
- this node; and all the children of a given node are chained
- together via their SIBLING fields. */
- struct die_info *child; /* Its first child, if any. */
- struct die_info *sibling; /* Its next sibling, if any. */
- struct die_info *parent; /* Its parent, if any. */
-
- /* An array of attributes, with NUM_ATTRS elements. There may be
- zero, but it's not common and zero-sized arrays are not
- sufficiently portable C. */
- struct attribute attrs[1];
- };
-
/* FIXME: We might want to set this from BFD via bfd_arch_bits_per_byte,
but this would require a corresponding change in unpack_field_as_long
and friends. */
std::vector<struct nextfield> fields;
std::vector<struct nextfield> baseclasses;
- /* Number of fields (including baseclasses). */
- int nfields = 0;
-
/* Set if the accessibility of one of the fields is not public. */
int non_public_fields = 0;
/* Nested types defined by this class and the number of elements in this
list. */
std::vector<struct decl_field> nested_types_list;
+
+ /* Return the total number of fields (including baseclasses). */
+ int nfields () const
+ {
+ return fields.size () + baseclasses.size ();
+ }
};
/* Loaded secondary compilation units are kept in memory until they
static CORE_ADDR read_addr_index (struct dwarf2_cu *cu, unsigned int addr_index);
-static CORE_ADDR read_address (bfd *, const gdb_byte *ptr, struct dwarf2_cu *,
- unsigned int *);
-
-static LONGEST read_initial_length (bfd *, const gdb_byte *, unsigned int *);
-
-static LONGEST read_checked_initial_length_and_offset
- (bfd *, const gdb_byte *, const struct comp_unit_head *,
- unsigned int *, unsigned int *);
-
-static LONGEST read_offset (bfd *, const gdb_byte *,
- const struct comp_unit_head *,
- unsigned int *);
-
-static LONGEST read_offset_1 (bfd *, const gdb_byte *, unsigned int);
-
static sect_offset read_abbrev_offset
(struct dwarf2_per_objfile *dwarf2_per_objfile,
struct dwarf2_section_info *, sect_offset);
-static const gdb_byte *read_n_bytes (bfd *, const gdb_byte *, unsigned int);
-
-static const char *read_direct_string (bfd *, const gdb_byte *, unsigned int *);
-
static const char *read_indirect_string
(struct dwarf2_per_objfile *dwarf2_per_objfile, bfd *, const gdb_byte *,
const struct comp_unit_head *, unsigned int *);
-static const char *read_indirect_line_string
- (struct dwarf2_per_objfile *dwarf2_per_objfile, bfd *, const gdb_byte *,
- const struct comp_unit_head *, unsigned int *);
-
static const char *read_indirect_string_at_offset
- (struct dwarf2_per_objfile *dwarf2_per_objfile, bfd *abfd,
- LONGEST str_offset);
-
-static const char *read_indirect_string_from_dwz
- (struct objfile *objfile, struct dwz_file *, LONGEST);
+ (struct dwarf2_per_objfile *dwarf2_per_objfile, LONGEST str_offset);
static CORE_ADDR read_addr_index_from_leb128 (struct dwarf2_cu *,
const gdb_byte *,
static struct attribute *dwarf2_attr (struct die_info *, unsigned int,
struct dwarf2_cu *);
-static struct attribute *dwarf2_attr_no_follow (struct die_info *,
- unsigned int);
-
static const char *dwarf2_string_attr (struct die_info *die, unsigned int name,
struct dwarf2_cu *cu);
static void process_die (struct die_info *, struct dwarf2_cu *);
static const char *dwarf2_canonicalize_name (const char *, struct dwarf2_cu *,
- struct obstack *);
+ struct objfile *);
static const char *dwarf2_name (struct die_info *die, struct dwarf2_cu *);
static const char *dwarf_attr_name (unsigned int);
-static const char *dwarf_unit_type_name (int unit_type);
-
static const char *dwarf_form_name (unsigned int);
static const char *dwarf_bool_name (unsigned int);
static const char *dwarf_type_encoding_name (unsigned int);
-static struct die_info *sibling_die (struct die_info *);
-
static void dump_die_shallow (struct ui_file *, int indent, struct die_info *);
static void dump_die_for_error (struct die_info *);
static file_and_directory find_file_and_directory (struct die_info *die,
struct dwarf2_cu *cu);
-/* Expected enum dwarf_unit_type for read_comp_unit_head. */
-enum class rcuh_kind { COMPILE, TYPE };
-
-static const gdb_byte *read_and_check_comp_unit_head
- (struct dwarf2_per_objfile* dwarf2_per_objfile,
- struct comp_unit_head *header,
- struct dwarf2_section_info *section,
- struct dwarf2_section_info *abbrev_section, const gdb_byte *info_ptr,
- rcuh_kind section_kind);
-
-static htab_up allocate_signatured_type_table (struct objfile *objfile);
+static htab_up allocate_signatured_type_table ();
-static htab_up allocate_dwo_unit_table (struct objfile *objfile);
+static htab_up allocate_dwo_unit_table ();
static struct dwo_unit *lookup_dwo_unit_in_dwp
(struct dwarf2_per_objfile *dwarf2_per_objfile,
\f
/* Various complaints about symbol reading that don't abort the process. */
-static void
-dwarf2_statement_list_fits_in_line_number_section_complaint (void)
-{
- complaint (_("statement list doesn't fit in .debug_line section"));
-}
-
static void
dwarf2_debug_line_missing_file_complaint (void)
{
arg1, arg2, arg3);
}
-static void
-dwarf2_section_buffer_overflow_complaint (struct dwarf2_section_info *section)
-{
- complaint (_("debug info runs off end of %s section"
- " [in module %s]"),
- section->get_name (),
- section->get_file_name ());
-}
-
-static void
-dwarf2_macro_malformed_definition_complaint (const char *arg1)
-{
- complaint (_("macro debug info contains a "
- "malformed macro definition:\n`%s'"),
- arg1);
-}
-
static void
dwarf2_invalid_attrib_class_complaint (const char *arg1, const char *arg2)
{
this->has_section_at_zero = true;
}
-/* A helper function that returns the size of a section in a safe way.
- If you are positive that the section has been read before using the
- size, then it is safe to refer to the dwarf2_section_info object's
- "size" field directly. In other cases, you must call this
- function, because for compressed sections the size field is not set
- correctly until the section has been read. */
-
-static bfd_size_type
-dwarf2_section_size (struct objfile *objfile,
- struct dwarf2_section_info *info)
-{
- if (!info->readin)
- info->read (objfile);
- return info->size;
-}
-
/* Fill in SECTP, BUFP and SIZEP with section info, given OBJFILE and
SECTION_NAME. */
if (dwz_bfd == NULL)
dwz_bfd = build_id_to_debug_bfd (buildid_len, buildid);
+ if (dwz_bfd == nullptr)
+ {
+ gdb::unique_xmalloc_ptr<char> alt_filename;
+ const char *origname = dwarf2_per_objfile->objfile->original_name;
+
+ scoped_fd fd (debuginfod_debuginfo_query (buildid,
+ buildid_len,
+ origname,
+ &alt_filename));
+
+ if (fd.get () >= 0)
+ {
+ /* File successfully retrieved from server. */
+ dwz_bfd = gdb_bfd_open (alt_filename.get (), gnutarget, -1);
+
+ if (dwz_bfd == nullptr)
+ warning (_("File \"%s\" from debuginfod cannot be opened as bfd"),
+ alt_filename.get ());
+ else if (!build_id_verify (dwz_bfd.get (), buildid_len, buildid))
+ dwz_bfd.reset (nullptr);
+ }
+ }
+
if (dwz_bfd == NULL)
error (_("could not find '.gnu_debugaltlink' file for %s"),
objfile_name (dwarf2_per_objfile->objfile));
/* Skip type_unit_groups, reading the type units they contain
is handled elsewhere. */
- if (IS_TYPE_UNIT_GROUP (per_cu))
+ if (per_cu->type_unit_group_p ())
return;
/* The destructor of dwarf2_queue_guard frees any entries left on
gdb_assert (dwarf2_per_objfile->all_type_units.empty ());
dwarf2_per_objfile->all_type_units.reserve (elements / 3);
- htab_up sig_types_hash = allocate_signatured_type_table (objfile);
+ htab_up sig_types_hash = allocate_signatured_type_table ();
for (offset_type i = 0; i < elements; i += 3)
{
gdb_assert (dwarf2_per_objfile->all_type_units.empty ());
dwarf2_per_objfile->all_type_units.reserve (map.tu_count);
- htab_up sig_types_hash = allocate_signatured_type_table (objfile);
+ htab_up sig_types_hash = allocate_signatured_type_table ();
for (uint32_t i = 0; i < map.tu_count; ++i)
{
/* This should never be called for TUs. */
gdb_assert (! this_cu->is_debug_types);
/* Nor type unit groups. */
- gdb_assert (! IS_TYPE_UNIT_GROUP (this_cu));
+ gdb_assert (! this_cu->type_unit_group_p ());
if (this_cu->v.quick->file_names != NULL)
return this_cu->v.quick->file_names;
+ namei * offset_size),
offset_size,
dwarf5_byte_order);
- return read_indirect_string_at_offset
- (dwarf2_per_objfile, dwarf2_per_objfile->objfile->obfd, namei_string_offs);
+ return read_indirect_string_at_offset (dwarf2_per_objfile,
+ namei_string_offs);
}
/* Find a slot in .debug_names for the object named NAME. If NAME is
}
}
-/* Return the total length of the CU described by HEADER. */
-
-static unsigned int
-get_cu_length (const struct comp_unit_head *header)
-{
- return header->initial_length_size + header->length;
-}
-
-/* Return TRUE if SECT_OFF is within CU_HEADER. */
-
-static inline bool
-offset_in_cu_p (const comp_unit_head *cu_header, sect_offset sect_off)
-{
- sect_offset bottom = cu_header->sect_off;
- sect_offset top = cu_header->sect_off + get_cu_length (cu_header);
-
- return sect_off >= bottom && sect_off < top;
-}
-
/* Find the base address of the compilation unit for range lists and
location lists. It will normally be specified by DW_AT_low_pc.
In DWARF-3 draft 4, the base address could be overridden by
{
struct attribute *attr;
- cu->base_known = 0;
- cu->base_address = 0;
+ cu->base_address.reset ();
attr = dwarf2_attr (die, DW_AT_entry_pc, cu);
if (attr != nullptr)
- {
- cu->base_address = attr->value_as_address ();
- cu->base_known = 1;
- }
+ cu->base_address = attr->value_as_address ();
else
{
attr = dwarf2_attr (die, DW_AT_low_pc, cu);
if (attr != nullptr)
- {
- cu->base_address = attr->value_as_address ();
- cu->base_known = 1;
- }
- }
-}
-
-/* Read in the comp unit header information from the debug_info at info_ptr.
- Use rcuh_kind::COMPILE as the default type if not known by the caller.
- NOTE: This leaves members offset, first_die_offset to be filled in
- by the caller. */
-
-static const gdb_byte *
-read_comp_unit_head (struct comp_unit_head *cu_header,
- const gdb_byte *info_ptr,
- struct dwarf2_section_info *section,
- rcuh_kind section_kind)
-{
- int signed_addr;
- unsigned int bytes_read;
- const char *filename = section->get_file_name ();
- bfd *abfd = section->get_bfd_owner ();
-
- cu_header->length = read_initial_length (abfd, info_ptr, &bytes_read);
- cu_header->initial_length_size = bytes_read;
- cu_header->offset_size = (bytes_read == 4) ? 4 : 8;
- info_ptr += bytes_read;
- cu_header->version = read_2_bytes (abfd, info_ptr);
- if (cu_header->version < 2 || cu_header->version > 5)
- error (_("Dwarf Error: wrong version in compilation unit header "
- "(is %d, should be 2, 3, 4 or 5) [in module %s]"),
- cu_header->version, filename);
- info_ptr += 2;
- if (cu_header->version < 5)
- switch (section_kind)
- {
- case rcuh_kind::COMPILE:
- cu_header->unit_type = DW_UT_compile;
- break;
- case rcuh_kind::TYPE:
- cu_header->unit_type = DW_UT_type;
- break;
- default:
- internal_error (__FILE__, __LINE__,
- _("read_comp_unit_head: invalid section_kind"));
- }
- else
- {
- cu_header->unit_type = static_cast<enum dwarf_unit_type>
- (read_1_byte (abfd, info_ptr));
- info_ptr += 1;
- switch (cu_header->unit_type)
- {
- case DW_UT_compile:
- case DW_UT_partial:
- case DW_UT_skeleton:
- case DW_UT_split_compile:
- if (section_kind != rcuh_kind::COMPILE)
- error (_("Dwarf Error: wrong unit_type in compilation unit header "
- "(is %s, should be %s) [in module %s]"),
- dwarf_unit_type_name (cu_header->unit_type),
- dwarf_unit_type_name (DW_UT_type), filename);
- break;
- case DW_UT_type:
- case DW_UT_split_type:
- section_kind = rcuh_kind::TYPE;
- break;
- default:
- error (_("Dwarf Error: wrong unit_type in compilation unit header "
- "(is %#04x, should be one of: %s, %s, %s, %s or %s) "
- "[in module %s]"), cu_header->unit_type,
- dwarf_unit_type_name (DW_UT_compile),
- dwarf_unit_type_name (DW_UT_skeleton),
- dwarf_unit_type_name (DW_UT_split_compile),
- dwarf_unit_type_name (DW_UT_type),
- dwarf_unit_type_name (DW_UT_split_type), filename);
- }
-
- cu_header->addr_size = read_1_byte (abfd, info_ptr);
- info_ptr += 1;
- }
- cu_header->abbrev_sect_off = (sect_offset) read_offset (abfd, info_ptr,
- cu_header,
- &bytes_read);
- info_ptr += bytes_read;
- if (cu_header->version < 5)
- {
- cu_header->addr_size = read_1_byte (abfd, info_ptr);
- info_ptr += 1;
- }
- signed_addr = bfd_get_sign_extend_vma (abfd);
- if (signed_addr < 0)
- internal_error (__FILE__, __LINE__,
- _("read_comp_unit_head: dwarf from non elf file"));
- cu_header->signed_addr_p = signed_addr;
-
- bool header_has_signature = section_kind == rcuh_kind::TYPE
- || cu_header->unit_type == DW_UT_skeleton
- || cu_header->unit_type == DW_UT_split_compile;
-
- if (header_has_signature)
- {
- cu_header->signature = read_8_bytes (abfd, info_ptr);
- info_ptr += 8;
- }
-
- if (section_kind == rcuh_kind::TYPE)
- {
- LONGEST type_offset;
- type_offset = read_offset (abfd, info_ptr, cu_header, &bytes_read);
- info_ptr += bytes_read;
- cu_header->type_cu_offset_in_tu = (cu_offset) type_offset;
- if (to_underlying (cu_header->type_cu_offset_in_tu) != type_offset)
- error (_("Dwarf Error: Too big type_offset in compilation unit "
- "header (is %s) [in module %s]"), plongest (type_offset),
- filename);
+ cu->base_address = attr->value_as_address ();
}
-
- return info_ptr;
}
/* Helper function that returns the proper abbrev section for
return abbrev;
}
-/* Subroutine of read_and_check_comp_unit_head and
- read_and_check_type_unit_head to simplify them.
- Perform various error checking on the header. */
-
-static void
-error_check_comp_unit_head (struct dwarf2_per_objfile *dwarf2_per_objfile,
- struct comp_unit_head *header,
- struct dwarf2_section_info *section,
- struct dwarf2_section_info *abbrev_section)
-{
- const char *filename = section->get_file_name ();
-
- if (to_underlying (header->abbrev_sect_off)
- >= dwarf2_section_size (dwarf2_per_objfile->objfile, abbrev_section))
- error (_("Dwarf Error: bad offset (%s) in compilation unit header "
- "(offset %s + 6) [in module %s]"),
- sect_offset_str (header->abbrev_sect_off),
- sect_offset_str (header->sect_off),
- filename);
-
- /* Cast to ULONGEST to use 64-bit arithmetic when possible to
- avoid potential 32-bit overflow. */
- if (((ULONGEST) header->sect_off + get_cu_length (header))
- > section->size)
- error (_("Dwarf Error: bad length (0x%x) in compilation unit header "
- "(offset %s + 0) [in module %s]"),
- header->length, sect_offset_str (header->sect_off),
- filename);
-}
-
-/* Read in a CU/TU header and perform some basic error checking.
- The contents of the header are stored in HEADER.
- The result is a pointer to the start of the first DIE. */
-
-static const gdb_byte *
-read_and_check_comp_unit_head (struct dwarf2_per_objfile *dwarf2_per_objfile,
- struct comp_unit_head *header,
- struct dwarf2_section_info *section,
- struct dwarf2_section_info *abbrev_section,
- const gdb_byte *info_ptr,
- rcuh_kind section_kind)
-{
- const gdb_byte *beg_of_comp_unit = info_ptr;
-
- header->sect_off = (sect_offset) (beg_of_comp_unit - section->buffer);
-
- info_ptr = read_comp_unit_head (header, info_ptr, section, section_kind);
-
- header->first_die_cu_offset = (cu_offset) (info_ptr - beg_of_comp_unit);
-
- error_check_comp_unit_head (dwarf2_per_objfile, header, section,
- abbrev_section);
-
- return info_ptr;
-}
-
/* Fetch the abbreviation table offset from a comp or type unit header. */
static sect_offset
info_ptr += 2;
}
- return (sect_offset) read_offset_1 (abfd, info_ptr, offset_size);
+ return (sect_offset) read_offset (abfd, info_ptr, offset_size);
}
+/* A partial symtab that is used only for include files. */
+struct dwarf2_include_psymtab : public partial_symtab
+{
+ dwarf2_include_psymtab (const char *filename, struct objfile *objfile)
+ : partial_symtab (filename, objfile)
+ {
+ }
+
+ void read_symtab (struct objfile *objfile) override
+ {
+ expand_psymtab (objfile);
+ }
+
+ void expand_psymtab (struct objfile *objfile) override
+ {
+ if (m_readin)
+ return;
+ /* It's an include file, no symbols to read for it.
+ Everything is in the parent symtab. */
+ read_dependencies (objfile);
+ m_readin = true;
+ }
+
+ bool readin_p () const override
+ {
+ return m_readin;
+ }
+
+ struct compunit_symtab *get_compunit_symtab () const override
+ {
+ return nullptr;
+ }
+
+private:
+
+ bool m_readin = false;
+};
+
/* Allocate a new partial symtab for file named NAME and mark this new
partial symtab as being an include of PST. */
dwarf2_create_include_psymtab (const char *name, dwarf2_psymtab *pst,
struct objfile *objfile)
{
- dwarf2_psymtab *subpst = new dwarf2_psymtab (name, objfile);
+ dwarf2_include_psymtab *subpst = new dwarf2_include_psymtab (name, objfile);
if (!IS_ABSOLUTE_PATH (subpst->filename))
{
subpst->dependencies = objfile->partial_symtabs->allocate_dependencies (1);
subpst->dependencies[0] = pst;
subpst->number_of_dependencies = 1;
-
- /* No private part is necessary for include psymtabs. This property
- can be used to differentiate between such include psymtabs and
- the regular ones. */
- subpst->per_cu_data = nullptr;
}
/* Read the Line Number Program data and extract the list of files
/* Allocate a hash table for signatured types. */
static htab_up
-allocate_signatured_type_table (struct objfile *objfile)
+allocate_signatured_type_table ()
{
return htab_up (htab_create_alloc (41,
hash_signatured_type,
ptr = read_and_check_comp_unit_head (dwarf2_per_objfile, &header, section,
abbrev_section, ptr, section_kind);
- length = get_cu_length (&header);
+ length = header.get_length ();
/* Skip dummy type units. */
if (ptr >= info_ptr + length
if (types_htab == NULL)
{
if (dwo_file)
- types_htab = allocate_dwo_unit_table (objfile);
+ types_htab = allocate_dwo_unit_table ();
else
- types_htab = allocate_signatured_type_table (objfile);
+ types_htab = allocate_signatured_type_table ();
}
if (dwo_file)
{
struct dwarf2_per_objfile *dwarf2_per_objfile
= cu->per_cu->dwarf2_per_objfile;
- struct objfile *objfile = dwarf2_per_objfile->objfile;
struct dwo_file *dwo_file;
struct dwo_unit find_dwo_entry, *dwo_entry;
struct signatured_type find_sig_entry, *sig_entry;
/* 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);
- }
+ dwarf2_per_objfile->signatured_types = allocate_signatured_type_table ();
/* We only ever need to read in one copy of a signatured type.
Use the global signatured_types array to do our own comdat-folding
{
struct dwarf2_per_objfile *dwarf2_per_objfile
= cu->per_cu->dwarf2_per_objfile;
- struct objfile *objfile = dwarf2_per_objfile->objfile;
struct dwp_file *dwp_file = get_dwp_file (dwarf2_per_objfile);
struct dwo_unit *dwo_entry;
struct signatured_type find_sig_entry, *sig_entry;
/* 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);
- }
+ dwarf2_per_objfile->signatured_types = allocate_signatured_type_table ();
find_sig_entry.signature = sig;
slot = htab_find_slot (dwarf2_per_objfile->signatured_types.get (),
}
}
-/* Return the address base of the compile unit, which, if exists, is stored
- either at the attribute DW_AT_GNU_addr_base, or DW_AT_addr_base. */
-static gdb::optional<ULONGEST>
-lookup_addr_base (struct die_info *comp_unit_die)
-{
- struct attribute *attr;
- attr = dwarf2_attr_no_follow (comp_unit_die, DW_AT_addr_base);
- if (attr == nullptr)
- attr = dwarf2_attr_no_follow (comp_unit_die, DW_AT_GNU_addr_base);
- if (attr == nullptr)
- return gdb::optional<ULONGEST> ();
- return DW_UNSND (attr);
-}
-
-/* Return range lists base of the compile unit, which, if exists, is stored
- either at the attribute DW_AT_rnglists_base or DW_AT_GNU_ranges_base. */
-static ULONGEST
-lookup_ranges_base (struct die_info *comp_unit_die)
-{
- struct attribute *attr;
- attr = dwarf2_attr_no_follow (comp_unit_die, DW_AT_rnglists_base);
- if (attr == nullptr)
- attr = dwarf2_attr_no_follow (comp_unit_die, DW_AT_GNU_ranges_base);
- if (attr == nullptr)
- return 0;
- return DW_UNSND (attr);
-}
-
/* Low level DIE reading support. */
/* Initialize a die_reader_specs struct from a dwarf2_cu struct. */
ranges = dwarf2_attr (stub_comp_unit_die, DW_AT_ranges, cu);
comp_dir = dwarf2_attr (stub_comp_unit_die, DW_AT_comp_dir, cu);
- cu->addr_base = lookup_addr_base (stub_comp_unit_die);
+ cu->addr_base = stub_comp_unit_die->addr_base ();
/* There should be a DW_AT_rnglists_base (DW_AT_GNU_ranges_base) attribute
here (if needed). We need the value before we can process
DW_AT_ranges. */
- cu->ranges_base = lookup_ranges_base (stub_comp_unit_die);
+ cu->ranges_base = stub_comp_unit_die->ranges_base ();
}
else if (stub_comp_dir != NULL)
{
gdb_assert (dwo_unit->sect_off == cu->header.sect_off);
/* For DWOs coming from DWP files, we don't know the CU length
nor the type's offset in the TU until now. */
- dwo_unit->length = get_cu_length (&cu->header);
+ dwo_unit->length = cu->header.get_length ();
dwo_unit->type_offset_in_tu = cu->header.type_cu_offset_in_tu;
/* Establish the type offset that can be used to lookup the type.
gdb_assert (dwo_unit->sect_off == cu->header.sect_off);
/* For DWOs coming from DWP files, we don't know the CU length
until now. */
- dwo_unit->length = get_cu_length (&cu->header);
+ dwo_unit->length = cu->header.get_length ();
}
*result_dwo_abbrev_table
void
cutu_reader::init_tu_and_read_dwo_dies (struct dwarf2_per_cu_data *this_cu,
- int use_existing_cu, int keep)
+ int use_existing_cu)
{
struct signatured_type *sig_type;
- struct die_reader_specs reader;
/* Verify we can do the following downcast, and that we have the
data we need. */
if (read_cutu_die_from_dwo (this_cu, sig_type->dwo_unit,
NULL /* stub_comp_unit_die */,
sig_type->dwo_unit->dwo_file->comp_dir,
- &reader, &info_ptr,
+ this, &info_ptr,
&comp_unit_die,
&m_dwo_abbrev_table) == 0)
{
This is an optimization for when we already have the abbrev table.
If USE_EXISTING_CU is non-zero, and THIS_CU->cu is non-NULL, then use it.
- Otherwise, a new CU is allocated with xmalloc.
-
- If KEEP is non-zero, then if we allocated a dwarf2_cu we add it to
- read_in_chain. Otherwise the dwarf2_cu data is freed at the
- end. */
+ Otherwise, a new CU is allocated with xmalloc. */
cutu_reader::cutu_reader (struct dwarf2_per_cu_data *this_cu,
struct abbrev_table *abbrev_table,
- int use_existing_cu, int keep,
+ int use_existing_cu,
bool skip_partial)
: die_reader_specs {},
- m_this_cu (this_cu),
- m_keep (keep)
+ m_this_cu (this_cu)
{
struct dwarf2_per_objfile *dwarf2_per_objfile = this_cu->dwarf2_per_objfile;
struct objfile *objfile = dwarf2_per_objfile->objfile;
this_cu->is_debug_types ? "type" : "comp",
sect_offset_str (this_cu->sect_off));
- if (use_existing_cu)
- gdb_assert (keep);
-
/* If we're reading a TU directly from a DWO file, including a virtual DWO
file (instead of going through the stub), short-circuit all of this. */
if (this_cu->reading_dwo_directly)
/* Narrow down the scope of possibilities to have to understand. */
gdb_assert (this_cu->is_debug_types);
gdb_assert (abbrev_table == NULL);
- init_tu_and_read_dwo_dies (this_cu, use_existing_cu, keep);
+ init_tu_and_read_dwo_dies (this_cu, use_existing_cu);
return;
}
/* LENGTH has not been set yet for type units if we're
using .gdb_index. */
- this_cu->length = get_cu_length (&cu->header);
+ this_cu->length = cu->header.get_length ();
/* Establish the type offset that can be used to lookup the type. */
sig_type->type_offset_in_section =
rcuh_kind::COMPILE);
gdb_assert (this_cu->sect_off == cu->header.sect_off);
- gdb_assert (this_cu->length == get_cu_length (&cu->header));
+ gdb_assert (this_cu->length == cu->header.get_length ());
this_cu->dwarf_version = cu->header.version;
}
}
}
}
-cutu_reader::~cutu_reader ()
+void
+cutu_reader::keep ()
{
/* Done, clean up. */
- if (m_new_cu != NULL && m_keep && !dummy_p)
+ gdb_assert (!dummy_p);
+ if (m_new_cu != NULL)
{
struct dwarf2_per_objfile *dwarf2_per_objfile
= m_this_cu->dwarf2_per_objfile;
m_new_cu->str_offsets_base = parent_cu->str_offsets_base;
m_new_cu->addr_base = parent_cu->addr_base;
}
- this_cu->length = get_cu_length (&m_new_cu->header);
+ this_cu->length = m_new_cu->header.get_length ();
/* Skip dummy compilation units. */
if (info_ptr >= begin_info_ptr + this_cu->length
/* Allocate a hash table for type unit groups. */
static htab_up
-allocate_type_unit_groups_table (struct objfile *objfile)
+allocate_type_unit_groups_table ()
{
return htab_up (htab_create_alloc (3,
hash_type_unit_group,
struct type_unit_group type_unit_group_for_lookup;
if (dwarf2_per_objfile->type_unit_groups == NULL)
- {
- dwarf2_per_objfile->type_unit_groups =
- allocate_type_unit_groups_table (dwarf2_per_objfile->objfile);
- }
+ dwarf2_per_objfile->type_unit_groups = allocate_type_unit_groups_table ();
/* Do we need to create a new group, or can we use an existing one? */
process_psymtab_comp_unit_reader (const struct die_reader_specs *reader,
const gdb_byte *info_ptr,
struct die_info *comp_unit_die,
- int want_partial_unit,
enum language pretend_language)
{
struct dwarf2_cu *cu = reader->cu;
enum pc_bounds_kind cu_bounds_kind;
const char *filename;
- if (comp_unit_die->tag == DW_TAG_partial_unit && !want_partial_unit)
- return;
-
gdb_assert (! per_cu->is_debug_types);
prepare_one_comp_unit (cu, comp_unit_die, pretend_language);
/* Allocate a new partial symbol table structure. */
+ gdb::unique_xmalloc_ptr<char> debug_filename;
+ static const char artificial[] = "<artificial>";
filename = dwarf2_string_attr (comp_unit_die, DW_AT_name, cu);
if (filename == NULL)
filename = "";
+ else if (strcmp (filename, artificial) == 0)
+ {
+ debug_filename.reset (concat (artificial, "@",
+ sect_offset_str (per_cu->sect_off),
+ (char *) NULL));
+ filename = debug_filename.get ();
+ }
pst = create_partial_symtab (per_cu, filename);
static void
process_psymtab_comp_unit (struct dwarf2_per_cu_data *this_cu,
- int want_partial_unit,
+ bool want_partial_unit,
enum language pretend_language)
{
/* If this compilation unit was already read in, free the
if (this_cu->cu != NULL)
free_one_cached_comp_unit (this_cu);
- cutu_reader reader (this_cu, NULL, 0, 0, false);
+ cutu_reader reader (this_cu, NULL, 0, false);
+
+ switch (reader.comp_unit_die->tag)
+ {
+ case DW_TAG_compile_unit:
+ this_cu->unit_type = DW_UT_compile;
+ break;
+ case DW_TAG_partial_unit:
+ this_cu->unit_type = DW_UT_partial;
+ break;
+ default:
+ abort ();
+ }
if (reader.dummy_p)
{
else if (this_cu->is_debug_types)
build_type_psymtabs_reader (&reader, reader.info_ptr,
reader.comp_unit_die);
- else
+ else if (want_partial_unit
+ || reader.comp_unit_die->tag != DW_TAG_partial_unit)
process_psymtab_comp_unit_reader (&reader, reader.info_ptr,
reader.comp_unit_die,
- want_partial_unit,
pretend_language);
+ this_cu->lang = this_cu->cu->language;
+
/* Age out any secondary CUs. */
age_cached_comp_units (this_cu->dwarf2_per_objfile);
}
if (! type_unit_die->has_children)
return;
- attr = dwarf2_attr_no_follow (type_unit_die, DW_AT_stmt_list);
+ attr = type_unit_die->attr (DW_AT_stmt_list);
tu_group = get_type_unit_group (cu, attr);
if (tu_group->tus == nullptr)
}
cutu_reader reader (&tu.sig_type->per_cu, abbrev_table.get (),
- 0, 0, false);
+ 0, false);
if (!reader.dummy_p)
build_type_psymtabs_reader (&reader, reader.info_ptr,
reader.comp_unit_die);
int i;
gdb_assert (len > 0);
- gdb_assert (IS_TYPE_UNIT_GROUP (per_cu));
+ gdb_assert (per_cu->type_unit_group_p ());
pst->number_of_dependencies = len;
pst->dependencies = objfile->partial_symtabs->allocate_dependencies (len);
/* 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 (dwarf2_per_objfile->objfile);
- }
+ dwarf2_per_objfile->signatured_types = allocate_signatured_type_table ();
find_entry.signature = dwo_unit->signature;
slot = htab_find_slot (dwarf2_per_objfile->signatured_types.get (),
*slot = entry;
/* This does the job that build_type_psymtabs_1 would have done. */
- cutu_reader reader (&entry->per_cu, NULL, 0, 0, false);
+ cutu_reader reader (&entry->per_cu, NULL, 0, false);
if (!reader.dummy_p)
build_type_psymtabs_reader (&reader, reader.info_ptr,
reader.comp_unit_die);
objfile_name (objfile));
}
- dwarf2_per_objfile->reading_partial_symbols = 1;
+ scoped_restore restore_reading_psyms
+ = make_scoped_restore (&dwarf2_per_objfile->reading_partial_symbols,
+ true);
dwarf2_per_objfile->info.read (objfile);
addrmap_create_mutable (&temp_obstack));
for (dwarf2_per_cu_data *per_cu : dwarf2_per_objfile->all_comp_units)
- process_psymtab_comp_unit (per_cu, 0, language_minimal);
+ process_psymtab_comp_unit (per_cu, false, language_minimal);
/* This has to wait until we read the CUs, we need the list of DWOs. */
process_skeletonless_type_units (dwarf2_per_objfile);
static void
load_partial_comp_unit (struct dwarf2_per_cu_data *this_cu)
{
- cutu_reader reader (this_cu, NULL, 1, 1, false);
+ cutu_reader reader (this_cu, NULL, 1, false);
if (!reader.dummy_p)
{
If not, there's no more debug_info for this comp unit. */
if (reader.comp_unit_die->has_children)
load_partial_dies (&reader, reader.info_ptr, 0);
+
+ reader.keep ();
}
}
/* Go read the partial unit, if needed. */
if (per_cu->v.psymtab == NULL)
- process_psymtab_comp_unit (per_cu, 1, cu->language);
+ process_psymtab_comp_unit (per_cu, true, cu->language);
cu->per_cu->imported_symtabs_push (per_cu);
}
if (sibling_ptr < info_ptr)
complaint (_("DW_AT_sibling points backwards"));
else if (sibling_ptr > reader->buffer_end)
- dwarf2_section_buffer_overflow_complaint (reader->die_section);
+ reader->die_section->overflow_complaint ();
else
return sibling_ptr;
}
= dpo_backlink->has_section_at_zero;
}
- dwarf2_per_objfile->reading_partial_symbols = 0;
-
expand_psymtab (objfile);
process_cu_includes (dwarf2_per_objfile);
void
dwarf2_psymtab::expand_psymtab (struct objfile *objfile)
{
- struct dwarf2_per_cu_data *per_cu;
-
if (readin)
return;
read_dependencies (objfile);
- per_cu = per_cu_data;
-
- if (per_cu == NULL)
- {
- /* It's an include file, no symbols to read for it.
- Everything is in the parent symtab. */
- readin = true;
- return;
- }
-
- dw2_do_instantiate_symtab (per_cu, false);
+ dw2_do_instantiate_symtab (per_cu_data, false);
+ gdb_assert (get_compunit_symtab () != nullptr);
}
/* Trivial hash function for die_info: the hash value of a DIE
{
gdb_assert (! this_cu->is_debug_types);
- cutu_reader reader (this_cu, NULL, 1, 1, skip_partial);
+ cutu_reader reader (this_cu, NULL, 1, skip_partial);
if (reader.dummy_p)
return;
Similarly, if we do not read the producer, we can not apply
producer-specific interpretation. */
prepare_one_comp_unit (cu, cu->dies, pretend_language);
+
+ reader.keep ();
}
/* Add a DIE to the delayed physname list. */
if (package_name != NULL)
{
struct objfile *objfile = cu->per_cu->dwarf2_per_objfile->objfile;
- const char *saved_package_name
- = obstack_strdup (&objfile->per_bfd->storage_obstack, package_name.get ());
+ const char *saved_package_name = objfile->intern (package_name.get ());
struct type *type = init_type (objfile, TYPE_CODE_MODULE, 0,
saved_package_name);
struct symbol *sym;
= dwarf2_find_containing_comp_unit (sect_off, is_dwz,
cu->per_cu->dwarf2_per_objfile);
+ /* We're importing a C++ compilation unit with tag DW_TAG_compile_unit
+ into another compilation unit, at root level. Regard this as a hint,
+ and ignore it. */
+ if (die->parent && die->parent->parent == NULL
+ && per_cu->unit_type == DW_UT_compile
+ && per_cu->lang == language_cplus)
+ return;
+
/* If necessary, add it to the queue and load its DIEs. */
if (maybe_queue_comp_unit (cu, per_cu, cu->language))
load_full_comp_unit (per_cu, false, cu->language);
if (cu->language == language_cplus)
canonical_name
= dwarf2_canonicalize_name (intermediate_name.c_str (), cu,
- &objfile->per_bfd->storage_obstack);
+ objfile);
/* If we only computed INTERMEDIATE_NAME, or if
INTERMEDIATE_NAME is already canonical, then we need to
- copy it to the appropriate obstack. */
+ intern it. */
if (canonical_name == NULL || canonical_name == intermediate_name.c_str ())
- name = obstack_strdup (&objfile->per_bfd->storage_obstack,
- intermediate_name);
+ name = objfile->intern (intermediate_name);
else
name = canonical_name;
}
retval = canon;
if (need_copy)
- retval = obstack_strdup (&objfile->per_bfd->storage_obstack, retval);
+ retval = objfile->intern (retval);
return retval;
}
if (die->tag == DW_TAG_imported_module && cu->language == language_fortran)
for (child_die = die->child; child_die && child_die->tag;
- child_die = sibling_die (child_die))
+ child_die = child_die->sibling)
{
/* DWARF-4: A Fortran use statement with a “rename list” may be
represented by an imported module entry with an import attribute
while (child_die && child_die->tag)
{
process_die (child_die, cu);
- child_die = sibling_die (child_die);
+ child_die = child_die->sibling;
}
}
process_full_type_unit still needs to know if this is the first
time. */
- tu_group->num_symtabs = line_header->file_names_size ();
- tu_group->symtabs = XNEWVEC (struct symtab *,
- line_header->file_names_size ());
+ tu_group->symtabs
+ = XOBNEWVEC (&COMPUNIT_OBJFILE (cust)->objfile_obstack,
+ struct symtab *, line_header->file_names_size ());
auto &file_names = line_header->file_names ();
for (i = 0; i < file_names.size (); ++i)
while (child_die && child_die->tag)
{
process_die (child_die, cu);
- child_die = sibling_die (child_die);
+ child_die = child_die->sibling;
}
}
}
/* Allocate a hash table for DWO files. */
static htab_up
-allocate_dwo_file_hash_table (struct objfile *objfile)
+allocate_dwo_file_hash_table ()
{
auto delete_dwo_file = [] (void *item)
{
void **slot;
if (dwarf2_per_objfile->dwo_files == NULL)
- dwarf2_per_objfile->dwo_files
- = allocate_dwo_file_hash_table (dwarf2_per_objfile->objfile);
+ dwarf2_per_objfile->dwo_files = allocate_dwo_file_hash_table ();
find_entry.dwo_name = dwo_name;
find_entry.comp_dir = comp_dir;
There is one of these tables for each of CUs,TUs for each DWO file. */
static htab_up
-allocate_dwo_unit_table (struct objfile *objfile)
+allocate_dwo_unit_table ()
{
/* Start out with a pretty small number.
Generally DWO files contain only one CU and maybe some TUs. */
continue;
if (cus_htab == NULL)
- cus_htab = allocate_dwo_unit_table (objfile);
+ cus_htab = allocate_dwo_unit_table ();
dwo_unit = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwo_unit);
*dwo_unit = read_unit;
virtual_dwo_name.c_str ());
}
dwo_file = new struct dwo_file;
- dwo_file->dwo_name = obstack_strdup (&objfile->objfile_obstack,
- virtual_dwo_name);
+ dwo_file->dwo_name = objfile->intern (virtual_dwo_name);
dwo_file->comp_dir = comp_dir;
dwo_file->sections.abbrev = sections.abbrev;
dwo_file->sections.line = sections.line;
virtual_dwo_name.c_str ());
}
dwo_file = new struct dwo_file;
- dwo_file->dwo_name = obstack_strdup (&objfile->objfile_obstack,
- virtual_dwo_name);
+ dwo_file->dwo_name = objfile->intern (virtual_dwo_name);
dwo_file->comp_dir = comp_dir;
dwo_file->sections.abbrev =
create_dwp_v2_section (dwarf2_per_objfile, &dwp_file->sections.abbrev,
/* Allocate a hash table for dwp_file loaded CUs/TUs. */
static htab_up
-allocate_dwp_loaded_cutus_table (struct objfile *objfile)
+allocate_dwp_loaded_cutus_table ()
{
return htab_up (htab_create_alloc (3,
hash_dwp_loaded_cutus,
dwarf2_locate_v2_dwp_sections,
dwp_file.get ());
- dwp_file->loaded_cus = allocate_dwp_loaded_cutus_table (objfile);
- dwp_file->loaded_tus = allocate_dwp_loaded_cutus_table (objfile);
+ dwp_file->loaded_cus = allocate_dwp_loaded_cutus_table ();
+ dwp_file->loaded_tus = allocate_dwp_loaded_cutus_table ();
if (dwarf_read_debug)
{
for (child_die = die->child;
child_die && child_die->tag;
- child_die = sibling_die (child_die))
+ child_die = child_die->sibling)
{
struct die_info *child_origin_die;
struct dwarf2_cu *child_origin_cu;
if (!origin_child_die->in_process)
process_die (origin_child_die, origin_cu);
}
- origin_child_die = sibling_die (origin_child_die);
+ origin_child_die = origin_child_die->sibling;
}
origin_cu->list_in_scope = origin_previous_list_in_scope;
/* If we have any template arguments, then we must allocate a
different sort of symbol. */
- for (child_die = die->child; child_die; child_die = sibling_die (child_die))
+ for (child_die = die->child; child_die; child_die = child_die->sibling)
{
if (child_die->tag == DW_TAG_template_type_param
|| child_die->tag == DW_TAG_template_value_param)
}
else
process_die (child_die, cu);
- child_die = sibling_die (child_die);
+ child_die = child_die->sibling;
}
}
{
if (child_die->tag == DW_TAG_imported_module)
process_die (child_die, spec_cu);
- child_die = sibling_die (child_die);
+ child_die = child_die->sibling;
}
/* In some cases, GCC generates specification DIEs that
GCC does no longer produces such DWARF since GCC r224161. */
for (child_die = die->child;
child_die != NULL && child_die->tag;
- child_die = sibling_die (child_die))
+ child_die = child_die->sibling)
process_die (child_die, cu);
return;
case PC_BOUNDS_INVALID:
while (child_die && child_die->tag)
{
process_die (child_die, cu);
- child_die = sibling_die (child_die);
+ child_die = child_die->sibling;
}
}
inherit_abstract_dies (die, cu);
nparams = 0;
for (child_die = die->child; child_die && child_die->tag;
- child_die = sibling_die (child_die))
+ child_die = child_die->sibling)
{
if (child_die->tag != DW_TAG_call_site_parameter
&& child_die->tag != DW_TAG_GNU_call_site_parameter)
for (child_die = die->child;
child_die && child_die->tag;
- child_die = sibling_die (child_die))
+ child_die = child_die->sibling)
{
struct call_site_parameter *parameter;
struct attribute *loc, *origin;
sect_offset sect_off
= (sect_offset) dwarf2_get_ref_die_offset (origin);
- if (!offset_in_cu_p (&cu->header, sect_off))
+ if (!cu->header.offset_in_cu_p (sect_off))
{
/* As DW_OP_GNU_parameter_ref uses CU-relative offset this
binding can be done only inside one CU. Such referenced DIE
struct objfile *objfile = dwarf2_per_objfile->objfile;
bfd *obfd = objfile->obfd;
/* Base address selection entry. */
- CORE_ADDR base;
- int found_base;
+ gdb::optional<CORE_ADDR> base;
const gdb_byte *buffer;
CORE_ADDR baseaddr;
bool overflow = false;
- found_base = cu->base_known;
base = cu->base_address;
dwarf2_per_objfile->rnglists.read (objfile);
overflow = true;
break;
}
- base = read_address (obfd, buffer, cu, &bytes_read);
- found_base = 1;
+ base = cu->header.read_address (obfd, buffer, &bytes_read);
buffer += bytes_read;
break;
case DW_RLE_start_length:
overflow = true;
break;
}
- range_beginning = read_address (obfd, buffer, cu, &bytes_read);
+ range_beginning = cu->header.read_address (obfd, buffer,
+ &bytes_read);
buffer += bytes_read;
range_end = (range_beginning
+ read_unsigned_leb128 (obfd, buffer, &bytes_read));
overflow = true;
break;
}
- range_beginning = read_address (obfd, buffer, cu, &bytes_read);
+ range_beginning = cu->header.read_address (obfd, buffer,
+ &bytes_read);
buffer += bytes_read;
- range_end = read_address (obfd, buffer, cu, &bytes_read);
+ range_end = cu->header.read_address (obfd, buffer, &bytes_read);
buffer += bytes_read;
break;
default:
if (rlet == DW_RLE_base_address)
continue;
- if (!found_base)
+ if (!base.has_value ())
{
/* We have no valid base address for the ranges
data. */
if (range_beginning == range_end)
continue;
- range_beginning += base;
- range_end += base;
+ range_beginning += *base;
+ range_end += *base;
/* A not-uncommon case of bad debug info.
Don't pollute the addrmap with bad data. */
unsigned int addr_size = cu_header->addr_size;
CORE_ADDR mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1));
/* Base address selection entry. */
- CORE_ADDR base;
- int found_base;
+ gdb::optional<CORE_ADDR> base;
unsigned int dummy;
const gdb_byte *buffer;
CORE_ADDR baseaddr;
if (cu_header->version >= 5)
return dwarf2_rnglists_process (offset, cu, callback);
- found_base = cu->base_known;
base = cu->base_address;
dwarf2_per_objfile->ranges.read (objfile);
{
CORE_ADDR range_beginning, range_end;
- range_beginning = read_address (obfd, buffer, cu, &dummy);
+ range_beginning = cu->header.read_address (obfd, buffer, &dummy);
buffer += addr_size;
- range_end = read_address (obfd, buffer, cu, &dummy);
+ range_end = cu->header.read_address (obfd, buffer, &dummy);
buffer += addr_size;
offset += 2 * addr_size;
/* If we found the largest possible address, then we already
have the base address in range_end. */
base = range_end;
- found_base = 1;
continue;
}
- if (!found_base)
+ if (!base.has_value ())
{
/* We have no valid base address for the ranges
data. */
if (range_beginning == range_end)
continue;
- range_beginning += base;
- range_end += base;
+ range_beginning += *base;
+ range_end += *base;
/* A not-uncommon case of bad debug info.
Don't pollute the addrmap with bad data. */
if (child->tag == DW_TAG_subprogram
|| child->tag == DW_TAG_lexical_block)
dwarf2_get_subprogram_pc_bounds (child, lowpc, highpc, cu);
- child = sibling_die (child);
+ child = child->sibling;
}
}
break;
}
- child = sibling_die (child);
+ child = child->sibling;
}
}
new_field = &fip->fields.back ();
}
- fip->nfields++;
-
attr = dwarf2_attr (die, DW_AT_accessibility, cu);
if (attr != nullptr)
new_field->accessibility = DW_UNSND (attr);
dwarf2_attach_fields_to_type (struct field_info *fip, struct type *type,
struct dwarf2_cu *cu)
{
- int nfields = fip->nfields;
+ int nfields = fip->nfields ();
/* Record the field count, allocate space for the array of fields,
and create blank accessibility bitfields if necessary. */
/* If the definition of this type lives in .debug_types, read that type.
Don't follow DW_AT_specification though, that will take us back up
the chain and we want to go down. */
- attr = dwarf2_attr_no_follow (die, DW_AT_signature);
+ attr = die->attr (DW_AT_signature);
if (attr != nullptr)
{
type = get_DW_AT_signature_type (die, attr, cu);
for (die_info *variant_child = child_die->child;
variant_child != NULL;
- variant_child = sibling_die (variant_child))
+ variant_child = variant_child->sibling)
{
if (variant_child->tag == DW_TAG_member)
{
if (is_variant_part && discr_offset == child_die->sect_off)
fi.fields.back ().variant.is_discriminant = true;
- child_die = sibling_die (child_die);
+ child_die = child_die->sibling;
}
/* Attach template arguments to type. */
}
/* Attach fields and member functions to the type. */
- if (fi.nfields)
+ if (fi.nfields () > 0)
dwarf2_attach_fields_to_type (&fi, type, cu);
if (!fi.fnfieldlists.empty ())
{
else
process_die (child_die, cu);
- child_die = sibling_die (child_die);
+ child_die = child_die->sibling;
}
/* Do not consider external references. According to the DWARF standard,
struct die_info *child_die;
int unsigned_enum = 1;
int flag_enum = 1;
- ULONGEST mask = 0;
auto_obstack obstack;
for (child_die = die->child;
child_die != NULL && child_die->tag;
- child_die = sibling_die (child_die))
+ child_die = child_die->sibling)
{
struct attribute *attr;
LONGEST value;
unsigned_enum = 0;
flag_enum = 0;
}
- else if ((mask & value) != 0)
- flag_enum = 0;
else
- mask |= value;
+ {
+ if (count_one_bits_ll (value) >= 2)
+ flag_enum = 0;
+ }
/* 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 the definition of this type lives in .debug_types, read that type.
Don't follow DW_AT_specification though, that will take us back up
the chain and we want to go down. */
- attr = dwarf2_attr_no_follow (die, DW_AT_signature);
+ attr = die->attr (DW_AT_signature);
if (attr != nullptr)
{
type = get_DW_AT_signature_type (die, attr, cu);
}
}
- child_die = sibling_die (child_die);
+ child_die = child_die->sibling;
}
if (!fields.empty ())
range_types.push_back (child_type);
}
}
- child_die = sibling_die (child_die);
+ child_die = child_die->sibling;
}
/* Dwarf2 dimensions are output from left to right, create the
for (child_die = die->child;
child_die && child_die->tag;
- child_die = sibling_die (child_die))
+ child_die = child_die->sibling)
++n_entries;
size = (sizeof (struct common_block)
for (child_die = die->child;
child_die && child_die->tag;
- child_die = sibling_die (child_die))
+ child_die = child_die->sibling)
{
/* Create the symbol in the DW_TAG_common_block block in the current
symbol scope. */
while (child_die && child_die->tag)
{
process_die (child_die, cu);
- child_die = sibling_die (child_die);
+ child_die = child_die->sibling;
}
}
}
while (child_die && child_die->tag)
{
process_die (child_die, cu);
- child_die = sibling_die (child_die);
+ child_die = child_die->sibling;
}
}
nparams++;
else if (child_die->tag == DW_TAG_unspecified_parameters)
TYPE_VARARGS (ftype) = 1;
- child_die = sibling_die (child_die);
+ child_die = child_die->sibling;
}
/* Allocate storage for parameters and fill them in. */
TYPE_FIELD_TYPE (ftype, iparams) = arg_type;
iparams++;
}
- child_die = sibling_die (child_die);
+ child_die = child_die->sibling;
}
}
sect_offset_str (die->sect_off), objfile_name (objfile));
TYPE_TARGET_TYPE (this_type) = NULL;
}
+ if (name == NULL)
+ {
+ /* Gcc-7 and before supports -feliminate-dwarf2-dups, which generates
+ anonymous typedefs, which is, strictly speaking, invalid DWARF.
+ Handle these by just returning the target type, rather than
+ constructing an anonymous typedef type and trying to handle this
+ elsewhere. */
+ set_die_type (die, target_type, cu);
+ return target_type;
+ }
return this_type;
}
indexes_that_need_reprocess.push_back (i);
}
- struct attribute *attr = dwarf2_attr_no_follow (die, DW_AT_str_offsets_base);
+ struct attribute *attr = die->attr (DW_AT_str_offsets_base);
if (attr != nullptr)
cu->str_offsets_base = DW_UNSND (attr);
- auto maybe_addr_base = lookup_addr_base(die);
+ auto maybe_addr_base = die->addr_base ();
if (maybe_addr_base.has_value ())
cu->addr_base = *maybe_addr_base;
for (int index : indexes_that_need_reprocess)
struct objfile *objfile = dwarf2_per_objfile->objfile;
name
- = dwarf2_canonicalize_name (DW_STRING (&attr), cu,
- &objfile->per_bfd->storage_obstack);
+ = dwarf2_canonicalize_name (DW_STRING (&attr), cu, objfile);
}
break;
}
if (sibling_ptr < info_ptr)
complaint (_("DW_AT_sibling points backwards"));
else if (sibling_ptr > reader->buffer_end)
- dwarf2_section_buffer_overflow_complaint (reader->die_section);
+ reader->die_section->overflow_complaint ();
else
sibling = sibling_ptr;
}
struct partial_die_info *pd = NULL;
if (offset_in_dwz == cu->per_cu->is_dwz
- && offset_in_cu_p (&cu->header, sect_off))
+ && cu->header.offset_in_cu_p (sect_off))
{
pd = cu->find_partial_die (sect_off);
if (pd != NULL)
if (actual_class_name != NULL)
{
struct objfile *objfile = cu->per_cu->dwarf2_per_objfile->objfile;
- struct_pdi->name
- = obstack_strdup (&objfile->per_bfd->storage_obstack,
- actual_class_name.get ());
+ struct_pdi->name = objfile->intern (actual_class_name.get ());
}
break;
}
base = demangled.get ();
struct objfile *objfile = cu->per_cu->dwarf2_per_objfile->objfile;
- name = obstack_strdup (&objfile->per_bfd->storage_obstack, base);
+ name = objfile->intern (base);
}
}
{
case DW_FORM_ref_addr:
if (cu->header.version == 2)
- DW_UNSND (attr) = read_address (abfd, info_ptr, cu, &bytes_read);
+ DW_UNSND (attr) = cu->header.read_address (abfd, info_ptr,
+ &bytes_read);
else
- DW_UNSND (attr) = read_offset (abfd, info_ptr,
- &cu->header, &bytes_read);
+ DW_UNSND (attr) = cu->header.read_offset (abfd, info_ptr,
+ &bytes_read);
info_ptr += bytes_read;
break;
case DW_FORM_GNU_ref_alt:
- DW_UNSND (attr) = read_offset (abfd, info_ptr, &cu->header, &bytes_read);
+ DW_UNSND (attr) = cu->header.read_offset (abfd, info_ptr, &bytes_read);
info_ptr += bytes_read;
break;
case DW_FORM_addr:
- DW_ADDR (attr) = read_address (abfd, info_ptr, cu, &bytes_read);
+ DW_ADDR (attr) = cu->header.read_address (abfd, info_ptr, &bytes_read);
DW_ADDR (attr) = gdbarch_adjust_dwarf2_addr (gdbarch, DW_ADDR (attr));
info_ptr += bytes_read;
break;
DW_BLOCK (attr) = blk;
break;
case DW_FORM_sec_offset:
- DW_UNSND (attr) = read_offset (abfd, info_ptr, &cu->header, &bytes_read);
+ DW_UNSND (attr) = cu->header.read_offset (abfd, info_ptr, &bytes_read);
info_ptr += bytes_read;
break;
case DW_FORM_string:
case DW_FORM_line_strp:
if (!cu->per_cu->is_dwz)
{
- DW_STRING (attr) = read_indirect_line_string (dwarf2_per_objfile,
- abfd, info_ptr,
- cu_header, &bytes_read);
+ DW_STRING (attr)
+ = dwarf2_per_objfile->read_line_string (info_ptr, cu_header,
+ &bytes_read);
DW_STRING_IS_CANONICAL (attr) = 0;
info_ptr += bytes_read;
break;
case DW_FORM_GNU_strp_alt:
{
struct dwz_file *dwz = dwarf2_get_dwz_file (dwarf2_per_objfile);
- LONGEST str_offset = read_offset (abfd, info_ptr, cu_header,
- &bytes_read);
+ LONGEST str_offset = cu_header->read_offset (abfd, info_ptr,
+ &bytes_read);
- DW_STRING (attr) = read_indirect_string_from_dwz (objfile,
- dwz, str_offset);
+ DW_STRING (attr) = dwz->read_string (objfile, str_offset);
DW_STRING_IS_CANONICAL (attr) = 0;
info_ptr += bytes_read;
}
need_reprocess);
}
-static CORE_ADDR
-read_address (bfd *abfd, const gdb_byte *buf, struct dwarf2_cu *cu,
- unsigned int *bytes_read)
+/* Return pointer to string at .debug_str offset STR_OFFSET. */
+
+static const char *
+read_indirect_string_at_offset (struct dwarf2_per_objfile *dwarf2_per_objfile,
+ LONGEST str_offset)
{
- struct comp_unit_head *cu_header = &cu->header;
- CORE_ADDR retval = 0;
-
- if (cu_header->signed_addr_p)
- {
- switch (cu_header->addr_size)
- {
- case 2:
- retval = bfd_get_signed_16 (abfd, buf);
- break;
- case 4:
- retval = bfd_get_signed_32 (abfd, buf);
- break;
- case 8:
- retval = bfd_get_signed_64 (abfd, buf);
- break;
- default:
- internal_error (__FILE__, __LINE__,
- _("read_address: bad switch, signed [in module %s]"),
- bfd_get_filename (abfd));
- }
- }
- else
- {
- switch (cu_header->addr_size)
- {
- case 2:
- retval = bfd_get_16 (abfd, buf);
- break;
- case 4:
- retval = bfd_get_32 (abfd, buf);
- break;
- case 8:
- retval = bfd_get_64 (abfd, buf);
- break;
- default:
- internal_error (__FILE__, __LINE__,
- _("read_address: bad switch, "
- "unsigned [in module %s]"),
- bfd_get_filename (abfd));
- }
- }
-
- *bytes_read = cu_header->addr_size;
- return retval;
-}
-
-/* Read the initial length from a section. The (draft) DWARF 3
- specification allows the initial length to take up either 4 bytes
- or 12 bytes. If the first 4 bytes are 0xffffffff, then the next 8
- bytes describe the length and all offsets will be 8 bytes in length
- instead of 4.
-
- An older, non-standard 64-bit format is also handled by this
- function. The older format in question stores the initial length
- as an 8-byte quantity without an escape value. Lengths greater
- than 2^32 aren't very common which means that the initial 4 bytes
- is almost always zero. Since a length value of zero doesn't make
- sense for the 32-bit format, this initial zero can be considered to
- be an escape value which indicates the presence of the older 64-bit
- format. As written, the code can't detect (old format) lengths
- greater than 4GB. If it becomes necessary to handle lengths
- somewhat larger than 4GB, we could allow other small values (such
- as the non-sensical values of 1, 2, and 3) to also be used as
- escape values indicating the presence of the old format.
-
- The value returned via bytes_read should be used to increment the
- relevant pointer after calling read_initial_length().
-
- [ Note: read_initial_length() and read_offset() are based on the
- document entitled "DWARF Debugging Information Format", revision
- 3, draft 8, dated November 19, 2001. This document was obtained
- from:
-
- http://reality.sgiweb.org/davea/dwarf3-draft8-011125.pdf
-
- This document is only a draft and is subject to change. (So beware.)
-
- Details regarding the older, non-standard 64-bit format were
- determined empirically by examining 64-bit ELF files produced by
- the SGI toolchain on an IRIX 6.5 machine.
-
- - Kevin, July 16, 2002
- ] */
-
-static LONGEST
-read_initial_length (bfd *abfd, const gdb_byte *buf, unsigned int *bytes_read)
-{
- LONGEST length = bfd_get_32 (abfd, buf);
-
- if (length == 0xffffffff)
- {
- length = bfd_get_64 (abfd, buf + 4);
- *bytes_read = 12;
- }
- else if (length == 0)
- {
- /* Handle the (non-standard) 64-bit DWARF2 format used by IRIX. */
- length = bfd_get_64 (abfd, buf);
- *bytes_read = 8;
- }
- else
- {
- *bytes_read = 4;
- }
-
- return length;
-}
-
-/* Cover function for read_initial_length.
- Returns the length of the object at BUF, and stores the size of the
- initial length in *BYTES_READ and stores the size that offsets will be in
- *OFFSET_SIZE.
- If the initial length size is not equivalent to that specified in
- CU_HEADER then issue a complaint.
- This is useful when reading non-comp-unit headers. */
-
-static LONGEST
-read_checked_initial_length_and_offset (bfd *abfd, const gdb_byte *buf,
- const struct comp_unit_head *cu_header,
- unsigned int *bytes_read,
- unsigned int *offset_size)
-{
- LONGEST length = read_initial_length (abfd, buf, bytes_read);
-
- gdb_assert (cu_header->initial_length_size == 4
- || cu_header->initial_length_size == 8
- || cu_header->initial_length_size == 12);
-
- if (cu_header->initial_length_size != *bytes_read)
- complaint (_("intermixed 32-bit and 64-bit DWARF sections"));
-
- *offset_size = (*bytes_read == 4) ? 4 : 8;
- return length;
-}
-
-/* Read an offset from the data stream. The size of the offset is
- given by cu_header->offset_size. */
-
-static LONGEST
-read_offset (bfd *abfd, const gdb_byte *buf,
- const struct comp_unit_head *cu_header,
- unsigned int *bytes_read)
-{
- LONGEST offset = read_offset_1 (abfd, buf, cu_header->offset_size);
-
- *bytes_read = cu_header->offset_size;
- return offset;
-}
-
-/* Read an offset from the data stream. */
-
-static LONGEST
-read_offset_1 (bfd *abfd, const gdb_byte *buf, unsigned int offset_size)
-{
- LONGEST retval = 0;
-
- switch (offset_size)
- {
- case 4:
- retval = bfd_get_32 (abfd, buf);
- break;
- case 8:
- retval = bfd_get_64 (abfd, buf);
- break;
- default:
- internal_error (__FILE__, __LINE__,
- _("read_offset_1: bad switch [in module %s]"),
- bfd_get_filename (abfd));
- }
-
- return retval;
-}
-
-static const gdb_byte *
-read_n_bytes (bfd *abfd, const gdb_byte *buf, unsigned int size)
-{
- /* If the size of a host char is 8 bits, we can return a pointer
- to the buffer, otherwise we have to copy the data to a buffer
- allocated on the temporary obstack. */
- gdb_assert (HOST_CHAR_BIT == 8);
- return buf;
-}
-
-static const char *
-read_direct_string (bfd *abfd, const gdb_byte *buf,
- unsigned int *bytes_read_ptr)
-{
- /* If the size of a host char is 8 bits, we can return a pointer
- to the string, otherwise we have to copy the string to a buffer
- allocated on the temporary obstack. */
- gdb_assert (HOST_CHAR_BIT == 8);
- if (*buf == '\0')
- {
- *bytes_read_ptr = 1;
- return NULL;
- }
- *bytes_read_ptr = strlen ((const char *) buf) + 1;
- return (const char *) buf;
-}
-
-/* Return pointer to string at section SECT offset STR_OFFSET with error
- reporting strings FORM_NAME and SECT_NAME. */
-
-static const char *
-read_indirect_string_at_offset_from (struct objfile *objfile,
- bfd *abfd, LONGEST str_offset,
- struct dwarf2_section_info *sect,
- const char *form_name,
- const char *sect_name)
-{
- sect->read (objfile);
- if (sect->buffer == NULL)
- error (_("%s used without %s section [in module %s]"),
- form_name, sect_name, bfd_get_filename (abfd));
- if (str_offset >= sect->size)
- error (_("%s pointing outside of %s section [in module %s]"),
- form_name, sect_name, bfd_get_filename (abfd));
- gdb_assert (HOST_CHAR_BIT == 8);
- if (sect->buffer[str_offset] == '\0')
- return NULL;
- return (const char *) (sect->buffer + str_offset);
-}
-
-/* Return pointer to string at .debug_str offset STR_OFFSET. */
-
-static const char *
-read_indirect_string_at_offset (struct dwarf2_per_objfile *dwarf2_per_objfile,
- bfd *abfd, LONGEST str_offset)
-{
- return read_indirect_string_at_offset_from (dwarf2_per_objfile->objfile,
- abfd, str_offset,
- &dwarf2_per_objfile->str,
- "DW_FORM_strp", ".debug_str");
-}
-
-/* Return pointer to string at .debug_line_str offset STR_OFFSET. */
-
-static const char *
-read_indirect_line_string_at_offset (struct dwarf2_per_objfile *dwarf2_per_objfile,
- bfd *abfd, LONGEST str_offset)
-{
- return read_indirect_string_at_offset_from (dwarf2_per_objfile->objfile,
- abfd, str_offset,
- &dwarf2_per_objfile->line_str,
- "DW_FORM_line_strp",
- ".debug_line_str");
-}
-
-/* Read a string at offset STR_OFFSET in the .debug_str section from
- the .dwz file DWZ. Throw an error if the offset is too large. If
- the string consists of a single NUL byte, return NULL; otherwise
- return a pointer to the string. */
-
-static const char *
-read_indirect_string_from_dwz (struct objfile *objfile, struct dwz_file *dwz,
- LONGEST str_offset)
-{
- dwz->str.read (objfile);
-
- if (dwz->str.buffer == NULL)
- error (_("DW_FORM_GNU_strp_alt used without .debug_str "
- "section [in module %s]"),
- bfd_get_filename (dwz->dwz_bfd.get ()));
- if (str_offset >= dwz->str.size)
- error (_("DW_FORM_GNU_strp_alt pointing outside of "
- ".debug_str section [in module %s]"),
- bfd_get_filename (dwz->dwz_bfd.get ()));
- gdb_assert (HOST_CHAR_BIT == 8);
- if (dwz->str.buffer[str_offset] == '\0')
- return NULL;
- return (const char *) (dwz->str.buffer + str_offset);
-}
+ return dwarf2_per_objfile->str.read_string (dwarf2_per_objfile->objfile,
+ str_offset, "DW_FORM_strp");
+}
/* Return pointer to string at .debug_str offset as read from BUF.
BUF is assumed to be in a compilation unit described by CU_HEADER.
const struct comp_unit_head *cu_header,
unsigned int *bytes_read_ptr)
{
- LONGEST str_offset = read_offset (abfd, buf, cu_header, bytes_read_ptr);
+ LONGEST str_offset = cu_header->read_offset (abfd, buf, bytes_read_ptr);
- return read_indirect_string_at_offset (dwarf2_per_objfile, abfd, str_offset);
+ return read_indirect_string_at_offset (dwarf2_per_objfile, str_offset);
}
-/* Return pointer to string at .debug_line_str offset as read from BUF.
- BUF is assumed to be in a compilation unit described by CU_HEADER.
- Return *BYTES_READ_PTR count of bytes read from BUF. */
+/* See read.h. */
-static const char *
-read_indirect_line_string (struct dwarf2_per_objfile *dwarf2_per_objfile,
- bfd *abfd, const gdb_byte *buf,
+const char *
+dwarf2_per_objfile::read_line_string (const gdb_byte *buf,
const struct comp_unit_head *cu_header,
unsigned int *bytes_read_ptr)
{
- LONGEST str_offset = read_offset (abfd, buf, cu_header, bytes_read_ptr);
+ bfd *abfd = objfile->obfd;
+ LONGEST str_offset = cu_header->read_offset (abfd, buf, bytes_read_ptr);
- return read_indirect_line_string_at_offset (dwarf2_per_objfile, abfd,
- str_offset);
+ return line_str.read_string (objfile, str_offset, "DW_FORM_line_strp");
}
/* Given index ADDR_INDEX in .debug_addr, fetch the value.
return read_addr_index (cu, addr_index);
}
-/* Given an index in .debug_addr, fetch the value.
- NOTE: This can be called during dwarf expression evaluation,
- long after the debug information has been read, and thus per_cu->cu
- may no longer exist. */
+/* See read.h. */
CORE_ADDR
-dwarf2_read_addr_index (struct dwarf2_per_cu_data *per_cu,
- unsigned int addr_index)
+dwarf2_read_addr_index (dwarf2_per_cu_data *per_cu, unsigned int addr_index)
{
struct dwarf2_per_objfile *dwarf2_per_objfile = per_cu->dwarf2_per_objfile;
struct dwarf2_cu *cu = per_cu->cu;
}
else
{
- cutu_reader reader (per_cu, NULL, 0, 0, false);
+ cutu_reader reader (per_cu, NULL, 0, false);
addr_base = reader.cu->addr_base;
addr_size = reader.cu->header.addr_size;
}
return NULL;
}
-/* Return the named attribute or NULL if not there,
- but do not follow DW_AT_specification, etc.
- This is for use in contexts where we're reading .debug_types dies.
- Following DW_AT_specification, DW_AT_abstract_origin will take us
- back up the chain, and we want to go down. */
-
-static struct attribute *
-dwarf2_attr_no_follow (struct die_info *die, unsigned int name)
-{
- unsigned int i;
-
- for (i = 0; i < die->num_attrs; ++i)
- if (die->attrs[i].name == name)
- return &die->attrs[i];
-
- return NULL;
-}
-
/* Return the string associated with a string-typed attribute, or NULL if it
is either not found or is of an incorrect type. */
return section;
}
-/* Read directory or file name entry format, starting with byte of
- format count entries, ULEB128 pairs of entry formats, ULEB128 of
- entries count and the entries themselves in the described entry
- format. */
-
-static void
-read_formatted_entries (struct dwarf2_per_objfile *dwarf2_per_objfile,
- bfd *abfd, const gdb_byte **bufp,
- struct line_header *lh,
- const struct comp_unit_head *cu_header,
- void (*callback) (struct line_header *lh,
- const char *name,
- dir_index d_index,
- unsigned int mod_time,
- unsigned int length))
-{
- gdb_byte format_count, formati;
- ULONGEST data_count, datai;
- const gdb_byte *buf = *bufp;
- const gdb_byte *format_header_data;
- unsigned int bytes_read;
-
- format_count = read_1_byte (abfd, buf);
- buf += 1;
- format_header_data = buf;
- for (formati = 0; formati < format_count; formati++)
- {
- read_unsigned_leb128 (abfd, buf, &bytes_read);
- buf += bytes_read;
- read_unsigned_leb128 (abfd, buf, &bytes_read);
- buf += bytes_read;
- }
-
- data_count = read_unsigned_leb128 (abfd, buf, &bytes_read);
- buf += bytes_read;
- for (datai = 0; datai < data_count; datai++)
- {
- const gdb_byte *format = format_header_data;
- struct file_entry fe;
-
- for (formati = 0; formati < format_count; formati++)
- {
- ULONGEST content_type = read_unsigned_leb128 (abfd, format, &bytes_read);
- format += bytes_read;
-
- ULONGEST form = read_unsigned_leb128 (abfd, format, &bytes_read);
- format += bytes_read;
-
- gdb::optional<const char *> string;
- gdb::optional<unsigned int> uint;
-
- switch (form)
- {
- case DW_FORM_string:
- string.emplace (read_direct_string (abfd, buf, &bytes_read));
- buf += bytes_read;
- break;
-
- case DW_FORM_line_strp:
- string.emplace (read_indirect_line_string (dwarf2_per_objfile,
- abfd, buf,
- cu_header,
- &bytes_read));
- buf += bytes_read;
- break;
-
- case DW_FORM_data1:
- uint.emplace (read_1_byte (abfd, buf));
- buf += 1;
- break;
-
- case DW_FORM_data2:
- uint.emplace (read_2_bytes (abfd, buf));
- buf += 2;
- break;
-
- case DW_FORM_data4:
- uint.emplace (read_4_bytes (abfd, buf));
- buf += 4;
- break;
-
- case DW_FORM_data8:
- uint.emplace (read_8_bytes (abfd, buf));
- buf += 8;
- break;
-
- case DW_FORM_data16:
- /* This is used for MD5, but file_entry does not record MD5s. */
- buf += 16;
- break;
-
- case DW_FORM_udata:
- uint.emplace (read_unsigned_leb128 (abfd, buf, &bytes_read));
- buf += bytes_read;
- break;
-
- case DW_FORM_block:
- /* It is valid only for DW_LNCT_timestamp which is ignored by
- current GDB. */
- break;
- }
-
- switch (content_type)
- {
- case DW_LNCT_path:
- if (string.has_value ())
- fe.name = *string;
- break;
- case DW_LNCT_directory_index:
- if (uint.has_value ())
- fe.d_index = (dir_index) *uint;
- break;
- case DW_LNCT_timestamp:
- if (uint.has_value ())
- fe.mod_time = *uint;
- break;
- case DW_LNCT_size:
- if (uint.has_value ())
- fe.length = *uint;
- break;
- case DW_LNCT_MD5:
- break;
- default:
- complaint (_("Unknown format content type %s"),
- pulongest (content_type));
- }
- }
-
- callback (lh, fe.name, fe.d_index, fe.mod_time, fe.length);
- }
-
- *bufp = buf;
-}
-
/* Read the statement program header starting at OFFSET in
.debug_line, or .debug_line.dwo. Return a pointer
to a struct line_header, allocated using xmalloc.
static line_header_up
dwarf_decode_line_header (sect_offset sect_off, struct dwarf2_cu *cu)
{
- const gdb_byte *line_ptr;
- unsigned int bytes_read, offset_size;
- int i;
- const char *cur_dir, *cur_file;
struct dwarf2_section_info *section;
- bfd *abfd;
struct dwarf2_per_objfile *dwarf2_per_objfile
= cu->per_cu->dwarf2_per_objfile;
return 0;
}
- /* We can't do this until we know the section is non-empty.
- Only then do we know we have such a section. */
- abfd = section->get_bfd_owner ();
-
- /* Make sure that at least there's room for the total_length field.
- That could be 12 bytes long, but we're just going to fudge that. */
- if (to_underlying (sect_off) + 4 >= section->size)
- {
- dwarf2_statement_list_fits_in_line_number_section_complaint ();
- return 0;
- }
-
- line_header_up lh (new line_header ());
-
- lh->sect_off = sect_off;
- lh->offset_in_dwz = cu->per_cu->is_dwz;
-
- line_ptr = section->buffer + to_underlying (sect_off);
-
- /* Read in the header. */
- lh->total_length =
- read_checked_initial_length_and_offset (abfd, line_ptr, &cu->header,
- &bytes_read, &offset_size);
- line_ptr += bytes_read;
-
- const gdb_byte *start_here = line_ptr;
-
- if (line_ptr + lh->total_length > (section->buffer + section->size))
- {
- dwarf2_statement_list_fits_in_line_number_section_complaint ();
- return 0;
- }
- lh->statement_program_end = start_here + lh->total_length;
- lh->version = read_2_bytes (abfd, line_ptr);
- line_ptr += 2;
- if (lh->version > 5)
- {
- /* This is a version we don't understand. The format could have
- changed in ways we don't handle properly so just punt. */
- complaint (_("unsupported version in .debug_line section"));
- return NULL;
- }
- if (lh->version >= 5)
- {
- gdb_byte segment_selector_size;
-
- /* Skip address size. */
- read_1_byte (abfd, line_ptr);
- line_ptr += 1;
-
- segment_selector_size = read_1_byte (abfd, line_ptr);
- line_ptr += 1;
- if (segment_selector_size != 0)
- {
- complaint (_("unsupported segment selector size %u "
- "in .debug_line section"),
- segment_selector_size);
- return NULL;
- }
- }
- lh->header_length = read_offset_1 (abfd, line_ptr, offset_size);
- line_ptr += offset_size;
- lh->statement_program_start = line_ptr + lh->header_length;
- lh->minimum_instruction_length = read_1_byte (abfd, line_ptr);
- line_ptr += 1;
- if (lh->version >= 4)
- {
- lh->maximum_ops_per_instruction = read_1_byte (abfd, line_ptr);
- line_ptr += 1;
- }
- else
- lh->maximum_ops_per_instruction = 1;
-
- if (lh->maximum_ops_per_instruction == 0)
- {
- lh->maximum_ops_per_instruction = 1;
- complaint (_("invalid maximum_ops_per_instruction "
- "in `.debug_line' section"));
- }
-
- lh->default_is_stmt = read_1_byte (abfd, line_ptr);
- line_ptr += 1;
- lh->line_base = read_1_signed_byte (abfd, line_ptr);
- line_ptr += 1;
- lh->line_range = read_1_byte (abfd, line_ptr);
- line_ptr += 1;
- lh->opcode_base = read_1_byte (abfd, line_ptr);
- line_ptr += 1;
- lh->standard_opcode_lengths.reset (new unsigned char[lh->opcode_base]);
-
- lh->standard_opcode_lengths[0] = 1; /* This should never be used anyway. */
- for (i = 1; i < lh->opcode_base; ++i)
- {
- lh->standard_opcode_lengths[i] = read_1_byte (abfd, line_ptr);
- line_ptr += 1;
- }
-
- if (lh->version >= 5)
- {
- /* Read directory table. */
- read_formatted_entries (dwarf2_per_objfile, abfd, &line_ptr, lh.get (),
- &cu->header,
- [] (struct line_header *header, const char *name,
- dir_index d_index, unsigned int mod_time,
- unsigned int length)
- {
- header->add_include_dir (name);
- });
-
- /* Read file name table. */
- read_formatted_entries (dwarf2_per_objfile, abfd, &line_ptr, lh.get (),
- &cu->header,
- [] (struct line_header *header, const char *name,
- dir_index d_index, unsigned int mod_time,
- unsigned int length)
- {
- header->add_file_name (name, d_index, mod_time, length);
- });
- }
- else
- {
- /* Read directory table. */
- while ((cur_dir = read_direct_string (abfd, line_ptr, &bytes_read)) != NULL)
- {
- line_ptr += bytes_read;
- lh->add_include_dir (cur_dir);
- }
- line_ptr += bytes_read;
-
- /* Read file name table. */
- while ((cur_file = read_direct_string (abfd, line_ptr, &bytes_read)) != NULL)
- {
- unsigned int mod_time, length;
- dir_index d_index;
-
- line_ptr += bytes_read;
- d_index = (dir_index) read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
- line_ptr += bytes_read;
- mod_time = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
- line_ptr += bytes_read;
- length = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
- line_ptr += bytes_read;
-
- lh->add_file_name (cur_file, d_index, mod_time, length);
- }
- line_ptr += bytes_read;
- }
-
- if (line_ptr > (section->buffer + section->size))
- complaint (_("line number info header doesn't "
- "fit in `.debug_line' section"));
-
- return lh;
+ return dwarf_decode_line_header (sect_off, cu->per_cu->is_dwz,
+ dwarf2_per_objfile, section,
+ &cu->header);
}
/* Subroutine of dwarf_decode_lines to simplify it.
lnp_state_machine::handle_special_opcode (unsigned char op_code)
{
unsigned char adj_opcode = op_code - m_line_header->opcode_base;
- CORE_ADDR addr_adj = (((m_op_index
- + (adj_opcode / m_line_header->line_range))
+ unsigned char adj_opcode_d = adj_opcode / m_line_header->line_range;
+ unsigned char adj_opcode_r = adj_opcode % m_line_header->line_range;
+ CORE_ADDR addr_adj = (((m_op_index + adj_opcode_d)
/ m_line_header->maximum_ops_per_instruction)
* m_line_header->minimum_instruction_length);
m_address += gdbarch_adjust_dwarf2_line (m_gdbarch, addr_adj, true);
- m_op_index = ((m_op_index + (adj_opcode / m_line_header->line_range))
+ m_op_index = ((m_op_index + adj_opcode_d)
% m_line_header->maximum_ops_per_instruction);
- int line_delta = (m_line_header->line_base
- + (adj_opcode % m_line_header->line_range));
+ int line_delta = m_line_header->line_base + adj_opcode_r;
advance_line (line_delta);
record_line (false);
m_discriminator = 0;
static void
dwarf_record_line_1 (struct gdbarch *gdbarch, struct subfile *subfile,
- unsigned int line, CORE_ADDR address,
+ unsigned int line, CORE_ADDR address, bool is_stmt,
struct dwarf2_cu *cu)
{
CORE_ADDR addr = gdbarch_addr_bits_remove (gdbarch, address);
}
if (cu != nullptr)
- cu->get_builder ()->record_line (subfile, line, addr);
+ cu->get_builder ()->record_line (subfile, line, addr, is_stmt);
}
/* Subroutine of dwarf_decode_lines_1 to simplify it.
paddress (gdbarch, address));
}
- dwarf_record_line_1 (gdbarch, subfile, 0, address, cu);
+ dwarf_record_line_1 (gdbarch, subfile, 0, address, true, cu);
}
void
else if (m_op_index == 0 || end_sequence)
{
fe->included_p = 1;
- if (m_record_lines_p
- && (producer_is_codewarrior (m_cu) || m_is_stmt || end_sequence))
+ if (m_record_lines_p)
{
if (m_last_subfile != m_cu->get_builder ()->get_current_subfile ()
|| end_sequence)
if (!end_sequence)
{
+ bool is_stmt = producer_is_codewarrior (m_cu) || m_is_stmt;
+
if (dwarf_record_line_p (m_cu, m_line, m_last_line,
m_line_has_non_zero_discriminator,
m_last_subfile))
buildsym_compunit *builder = m_cu->get_builder ();
dwarf_record_line_1 (m_gdbarch,
builder->get_current_subfile (),
- m_line, m_address,
+ m_line, m_address, is_stmt,
m_currently_recording_lines ? m_cu : nullptr);
}
m_last_subfile = m_cu->get_builder ()->get_current_subfile ();
case DW_LNE_set_address:
{
CORE_ADDR address
- = read_address (abfd, line_ptr, cu, &bytes_read);
+ = cu->header.read_address (abfd, line_ptr, &bytes_read);
line_ptr += bytes_read;
state_machine.check_line_address (cu, line_ptr,
unsigned int dummy;
if (DW_BLOCK (attr)->data[0] == DW_OP_addr)
- SET_SYMBOL_VALUE_ADDRESS (sym,
- read_address (objfile->obfd,
- DW_BLOCK (attr)->data + 1,
- cu, &dummy));
+ SET_SYMBOL_VALUE_ADDRESS
+ (sym, cu->header.read_address (objfile->obfd,
+ DW_BLOCK (attr)->data + 1,
+ &dummy));
else
SET_SYMBOL_VALUE_ADDRESS
(sym, read_addr_index_from_leb128 (cu, DW_BLOCK (attr)->data + 1,
}
}
-/* Return sibling of die, NULL if no sibling. */
-
-static struct die_info *
-sibling_die (struct die_info *die)
-{
- return die->sibling;
-}
-
/* Get name of a die, return NULL if not found. */
static const char *
dwarf2_canonicalize_name (const char *name, struct dwarf2_cu *cu,
- struct obstack *obstack)
+ struct objfile *objfile)
{
if (name && cu->language == language_cplus)
{
if (!canon_name.empty ())
{
if (canon_name != name)
- name = obstack_strdup (obstack, canon_name);
+ name = objfile->intern (canon_name);
}
}
{
gdb::unique_xmalloc_ptr<char> demangled
(gdb_demangle (DW_STRING (attr), DMGL_TYPES));
+ if (demangled == nullptr)
+ return nullptr;
- const char *base;
-
- /* FIXME: we already did this for the partial symbol... */
- DW_STRING (attr)
- = obstack_strdup (&objfile->per_bfd->storage_obstack,
- demangled.get ());
+ DW_STRING (attr) = objfile->intern (demangled.get ());
DW_STRING_IS_CANONICAL (attr) = 1;
-
- /* Strip any leading namespaces/classes, keep only the base name.
- DW_AT_name for named DIEs does not contain the prefixes. */
- base = strrchr (DW_STRING (attr), ':');
- if (base && base > DW_STRING (attr) && base[-1] == ':')
- return &base[1];
- else
- return DW_STRING (attr);
}
+
+ /* Strip any leading namespaces/classes, keep only the base name.
+ DW_AT_name for named DIEs does not contain the prefixes. */
+ const char *base = strrchr (DW_STRING (attr), ':');
+ if (base && base > DW_STRING (attr) && base[-1] == ':')
+ return &base[1];
+ else
+ return DW_STRING (attr);
}
break;
if (!DW_STRING_IS_CANONICAL (attr))
{
- DW_STRING (attr)
- = dwarf2_canonicalize_name (DW_STRING (attr), cu,
- &objfile->per_bfd->storage_obstack);
+ DW_STRING (attr) = dwarf2_canonicalize_name (DW_STRING (attr), cu,
+ objfile);
DW_STRING_IS_CANONICAL (attr) = 1;
}
return DW_STRING (attr);
return name;
}
-/* Convert a unit type to corresponding DW_UT name. */
-
-static const char *
-dwarf_unit_type_name (int unit_type) {
- switch (unit_type)
- {
- case 0x01:
- return "DW_UT_compile (0x01)";
- case 0x02:
- return "DW_UT_type (0x02)";
- case 0x03:
- return "DW_UT_partial (0x03)";
- case 0x04:
- return "DW_UT_skeleton (0x04)";
- case 0x05:
- return "DW_UT_split_compile (0x05)";
- case 0x06:
- return "DW_UT_split_type (0x06)";
- case 0x80:
- return "DW_UT_lo_user (0x80)";
- case 0xff:
- return "DW_UT_hi_user (0xff)";
- default:
- return nullptr;
- }
-}
-
/* Convert a DWARF value form code into its string name. */
static const char *
/* .debug_types CUs cannot reference anything outside their CU.
If they need to, they have to reference a signatured type via
DW_FORM_ref_sig8. */
- if (!offset_in_cu_p (&cu->header, sect_off))
+ if (!cu->header.offset_in_cu_p (sect_off))
return NULL;
}
else if (offset_in_dwz != cu->per_cu->is_dwz
- || !offset_in_cu_p (&cu->header, sect_off))
+ || !cu->header.offset_in_cu_p (sect_off))
{
struct dwarf2_per_cu_data *per_cu;
return die;
}
-/* Return DWARF block referenced by DW_AT_location of DIE at SECT_OFF at PER_CU.
- Returned value is intended for DW_OP_call*. Returned
- dwarf2_locexpr_baton->data has lifetime of
- PER_CU->DWARF2_PER_OBJFILE->OBJFILE. */
+/* See read.h. */
struct dwarf2_locexpr_baton
dwarf2_fetch_die_loc_sect_off (sect_offset sect_off,
- struct dwarf2_per_cu_data *per_cu,
+ dwarf2_per_cu_data *per_cu,
CORE_ADDR (*get_frame_pc) (void *baton),
void *baton, bool resolve_abstract_p)
{
return retval;
}
-/* Like dwarf2_fetch_die_loc_sect_off, but take a CU
- offset. */
+/* See read.h. */
struct dwarf2_locexpr_baton
dwarf2_fetch_die_loc_cu_off (cu_offset offset_in_cu,
- struct dwarf2_per_cu_data *per_cu,
+ dwarf2_per_cu_data *per_cu,
CORE_ADDR (*get_frame_pc) (void *baton),
void *baton)
{
return result;
}
-/* If the DIE at OFFSET in PER_CU has a DW_AT_const_value, return a
- pointer to the constant bytes and set LEN to the length of the
- data. If memory is needed, allocate it on OBSTACK. If the DIE
- does not have a DW_AT_const_value, return NULL. */
+/* See read.h. */
const gdb_byte *
dwarf2_fetch_constant_bytes (sect_offset sect_off,
- struct dwarf2_per_cu_data *per_cu,
- struct obstack *obstack,
+ dwarf2_per_cu_data *per_cu,
+ obstack *obstack,
LONGEST *len)
{
struct dwarf2_cu *cu;
return result;
}
-/* Return the type of the die at OFFSET in PER_CU. Return NULL if no
- valid type for this die is found. */
+/* See read.h. */
struct type *
dwarf2_fetch_die_type_sect_off (sect_offset sect_off,
- struct dwarf2_per_cu_data *per_cu)
+ dwarf2_per_cu_data *per_cu)
{
struct dwarf2_cu *cu;
struct die_info *die;
return die_type (die, cu);
}
-/* Return the type of the DIE at DIE_OFFSET in the CU named by
- PER_CU. */
+/* See read.h. */
struct type *
dwarf2_get_die_type (cu_offset die_offset,
struct signatured_type *sig_type;
/* Caller is responsible for ensuring type_unit_groups don't get here. */
- gdb_assert (! IS_TYPE_UNIT_GROUP (per_cu));
+ gdb_assert (! per_cu->type_unit_group_p ());
/* We have the per_cu, but we need the signatured_type.
Fortunately this is an easy translation. */
gdb_assert (per_cu->is_debug_types);
gdb_assert (per_cu->cu == NULL);
- cutu_reader reader (per_cu, NULL, 0, 1, false);
+ cutu_reader reader (per_cu, NULL, 0, false);
if (!reader.dummy_p)
{
correctly. Similarly, if we do not read the producer, we can
not apply producer-specific interpretation. */
prepare_one_comp_unit (cu, cu->dies, language_minimal);
+
+ reader.keep ();
}
sig_type->per_cu.tu_read = 1;
break;
case DW_OP_addr:
- stack[++stacki] = read_address (objfile->obfd, &data[i],
- cu, &bytes_read);
+ stack[++stacki] = cu->header.read_address (objfile->obfd, &data[i],
+ &bytes_read);
i += bytes_read;
break;
}
\f
+
/* Macro support. */
-static struct macro_source_file *
-macro_start_file (struct dwarf2_cu *cu,
- int file, int line,
- struct macro_source_file *current_file,
- struct line_header *lh)
+/* An overload of dwarf_decode_macros that finds the correct section
+ and ensures it is read in before calling the other overload. */
+
+static void
+dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset,
+ int section_is_gnu)
{
- /* File name relative to the compilation directory of this source file. */
- gdb::unique_xmalloc_ptr<char> file_name = lh->file_file_name (file);
+ struct dwarf2_per_objfile *dwarf2_per_objfile
+ = cu->per_cu->dwarf2_per_objfile;
+ struct objfile *objfile = dwarf2_per_objfile->objfile;
+ const struct line_header *lh = cu->line_header;
+ unsigned int offset_size = cu->header.offset_size;
+ struct dwarf2_section_info *section;
+ const char *section_name;
- if (! current_file)
- {
- /* Note: We don't create a macro table for this compilation unit
- at all until we actually get a filename. */
- struct macro_table *macro_table = cu->get_builder ()->get_macro_table ();
-
- /* If we have no current file, then this must be the start_file
- directive for the compilation unit's main source file. */
- current_file = macro_set_main (macro_table, file_name.get ());
- macro_define_special (macro_table);
- }
- else
- current_file = macro_include (current_file, line, file_name.get ());
-
- return current_file;
-}
-
-static const char *
-consume_improper_spaces (const char *p, const char *body)
-{
- if (*p == ' ')
- {
- complaint (_("macro definition contains spaces "
- "in formal argument list:\n`%s'"),
- body);
-
- while (*p == ' ')
- p++;
- }
-
- return p;
-}
-
-
-static void
-parse_macro_definition (struct macro_source_file *file, int line,
- const char *body)
-{
- const char *p;
-
- /* The body string takes one of two forms. For object-like macro
- definitions, it should be:
-
- <macro name> " " <definition>
-
- For function-like macro definitions, it should be:
-
- <macro name> "() " <definition>
- or
- <macro name> "(" <arg name> ( "," <arg name> ) * ") " <definition>
-
- Spaces may appear only where explicitly indicated, and in the
- <definition>.
-
- The Dwarf 2 spec says that an object-like macro's name is always
- followed by a space, but versions of GCC around March 2002 omit
- the space when the macro's definition is the empty string.
-
- The Dwarf 2 spec says that there should be no spaces between the
- formal arguments in a function-like macro's formal argument list,
- but versions of GCC around March 2002 include spaces after the
- commas. */
-
-
- /* Find the extent of the macro name. The macro name is terminated
- by either a space or null character (for an object-like macro) or
- an opening paren (for a function-like macro). */
- for (p = body; *p; p++)
- if (*p == ' ' || *p == '(')
- break;
-
- if (*p == ' ' || *p == '\0')
- {
- /* It's an object-like macro. */
- int name_len = p - body;
- std::string name (body, name_len);
- const char *replacement;
-
- if (*p == ' ')
- replacement = body + name_len + 1;
- else
- {
- dwarf2_macro_malformed_definition_complaint (body);
- replacement = body + name_len;
- }
-
- macro_define_object (file, line, name.c_str (), replacement);
- }
- else if (*p == '(')
- {
- /* It's a function-like macro. */
- std::string name (body, p - body);
- int argc = 0;
- int argv_size = 1;
- char **argv = XNEWVEC (char *, argv_size);
-
- p++;
-
- p = consume_improper_spaces (p, body);
-
- /* Parse the formal argument list. */
- while (*p && *p != ')')
- {
- /* Find the extent of the current argument name. */
- const char *arg_start = p;
-
- while (*p && *p != ',' && *p != ')' && *p != ' ')
- p++;
-
- if (! *p || p == arg_start)
- dwarf2_macro_malformed_definition_complaint (body);
- else
- {
- /* Make sure argv has room for the new argument. */
- if (argc >= argv_size)
- {
- argv_size *= 2;
- argv = XRESIZEVEC (char *, argv, argv_size);
- }
-
- argv[argc++] = savestring (arg_start, p - arg_start);
- }
-
- p = consume_improper_spaces (p, body);
-
- /* Consume the comma, if present. */
- if (*p == ',')
- {
- p++;
-
- p = consume_improper_spaces (p, body);
- }
- }
-
- if (*p == ')')
- {
- p++;
-
- if (*p == ' ')
- /* Perfectly formed definition, no complaints. */
- macro_define_function (file, line, name.c_str (),
- argc, (const char **) argv,
- p + 1);
- else if (*p == '\0')
- {
- /* Complain, but do define it. */
- dwarf2_macro_malformed_definition_complaint (body);
- macro_define_function (file, line, name.c_str (),
- argc, (const char **) argv,
- p);
- }
- else
- /* Just complain. */
- dwarf2_macro_malformed_definition_complaint (body);
- }
- else
- /* Just complain. */
- dwarf2_macro_malformed_definition_complaint (body);
-
- {
- int i;
-
- for (i = 0; i < argc; i++)
- xfree (argv[i]);
- }
- xfree (argv);
- }
- else
- dwarf2_macro_malformed_definition_complaint (body);
-}
-
-/* Skip some bytes from BYTES according to the form given in FORM.
- Returns the new pointer. */
-
-static const gdb_byte *
-skip_form_bytes (bfd *abfd, const gdb_byte *bytes, const gdb_byte *buffer_end,
- enum dwarf_form form,
- unsigned int offset_size,
- struct dwarf2_section_info *section)
-{
- unsigned int bytes_read;
-
- switch (form)
- {
- case DW_FORM_data1:
- case DW_FORM_flag:
- ++bytes;
- break;
-
- case DW_FORM_data2:
- bytes += 2;
- break;
-
- case DW_FORM_data4:
- bytes += 4;
- break;
-
- case DW_FORM_data8:
- bytes += 8;
- break;
-
- case DW_FORM_data16:
- bytes += 16;
- break;
-
- case DW_FORM_string:
- read_direct_string (abfd, bytes, &bytes_read);
- bytes += bytes_read;
- break;
-
- case DW_FORM_sec_offset:
- case DW_FORM_strp:
- case DW_FORM_GNU_strp_alt:
- bytes += offset_size;
- break;
-
- case DW_FORM_block:
- bytes += read_unsigned_leb128 (abfd, bytes, &bytes_read);
- bytes += bytes_read;
- break;
-
- case DW_FORM_block1:
- bytes += 1 + read_1_byte (abfd, bytes);
- break;
- case DW_FORM_block2:
- bytes += 2 + read_2_bytes (abfd, bytes);
- break;
- case DW_FORM_block4:
- bytes += 4 + read_4_bytes (abfd, bytes);
- break;
-
- case DW_FORM_addrx:
- case DW_FORM_sdata:
- case DW_FORM_strx:
- case DW_FORM_udata:
- case DW_FORM_GNU_addr_index:
- case DW_FORM_GNU_str_index:
- bytes = gdb_skip_leb128 (bytes, buffer_end);
- if (bytes == NULL)
- {
- dwarf2_section_buffer_overflow_complaint (section);
- return NULL;
- }
- break;
-
- case DW_FORM_implicit_const:
- break;
-
- default:
- {
- complaint (_("invalid form 0x%x in `%s'"),
- form, section->get_name ());
- return NULL;
- }
- }
-
- return bytes;
-}
-
-/* A helper for dwarf_decode_macros that handles skipping an unknown
- opcode. Returns an updated pointer to the macro data buffer; or,
- on error, issues a complaint and returns NULL. */
-
-static const gdb_byte *
-skip_unknown_opcode (unsigned int opcode,
- const gdb_byte **opcode_definitions,
- const gdb_byte *mac_ptr, const gdb_byte *mac_end,
- bfd *abfd,
- unsigned int offset_size,
- struct dwarf2_section_info *section)
-{
- unsigned int bytes_read, i;
- unsigned long arg;
- const gdb_byte *defn;
-
- if (opcode_definitions[opcode] == NULL)
- {
- complaint (_("unrecognized DW_MACFINO opcode 0x%x"),
- opcode);
- return NULL;
- }
-
- defn = opcode_definitions[opcode];
- arg = read_unsigned_leb128 (abfd, defn, &bytes_read);
- defn += bytes_read;
-
- for (i = 0; i < arg; ++i)
- {
- mac_ptr = skip_form_bytes (abfd, mac_ptr, mac_end,
- (enum dwarf_form) defn[i], offset_size,
- section);
- if (mac_ptr == NULL)
- {
- /* skip_form_bytes already issued the complaint. */
- return NULL;
- }
- }
-
- return mac_ptr;
-}
-
-/* A helper function which parses the header of a macro section.
- If the macro section is the extended (for now called "GNU") type,
- then this updates *OFFSET_SIZE. Returns a pointer to just after
- the header, or issues a complaint and returns NULL on error. */
-
-static const gdb_byte *
-dwarf_parse_macro_header (const gdb_byte **opcode_definitions,
- bfd *abfd,
- const gdb_byte *mac_ptr,
- unsigned int *offset_size,
- int section_is_gnu)
-{
- memset (opcode_definitions, 0, 256 * sizeof (gdb_byte *));
-
- if (section_is_gnu)
- {
- unsigned int version, flags;
-
- version = read_2_bytes (abfd, mac_ptr);
- if (version != 4 && version != 5)
- {
- complaint (_("unrecognized version `%d' in .debug_macro section"),
- version);
- return NULL;
- }
- mac_ptr += 2;
-
- flags = read_1_byte (abfd, mac_ptr);
- ++mac_ptr;
- *offset_size = (flags & 1) ? 8 : 4;
-
- if ((flags & 2) != 0)
- /* We don't need the line table offset. */
- mac_ptr += *offset_size;
-
- /* Vendor opcode descriptions. */
- if ((flags & 4) != 0)
- {
- unsigned int i, count;
-
- count = read_1_byte (abfd, mac_ptr);
- ++mac_ptr;
- for (i = 0; i < count; ++i)
- {
- unsigned int opcode, bytes_read;
- unsigned long arg;
-
- opcode = read_1_byte (abfd, mac_ptr);
- ++mac_ptr;
- opcode_definitions[opcode] = mac_ptr;
- arg = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
- mac_ptr += bytes_read;
- mac_ptr += arg;
- }
- }
- }
-
- return mac_ptr;
-}
-
-/* A helper for dwarf_decode_macros that handles the GNU extensions,
- including DW_MACRO_import. */
-
-static void
-dwarf_decode_macro_bytes (struct dwarf2_cu *cu,
- bfd *abfd,
- const gdb_byte *mac_ptr, const gdb_byte *mac_end,
- struct macro_source_file *current_file,
- struct line_header *lh,
- struct dwarf2_section_info *section,
- int section_is_gnu, int section_is_dwz,
- unsigned int offset_size,
- htab_t include_hash)
-{
- struct dwarf2_per_objfile *dwarf2_per_objfile
- = cu->per_cu->dwarf2_per_objfile;
- struct objfile *objfile = dwarf2_per_objfile->objfile;
- enum dwarf_macro_record_type macinfo_type;
- int at_commandline;
- const gdb_byte *opcode_definitions[256];
-
- mac_ptr = dwarf_parse_macro_header (opcode_definitions, abfd, mac_ptr,
- &offset_size, section_is_gnu);
- if (mac_ptr == NULL)
- {
- /* We already issued a complaint. */
- return;
- }
-
- /* Determines if GDB is still before first DW_MACINFO_start_file. If true
- GDB is still reading the definitions from command line. First
- DW_MACINFO_start_file will need to be ignored as it was already executed
- to create CURRENT_FILE for the main source holding also the command line
- definitions. On first met DW_MACINFO_start_file this flag is reset to
- normally execute all the remaining DW_MACINFO_start_file macinfos. */
-
- at_commandline = 1;
-
- do
- {
- /* Do we at least have room for a macinfo type byte? */
- if (mac_ptr >= mac_end)
- {
- dwarf2_section_buffer_overflow_complaint (section);
- break;
- }
-
- macinfo_type = (enum dwarf_macro_record_type) read_1_byte (abfd, mac_ptr);
- mac_ptr++;
-
- /* Note that we rely on the fact that the corresponding GNU and
- DWARF constants are the same. */
- DIAGNOSTIC_PUSH
- DIAGNOSTIC_IGNORE_SWITCH_DIFFERENT_ENUM_TYPES
- switch (macinfo_type)
- {
- /* A zero macinfo type indicates the end of the macro
- information. */
- case 0:
- break;
-
- case DW_MACRO_define:
- case DW_MACRO_undef:
- case DW_MACRO_define_strp:
- case DW_MACRO_undef_strp:
- case DW_MACRO_define_sup:
- case DW_MACRO_undef_sup:
- {
- unsigned int bytes_read;
- int line;
- const char *body;
- int is_define;
-
- line = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
- mac_ptr += bytes_read;
-
- if (macinfo_type == DW_MACRO_define
- || macinfo_type == DW_MACRO_undef)
- {
- body = read_direct_string (abfd, mac_ptr, &bytes_read);
- mac_ptr += bytes_read;
- }
- else
- {
- LONGEST str_offset;
-
- str_offset = read_offset_1 (abfd, mac_ptr, offset_size);
- mac_ptr += offset_size;
-
- if (macinfo_type == DW_MACRO_define_sup
- || macinfo_type == DW_MACRO_undef_sup
- || section_is_dwz)
- {
- struct dwz_file *dwz
- = dwarf2_get_dwz_file (dwarf2_per_objfile);
-
- body = read_indirect_string_from_dwz (objfile,
- dwz, str_offset);
- }
- else
- body = read_indirect_string_at_offset (dwarf2_per_objfile,
- abfd, str_offset);
- }
-
- is_define = (macinfo_type == DW_MACRO_define
- || macinfo_type == DW_MACRO_define_strp
- || macinfo_type == DW_MACRO_define_sup);
- if (! current_file)
- {
- /* DWARF violation as no main source is present. */
- complaint (_("debug info with no main source gives macro %s "
- "on line %d: %s"),
- is_define ? _("definition") : _("undefinition"),
- line, body);
- break;
- }
- if ((line == 0 && !at_commandline)
- || (line != 0 && at_commandline))
- complaint (_("debug info gives %s macro %s with %s line %d: %s"),
- at_commandline ? _("command-line") : _("in-file"),
- is_define ? _("definition") : _("undefinition"),
- line == 0 ? _("zero") : _("non-zero"), line, body);
-
- if (body == NULL)
- {
- /* Fedora's rpm-build's "debugedit" binary
- corrupted .debug_macro sections.
-
- For more info, see
- https://bugzilla.redhat.com/show_bug.cgi?id=1708786 */
- complaint (_("debug info gives %s invalid macro %s "
- "without body (corrupted?) at line %d "
- "on file %s"),
- at_commandline ? _("command-line") : _("in-file"),
- is_define ? _("definition") : _("undefinition"),
- line, current_file->filename);
- }
- else if (is_define)
- parse_macro_definition (current_file, line, body);
- else
- {
- gdb_assert (macinfo_type == DW_MACRO_undef
- || macinfo_type == DW_MACRO_undef_strp
- || macinfo_type == DW_MACRO_undef_sup);
- macro_undef (current_file, line, body);
- }
- }
- break;
-
- case DW_MACRO_start_file:
- {
- unsigned int bytes_read;
- int line, file;
-
- line = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
- mac_ptr += bytes_read;
- file = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
- mac_ptr += bytes_read;
-
- if ((line == 0 && !at_commandline)
- || (line != 0 && at_commandline))
- complaint (_("debug info gives source %d included "
- "from %s at %s line %d"),
- file, at_commandline ? _("command-line") : _("file"),
- line == 0 ? _("zero") : _("non-zero"), line);
-
- if (at_commandline)
- {
- /* This DW_MACRO_start_file was executed in the
- pass one. */
- at_commandline = 0;
- }
- else
- current_file = macro_start_file (cu, file, line, current_file,
- lh);
- }
- break;
-
- case DW_MACRO_end_file:
- if (! current_file)
- complaint (_("macro debug info has an unmatched "
- "`close_file' directive"));
- else
- {
- current_file = current_file->included_by;
- if (! current_file)
- {
- enum dwarf_macro_record_type next_type;
-
- /* GCC circa March 2002 doesn't produce the zero
- type byte marking the end of the compilation
- unit. Complain if it's not there, but exit no
- matter what. */
-
- /* Do we at least have room for a macinfo type byte? */
- if (mac_ptr >= mac_end)
- {
- dwarf2_section_buffer_overflow_complaint (section);
- return;
- }
-
- /* We don't increment mac_ptr here, so this is just
- a look-ahead. */
- next_type
- = (enum dwarf_macro_record_type) read_1_byte (abfd,
- mac_ptr);
- if (next_type != 0)
- complaint (_("no terminating 0-type entry for "
- "macros in `.debug_macinfo' section"));
-
- return;
- }
- }
- break;
-
- case DW_MACRO_import:
- case DW_MACRO_import_sup:
- {
- LONGEST offset;
- void **slot;
- bfd *include_bfd = abfd;
- struct dwarf2_section_info *include_section = section;
- const gdb_byte *include_mac_end = mac_end;
- int is_dwz = section_is_dwz;
- const gdb_byte *new_mac_ptr;
-
- offset = read_offset_1 (abfd, mac_ptr, offset_size);
- mac_ptr += offset_size;
-
- if (macinfo_type == DW_MACRO_import_sup)
- {
- struct dwz_file *dwz = dwarf2_get_dwz_file (dwarf2_per_objfile);
-
- dwz->macro.read (objfile);
-
- include_section = &dwz->macro;
- include_bfd = include_section->get_bfd_owner ();
- include_mac_end = dwz->macro.buffer + dwz->macro.size;
- is_dwz = 1;
- }
-
- new_mac_ptr = include_section->buffer + offset;
- slot = htab_find_slot (include_hash, new_mac_ptr, INSERT);
-
- if (*slot != NULL)
- {
- /* This has actually happened; see
- http://sourceware.org/bugzilla/show_bug.cgi?id=13568. */
- complaint (_("recursive DW_MACRO_import in "
- ".debug_macro section"));
- }
- else
- {
- *slot = (void *) new_mac_ptr;
-
- dwarf_decode_macro_bytes (cu, include_bfd, new_mac_ptr,
- include_mac_end, current_file, lh,
- section, section_is_gnu, is_dwz,
- offset_size, include_hash);
-
- htab_remove_elt (include_hash, (void *) new_mac_ptr);
- }
- }
- break;
-
- case DW_MACINFO_vendor_ext:
- if (!section_is_gnu)
- {
- unsigned int bytes_read;
-
- /* This reads the constant, but since we don't recognize
- any vendor extensions, we ignore it. */
- read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
- mac_ptr += bytes_read;
- read_direct_string (abfd, mac_ptr, &bytes_read);
- mac_ptr += bytes_read;
-
- /* We don't recognize any vendor extensions. */
- break;
- }
- /* FALLTHROUGH */
-
- default:
- mac_ptr = skip_unknown_opcode (macinfo_type, opcode_definitions,
- mac_ptr, mac_end, abfd, offset_size,
- section);
- if (mac_ptr == NULL)
- return;
- break;
- }
- DIAGNOSTIC_POP
- } while (macinfo_type != 0);
-}
-
-static void
-dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset,
- int section_is_gnu)
-{
- struct dwarf2_per_objfile *dwarf2_per_objfile
- = cu->per_cu->dwarf2_per_objfile;
- struct objfile *objfile = dwarf2_per_objfile->objfile;
- struct line_header *lh = cu->line_header;
- bfd *abfd;
- const gdb_byte *mac_ptr, *mac_end;
- struct macro_source_file *current_file = 0;
- enum dwarf_macro_record_type macinfo_type;
- unsigned int offset_size = cu->header.offset_size;
- const gdb_byte *opcode_definitions[256];
- void **slot;
- struct dwarf2_section_info *section;
- const char *section_name;
-
- if (cu->dwo_unit != NULL)
+ if (cu->dwo_unit != nullptr)
{
if (section_is_gnu)
{
}
section->read (objfile);
- if (section->buffer == NULL)
+ if (section->buffer == nullptr)
{
complaint (_("missing %s section"), section_name);
return;
}
- abfd = section->get_bfd_owner ();
-
- /* First pass: Find the name of the base filename.
- This filename is needed in order to process all macros whose definition
- (or undefinition) comes from the command line. These macros are defined
- before the first DW_MACINFO_start_file entry, and yet still need to be
- associated to the base file.
-
- To determine the base file name, we scan the macro definitions until we
- reach the first DW_MACINFO_start_file entry. We then initialize
- CURRENT_FILE accordingly so that any macro definition found before the
- first DW_MACINFO_start_file can still be associated to the base file. */
-
- mac_ptr = section->buffer + offset;
- mac_end = section->buffer + section->size;
-
- mac_ptr = dwarf_parse_macro_header (opcode_definitions, abfd, mac_ptr,
- &offset_size, section_is_gnu);
- if (mac_ptr == NULL)
- {
- /* We already issued a complaint. */
- return;
- }
-
- do
- {
- /* Do we at least have room for a macinfo type byte? */
- if (mac_ptr >= mac_end)
- {
- /* Complaint is printed during the second pass as GDB will probably
- stop the first pass earlier upon finding
- DW_MACINFO_start_file. */
- break;
- }
-
- macinfo_type = (enum dwarf_macro_record_type) read_1_byte (abfd, mac_ptr);
- mac_ptr++;
-
- /* Note that we rely on the fact that the corresponding GNU and
- DWARF constants are the same. */
- DIAGNOSTIC_PUSH
- DIAGNOSTIC_IGNORE_SWITCH_DIFFERENT_ENUM_TYPES
- switch (macinfo_type)
- {
- /* A zero macinfo type indicates the end of the macro
- information. */
- case 0:
- break;
-
- case DW_MACRO_define:
- case DW_MACRO_undef:
- /* Only skip the data by MAC_PTR. */
- {
- unsigned int bytes_read;
-
- read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
- mac_ptr += bytes_read;
- read_direct_string (abfd, mac_ptr, &bytes_read);
- mac_ptr += bytes_read;
- }
- break;
-
- case DW_MACRO_start_file:
- {
- unsigned int bytes_read;
- int line, file;
-
- line = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
- mac_ptr += bytes_read;
- file = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
- mac_ptr += bytes_read;
-
- current_file = macro_start_file (cu, file, line, current_file, lh);
- }
- break;
-
- case DW_MACRO_end_file:
- /* No data to skip by MAC_PTR. */
- break;
-
- case DW_MACRO_define_strp:
- case DW_MACRO_undef_strp:
- case DW_MACRO_define_sup:
- case DW_MACRO_undef_sup:
- {
- unsigned int bytes_read;
-
- read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
- mac_ptr += bytes_read;
- mac_ptr += offset_size;
- }
- break;
-
- case DW_MACRO_import:
- case DW_MACRO_import_sup:
- /* Note that, according to the spec, a transparent include
- chain cannot call DW_MACRO_start_file. So, we can just
- skip this opcode. */
- mac_ptr += offset_size;
- break;
-
- case DW_MACINFO_vendor_ext:
- /* Only skip the data by MAC_PTR. */
- if (!section_is_gnu)
- {
- unsigned int bytes_read;
-
- read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
- mac_ptr += bytes_read;
- read_direct_string (abfd, mac_ptr, &bytes_read);
- mac_ptr += bytes_read;
- }
- /* FALLTHROUGH */
- default:
- mac_ptr = skip_unknown_opcode (macinfo_type, opcode_definitions,
- mac_ptr, mac_end, abfd, offset_size,
- section);
- if (mac_ptr == NULL)
- return;
- break;
- }
- DIAGNOSTIC_POP
- } while (macinfo_type != 0 && current_file == NULL);
-
- /* Second pass: Process all entries.
-
- Use the AT_COMMAND_LINE flag to determine whether we are still processing
- command-line macro definitions/undefinitions. This flag is unset when we
- reach the first DW_MACINFO_start_file entry. */
+ buildsym_compunit *builder = cu->get_builder ();
- htab_up include_hash (htab_create_alloc (1, htab_hash_pointer,
- htab_eq_pointer,
- NULL, xcalloc, xfree));
- mac_ptr = section->buffer + offset;
- slot = htab_find_slot (include_hash.get (), mac_ptr, INSERT);
- *slot = (void *) mac_ptr;
- dwarf_decode_macro_bytes (cu, abfd, mac_ptr, mac_end,
- current_file, lh, section,
- section_is_gnu, 0, offset_size,
- include_hash.get ());
+ dwarf_decode_macros (dwarf2_per_objfile, builder, section, lh,
+ offset_size, offset, section_is_gnu);
}
/* Return the .debug_loc section to use for CU.
don't run off the edge of the section. */
baton->size = section->size - DW_UNSND (attr);
baton->data = section->buffer + DW_UNSND (attr);
- baton->base_address = cu->base_address;
+ if (cu->base_address.has_value ())
+ baton->base_address = *cu->base_address;
+ else
+ baton->base_address = 0;
baton->from_dwo = cu->dwo_unit != NULL;
}
/* .debug_loc{,.dwo} may not exist at all, or the offset may be outside
the section. If so, fall through to the complaint in the
other branch. */
- && DW_UNSND (attr) < dwarf2_section_size (objfile, section))
+ && DW_UNSND (attr) < section->get_size (objfile))
{
struct dwarf2_loclist_baton *baton;
fill_in_loclist_baton (cu, baton, attr);
- if (cu->base_known == 0)
+ if (!cu->base_address.has_value ())
complaint (_("Location list used without "
"specifying the CU base address."));
return addr_type;
}
-/* Locate the .debug_info compilation unit from CU's objfile which contains
- the DIE at OFFSET. Raises an error on failure. */
+/* A helper function for dwarf2_find_containing_comp_unit that returns
+ the index of the result, and that searches a vector. It will
+ return a result even if the offset in question does not actually
+ occur in any CU. This is separate so that it can be unit
+ tested. */
-static struct dwarf2_per_cu_data *
-dwarf2_find_containing_comp_unit (sect_offset sect_off,
- unsigned int offset_in_dwz,
- struct dwarf2_per_objfile *dwarf2_per_objfile)
+static int
+dwarf2_find_containing_comp_unit
+ (sect_offset sect_off,
+ unsigned int offset_in_dwz,
+ const std::vector<dwarf2_per_cu_data *> &all_comp_units)
{
- struct dwarf2_per_cu_data *this_cu;
int low, high;
low = 0;
- high = dwarf2_per_objfile->all_comp_units.size () - 1;
+ high = all_comp_units.size () - 1;
while (high > low)
{
struct dwarf2_per_cu_data *mid_cu;
int mid = low + (high - low) / 2;
- mid_cu = dwarf2_per_objfile->all_comp_units[mid];
+ mid_cu = all_comp_units[mid];
if (mid_cu->is_dwz > offset_in_dwz
|| (mid_cu->is_dwz == offset_in_dwz
- && mid_cu->sect_off + mid_cu->length >= sect_off))
+ && mid_cu->sect_off + mid_cu->length > sect_off))
high = mid;
else
low = mid + 1;
}
gdb_assert (low == high);
- this_cu = dwarf2_per_objfile->all_comp_units[low];
+ return low;
+}
+
+/* Locate the .debug_info compilation unit from CU's objfile which contains
+ the DIE at OFFSET. Raises an error on failure. */
+
+static struct dwarf2_per_cu_data *
+dwarf2_find_containing_comp_unit (sect_offset sect_off,
+ unsigned int offset_in_dwz,
+ struct dwarf2_per_objfile *dwarf2_per_objfile)
+{
+ int low
+ = dwarf2_find_containing_comp_unit (sect_off, offset_in_dwz,
+ dwarf2_per_objfile->all_comp_units);
+ struct dwarf2_per_cu_data *this_cu
+ = dwarf2_per_objfile->all_comp_units[low];
+
if (this_cu->is_dwz != offset_in_dwz || this_cu->sect_off > sect_off)
{
if (low == 0 || this_cu->is_dwz != offset_in_dwz)
}
}
+#if GDB_SELF_TEST
+
+namespace selftests {
+namespace find_containing_comp_unit {
+
+static void
+run_test ()
+{
+ struct dwarf2_per_cu_data one {};
+ struct dwarf2_per_cu_data two {};
+ struct dwarf2_per_cu_data three {};
+ struct dwarf2_per_cu_data four {};
+
+ one.length = 5;
+ two.sect_off = sect_offset (one.length);
+ two.length = 7;
+
+ three.length = 5;
+ three.is_dwz = 1;
+ four.sect_off = sect_offset (three.length);
+ four.length = 7;
+ four.is_dwz = 1;
+
+ std::vector<dwarf2_per_cu_data *> units;
+ units.push_back (&one);
+ units.push_back (&two);
+ units.push_back (&three);
+ units.push_back (&four);
+
+ int result;
+
+ result = dwarf2_find_containing_comp_unit (sect_offset (0), 0, units);
+ SELF_CHECK (units[result] == &one);
+ result = dwarf2_find_containing_comp_unit (sect_offset (3), 0, units);
+ SELF_CHECK (units[result] == &one);
+ result = dwarf2_find_containing_comp_unit (sect_offset (5), 0, units);
+ SELF_CHECK (units[result] == &two);
+
+ result = dwarf2_find_containing_comp_unit (sect_offset (0), 1, units);
+ SELF_CHECK (units[result] == &three);
+ result = dwarf2_find_containing_comp_unit (sect_offset (3), 1, units);
+ SELF_CHECK (units[result] == &three);
+ result = dwarf2_find_containing_comp_unit (sect_offset (5), 1, units);
+ SELF_CHECK (units[result] == &four);
+}
+
+}
+}
+
+#endif /* GDB_SELF_TEST */
+
/* Initialize dwarf2_cu CU, owned by PER_CU. */
dwarf2_cu::dwarf2_cu (struct dwarf2_per_cu_data *per_cu_)
#if GDB_SELF_TEST
selftests::register_test ("dw2_expand_symtabs_matching",
selftests::dw2_expand_symtabs_matching::run_test);
+ selftests::register_test ("dwarf2_find_containing_comp_unit",
+ selftests::find_containing_comp_unit::run_test);
#endif
}